def __init__(self, uri=None, headers_in={}, connection=None, method='GET', protocol='HTTP/1.1', is_https=False): """Construct an instance. Arguments: uri: URI of the request. headers_in: Request headers. connection: Connection used for the request. method: request method. is_https: Whether this request is over SSL. See the document of mod_python Request for details. """ self.uri = uri self.unparsed_uri = uri self.connection = connection self.method = method self.protocol = protocol self.headers_in = MockTable(headers_in) # self.is_https_ needs to be accessible from tests. To avoid name # conflict with self.is_https(), it is named as such. self.is_https_ = is_https self.ws_stream = StreamHixie75(self, True) self.ws_close_code = None self.ws_close_reason = None self.ws_version = common.VERSION_HYBI00 self.ws_deflate = False
def _set_protocol_version(self): # |Sec-WebSocket-Draft| draft = self._request.headers_in.get(common.SEC_WEBSOCKET_DRAFT_HEADER) if draft is not None and draft != '0': raise HandshakeException( 'Illegal value for %s: %s' % (common.SEC_WEBSOCKET_DRAFT_HEADER, draft)) self._logger.debug('IETF HyBi 00 protocol') self._request.ws_version = common.VERSION_HYBI00 self._request.ws_stream = StreamHixie75(self._request, True)
def _create_blocking_request_hixie75(): req = mock.MockRequest(connection=mock.MockBlockingConn()) req.ws_stream = StreamHixie75(req) return req
def _create_request_hixie75(read_data=''): req = mock.MockRequest(connection=mock.MockConn(read_data)) req.ws_stream = StreamHixie75(req) return req
def run(self): """Run the client. Shake hands and then repeat sending message and receiving its echo. """ self._socket = socket.socket() self._socket.settimeout(self._options.socket_timeout) try: self._socket.connect((self._options.server_host, self._options.server_port)) if self._options.use_tls: self._socket = _TLSSocket( self._socket, self._options.tls_module, self._options.tls_version, self._options.disable_tls_compression) version = self._options.protocol_version if (version == _PROTOCOL_VERSION_HYBI08 or version == _PROTOCOL_VERSION_HYBI13): self._handshake = ClientHandshakeProcessor( self._socket, self._options) elif version == _PROTOCOL_VERSION_HYBI00: self._handshake = ClientHandshakeProcessorHybi00( self._socket, self._options) else: raise ValueError( 'Invalid --protocol-version flag: %r' % version) self._handshake.handshake() self._logger.info('Connection established') request = ClientRequest(self._socket) version_map = { _PROTOCOL_VERSION_HYBI08: common.VERSION_HYBI08, _PROTOCOL_VERSION_HYBI13: common.VERSION_HYBI13, _PROTOCOL_VERSION_HYBI00: common.VERSION_HYBI00} request.ws_version = version_map[version] if (version == _PROTOCOL_VERSION_HYBI08 or version == _PROTOCOL_VERSION_HYBI13): stream_option = StreamOptions() stream_option.mask_send = True stream_option.unmask_receive = False if self._options.deflate_frame is not False: processor = self._options.deflate_frame processor.setup_stream_options(stream_option) if self._options.use_permessage_deflate is not False: framer = self._options.use_permessage_deflate framer.setup_stream_options(stream_option) self._stream = Stream(request, stream_option) elif version == _PROTOCOL_VERSION_HYBI00: self._stream = StreamHixie75(request, True) for line in self._options.message.split(','): self._stream.send_message(line) if self._options.verbose: print('Send: %s' % line) try: received = self._stream.receive_message() if self._options.verbose: print('Recv: %s' % received) except Exception, e: if self._options.verbose: print('Error: %s' % e) raise self._do_closing_handshake()
class Handshaker(object): """This class performs WebSocket handshake.""" def __init__(self, request, dispatcher): """Construct an instance. Args: request: mod_python request. dispatcher: Dispatcher (dispatch.Dispatcher). Handshaker will add attributes such as ws_resource in performing handshake. """ self._logger = util.get_class_logger(self) self._request = request self._dispatcher = dispatcher def do_handshake(self): """Perform WebSocket Handshake. On _request, we set ws_resource, ws_protocol, ws_location, ws_origin, ws_challenge, ws_challenge_md5: WebSocket handshake information. ws_stream: Frame generation/parsing class. ws_version: Protocol version. """ # 5.1 Reading the client's opening handshake. # dispatcher sets it in self._request. check_header_lines(self._request, _MANDATORY_HEADERS) self._set_resource() self._set_subprotocol() self._set_location() self._set_origin() self._set_challenge_response() self._set_protocol_version() self._dispatcher.do_extra_handshake(self._request) self._send_handshake() self._logger.debug('Sent opening handshake response') def _set_resource(self): self._request.ws_resource = self._request.uri def _set_subprotocol(self): # |Sec-WebSocket-Protocol| subprotocol = self._request.headers_in.get( common.SEC_WEBSOCKET_PROTOCOL_HEADER) if subprotocol is not None: validate_subprotocol(subprotocol) self._request.ws_protocol = subprotocol def _set_location(self): # |Host| host = self._request.headers_in.get(common.HOST_HEADER) if host is not None: self._request.ws_location = build_location(self._request) # TODO(ukai): check host is this host. def _set_origin(self): # |Origin| origin = self._request.headers_in['Origin'] if origin is not None: self._request.ws_origin = origin def _set_protocol_version(self): # |Sec-WebSocket-Draft| draft = self._request.headers_in.get('Sec-WebSocket-Draft') if draft is not None: try: draft_int = int(draft) # Draft value 2 is used by HyBi 02 and 03 which we no longer # support. draft >= 3 and <= 1 are never defined in the spec. # 0 might be used to mean HyBi 00 by somebody. 1 might be used # to mean HyBi 01 by somebody but we no longer support it. if draft_int == 1 or draft_int == 2: raise HandshakeError('HyBi 01-03 are not supported') elif draft_int != 0: raise ValueError except ValueError, e: raise HandshakeError( 'Illegal value for Sec-WebSocket-Draft: %s' % draft) self._logger.debug('IETF HyBi 00 protocol') self._request.ws_version = common.VERSION_HYBI00 self._request.ws_stream = StreamHixie75(self._request, True)
def test_payload_length(self): for length, bytes in ((0, '\x00'), (0x7f, '\x7f'), (0x80, '\x81\x00'), (0x1234, '\x80\xa4\x34')): test_stream = StreamHixie75(_create_request_hixie75(bytes)) self.assertEqual(length, test_stream._read_payload_length_hixie75())
def _set_protocol_version(self): self._logger.debug('IETF Hixie 75 protocol') self._request.ws_version = common.VERSION_HIXIE75 self._request.ws_stream = StreamHixie75(self._request)