def _send_handshake(self, accept): response = [] response.append('HTTP/1.1 101 Switching Protocols\r\n') response.append(format_header( common.UPGRADE_HEADER, common.WEBSOCKET_UPGRADE_TYPE)) response.append(format_header( common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE)) response.append(format_header( common.SEC_WEBSOCKET_ACCEPT_HEADER, accept)) if self._request.ws_protocol is not None: response.append(format_header( common.SEC_WEBSOCKET_PROTOCOL_HEADER, self._request.ws_protocol)) if (self._request.ws_extensions is not None and len(self._request.ws_extensions) != 0): response.append(format_header( common.SEC_WEBSOCKET_EXTENSIONS_HEADER, format_extensions(self._request.ws_extensions))) response.append('\r\n') raw_response = ''.join(response) self._request.connection.write(raw_response) self._logger.debug('Sent server\'s opening handshake: %r', raw_response)
def _send_handshake(self, accept): response = [] response.append('HTTP/1.1 101 Switching Protocols\r\n') response.append(format_header( common.UPGRADE_HEADER, common.WEBSOCKET_UPGRADE_TYPE)) response.append(format_header( common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE)) response.append(format_header( common.SEC_WEBSOCKET_ACCEPT_HEADER, accept)) # TODO(tyoshino): Encode value of protocol and extensions if any # special character that we have to encode by some manner. if self._request.ws_protocol is not None: response.append(format_header( common.SEC_WEBSOCKET_PROTOCOL_HEADER, self._request.ws_protocol)) if self._request.ws_extensions is not None: response.append(format_header( common.SEC_WEBSOCKET_EXTENSIONS_HEADER, format_extensions(self._request.ws_extensions))) response.append('\r\n') raw_response = ''.join(response) self._logger.debug('Opening handshake response: %r', raw_response) self._request.connection.write(raw_response)
def _send_handshake(self, accept): response = [] response.append('HTTP/1.1 101 Switching Protocols\r\n') response.append( format_header(common.UPGRADE_HEADER, common.WEBSOCKET_UPGRADE_TYPE)) response.append( format_header(common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE)) response.append( format_header(common.SEC_WEBSOCKET_ACCEPT_HEADER, accept)) if self._request.ws_protocol is not None: response.append( format_header(common.SEC_WEBSOCKET_PROTOCOL_HEADER, self._request.ws_protocol)) if (self._request.ws_extensions is not None and len(self._request.ws_extensions) != 0): response.append( format_header(common.SEC_WEBSOCKET_EXTENSIONS_HEADER, format_extensions(self._request.ws_extensions))) # MOZILLA: Add HSTS header if requested to if self._request.sts is not None: response.append( format_header("Strict-Transport-Security", self._request.sts)) # /MOZILLA response.append('\r\n') raw_response = ''.join(response) self._request.connection.write(raw_response) self._logger.debug('Sent server\'s opening handshake: %r', raw_response)
def _send_handshake(self, accept): response = [] response.append('HTTP/1.1 101 Switching Protocols\r\n') response.append( format_header(common.UPGRADE_HEADER, common.WEBSOCKET_UPGRADE_TYPE)) response.append( format_header(common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE)) response.append( format_header(common.SEC_WEBSOCKET_ACCEPT_HEADER, accept)) # TODO(tyoshino): Encode value of protocol and extensions if any # special character that we have to encode by some manner. if self._request.ws_protocol is not None: response.append( format_header(common.SEC_WEBSOCKET_PROTOCOL_HEADER, self._request.ws_protocol)) if self._request.ws_extensions is not None: response.append( format_header(common.SEC_WEBSOCKET_EXTENSIONS_HEADER, format_extensions(self._request.ws_extensions))) response.append('\r\n') raw_response = ''.join(response) self._logger.debug('Opening handshake response: %r', raw_response) self._request.connection.write(raw_response)
def test_format_extensions(self): for formatted_string, definitions in _TEST_TOKEN_EXTENSION_DATA: extensions = [] for definition in definitions: (name, parameters) = definition extension = ExtensionParameter(name) extension._parameters = parameters extensions.append(extension) self.assertEqual( formatted_string, format_extensions(extensions))
def handshake(self): """Performs opening handshake on the specified socket. Raises: ClientHandshakeError: handshake failed. """ request_line = _build_method_line(self._options.resource) self._logger.debug("Client's opening handshake Request-Line: %r", request_line) self._socket.sendall(request_line) fields = [] fields.append(_format_host_header(self._options.server_host, self._options.server_port, self._options.use_tls)) fields.append(_UPGRADE_HEADER) fields.append(_CONNECTION_HEADER) if self._options.origin is not None: if self._options.protocol_version == _PROTOCOL_VERSION_HYBI08: fields.append(_origin_header(common.SEC_WEBSOCKET_ORIGIN_HEADER, self._options.origin)) else: fields.append(_origin_header(common.ORIGIN_HEADER, self._options.origin)) original_key = os.urandom(16) self._key = base64.b64encode(original_key) self._logger.debug("%s: %r (%s)", common.SEC_WEBSOCKET_KEY_HEADER, self._key, util.hexify(original_key)) fields.append("%s: %s\r\n" % (common.SEC_WEBSOCKET_KEY_HEADER, self._key)) if self._options.version_header > 0: fields.append("%s: %d\r\n" % (common.SEC_WEBSOCKET_VERSION_HEADER, self._options.version_header)) elif self._options.protocol_version == _PROTOCOL_VERSION_HYBI08: fields.append("%s: %d\r\n" % (common.SEC_WEBSOCKET_VERSION_HEADER, common.VERSION_HYBI08)) else: fields.append("%s: %d\r\n" % (common.SEC_WEBSOCKET_VERSION_HEADER, common.VERSION_HYBI_LATEST)) extensions_to_request = [] if self._options.deflate_stream: extensions_to_request.append(common.ExtensionParameter(common.DEFLATE_STREAM_EXTENSION)) if self._options.deflate_frame: extensions_to_request.append(common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)) if len(extensions_to_request) != 0: fields.append( "%s: %s\r\n" % (common.SEC_WEBSOCKET_EXTENSIONS_HEADER, format_extensions(extensions_to_request)) ) for field in fields: self._socket.sendall(field) self._socket.sendall("\r\n") self._logger.debug("Sent client's opening handshake headers: %r", fields) self._logger.debug("Start reading Status-Line") status_line = "" while True: ch = _receive_bytes(self._socket, 1) status_line += ch if ch == "\n": break m = re.match("HTTP/\\d+\.\\d+ (\\d\\d\\d) .*\r\n", status_line) if m is None: raise ClientHandshakeError("Wrong status line format: %r" % status_line) status_code = m.group(1) if status_code != "101": self._logger.debug( "Unexpected status code %s with following " "headers: %r", status_code, self._read_fields() ) raise ClientHandshakeError("Expected HTTP status code 101 but found %r" % status_code) self._logger.debug("Received valid Status-Line") self._logger.debug("Start reading headers until we see an empty line") fields = self._read_fields() ch = _receive_bytes(self._socket, 1) if ch != "\n": # 0x0A raise ClientHandshakeError( "Expected LF but found %r while reading value %r for header " "name %r" % (ch, value, name) ) self._logger.debug("Received an empty line") self._logger.debug("Server's opening handshake headers: %r", fields) _validate_mandatory_header(fields, common.UPGRADE_HEADER, common.WEBSOCKET_UPGRADE_TYPE, False) _validate_mandatory_header(fields, common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE, False) accept = _get_mandatory_header(fields, common.SEC_WEBSOCKET_ACCEPT_HEADER) # Validate try: binary_accept = base64.b64decode(accept) except TypeError, e: raise HandshakeError("Illegal value for header %s: %r" % (common.SEC_WEBSOCKET_ACCEPT_HEADER, accept))