| 50 | | def _checkClientHandshake(self): |
| 51 | | """ |
| 52 | | Verify client handshake, closing the connection in case of problem. |
| | 60 | def _handshake75(self): |
| | 61 | origin = self.requestHeaders.getRawHeaders("Origin", [None])[0] |
| | 62 | host = self.requestHeaders.getRawHeaders("Host", [None])[0] |
| | 63 | if not origin or not host: |
| | 64 | return |
| | 65 | |
| | 66 | protocol = self.requestHeaders.getRawHeaders("WebSocket-Protocol", [None])[0] |
| | 67 | if protocol and protocol not in self.site.supportedProtocols: |
| | 68 | return |
| | 69 | |
| | 70 | if self.isSecure(): |
| | 71 | scheme = "wss" |
| | 72 | else: |
| | 73 | scheme = "ws" |
| | 74 | location = "%s://%s%s" % (scheme, host, self.uri) |
| | 75 | handshake = [ |
| | 76 | "HTTP/1.1 101 Web Socket Protocol Handshake", |
| | 77 | "Upgrade: WebSocket", |
| | 78 | "Connection: Upgrade", |
| | 79 | "WebSocket-Origin: %s" % origin, |
| | 80 | "WebSocket-Location: %s" % location, |
| | 81 | ] |
| | 82 | if protocol is not None: |
| | 83 | handshake.append("WebSocket-Protocol: %s" % protocol) |
| | 84 | |
| | 85 | return handshake |
| | 86 | |
| | 87 | def _handshake76(self): |
| | 88 | origin = self.requestHeaders.getRawHeaders("Origin", [None])[0] |
| | 89 | host = self.requestHeaders.getRawHeaders("Host", [None])[0] |
| | 90 | if not origin or not host: |
| | 91 | return None, None |
| | 92 | |
| | 93 | protocol = self.requestHeaders.getRawHeaders("Sec-WebSocket-Protocol", [None])[0] |
| | 94 | if protocol and protocol not in self.site.supportedProtocols: |
| | 95 | return None, None |
| 54 | | @return: C{None} if a problem was detected, or a tuple of I{Origin} |
| 55 | | header, I{Host} header, I{WebSocket-Protocol} header, and |
| 56 | | C{WebSocketHandler} instance. The I{WebSocket-Protocol} header will |
| 57 | | be C{None} if not specified by the client. |
| 58 | | """ |
| 59 | | def finish(): |
| 60 | | self.channel.transport.loseConnection() |
| 61 | | if self.queued: |
| 62 | | return finish() |
| 63 | | originHeaders = self.requestHeaders.getRawHeaders("Origin", []) |
| 64 | | if len(originHeaders) != 1: |
| 65 | | return finish() |
| 66 | | hostHeaders = self.requestHeaders.getRawHeaders("Host", []) |
| 67 | | if len(hostHeaders) != 1: |
| 68 | | return finish() |
| 69 | | |
| 70 | | handlerFactory = self.site.handlers.get(self.uri) |
| 71 | | if not handlerFactory: |
| 72 | | return finish() |
| 73 | | transport = WebSocketTransport(self) |
| 74 | | handler = handlerFactory(transport) |
| 75 | | transport._attachHandler(handler) |
| 76 | | |
| 77 | | protocolHeaders = self.requestHeaders.getRawHeaders( |
| 78 | | "WebSocket-Protocol", []) |
| 79 | | if len(protocolHeaders) not in (0, 1): |
| 80 | | return finish() |
| 81 | | if protocolHeaders: |
| 82 | | if protocolHeaders[0] not in self.site.supportedProtocols: |
| 83 | | return finish() |
| 84 | | protocolHeader = protocolHeaders[0] |
| | 97 | if self.isSecure(): |
| | 98 | scheme = "wss" |
| 86 | | protocolHeader = None |
| 87 | | return originHeaders[0], hostHeaders[0], protocolHeader, handler |
| | 100 | scheme = "ws" |
| | 101 | location = "%s://%s%s" % (scheme, host, self.uri) |
| | 102 | handshake = [ |
| | 103 | "HTTP/1.1 101 Web Socket Protocol Handshake", |
| | 104 | "Upgrade: WebSocket", |
| | 105 | "Connection: Upgrade", |
| | 106 | "Sec-WebSocket-Origin: %s" % origin, |
| | 107 | "Sec-WebSocket-Location: %s" % location, |
| | 108 | ] |
| | 109 | if protocol is not None: |
| | 110 | handshake.append("Sec-WebSocket-Protocol: %s" % protocol) |
| | 111 | |
| | 112 | self.channel.setRawMode() |
| | 113 | |
| | 114 | # Refer to 5.2 4-9 of the draft 76 |
| | 115 | key1 = self.requestHeaders.getRawHeaders('Sec-WebSocket-Key1', [None])[0] |
| | 116 | key2 = self.requestHeaders.getRawHeaders('Sec-WebSocket-Key2', [None])[0] |
| | 117 | key3 = self.content.getvalue() |
| | 118 | |
| | 119 | def extract_nums(s): return int(''.join(re.findall(r'[0-9]', s))) |
| | 120 | def count_spaces(s): return len(re.findall(r' ', s)) |
| | 121 | part1 = extract_nums(key1) / count_spaces(key1) |
| | 122 | part2 = extract_nums(key2) / count_spaces(key2) |
| | 123 | challenge = hashlib.md5(struct.pack('>ii8s', part1, part2, key3)).digest() |
| | 124 | |
| | 125 | return handshake, challenge |
| 101 | | originHeader, hostHeader, protocolHeader, handler = check |
| 102 | | self.startedWriting = True |
| 103 | | handshake = [ |
| 104 | | "HTTP/1.1 101 Web Socket Protocol Handshake", |
| 105 | | "Upgrade: WebSocket", |
| 106 | | "Connection: Upgrade"] |
| 107 | | handshake.append("WebSocket-Origin: %s" % (originHeader)) |
| 108 | | if self.isSecure(): |
| 109 | | scheme = "wss" |
| | 144 | |
| | 145 | if self.requestHeaders.getRawHeaders("Sec-WebSocket-Key1", [None])[0]: |
| | 146 | handshake, challenge_response = self._handshake76() |