class WebSocketProtocol(HttpProtocol): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.websocket = None def connection_timeout(self): # timeouts make no sense for websocket routes if self.websocket is None: super().connection_timeout() def connection_lost(self, exc): if self.websocket is not None: self.websocket.connection_lost(exc) super().connection_lost(exc) def data_received(self, data): if self.websocket is not None: # pass the data to the websocket protocol self.websocket.data_received(data) else: try: super().data_received(data) except HttpParserUpgrade: # this is okay, it just indicates we've got an upgrade request pass def write_response(self, response): if self.websocket is not None: # websocket requests do not write a response self.transport.close() else: super().write_response(response) async def websocket_handshake(self, request): # let the websockets package do the handshake with the client headers = [] def get_header(k): return request.headers.get(k, '') def set_header(k, v): headers.append((k, v)) try: key = handshake.check_request(get_header) handshake.build_response(set_header, key) except InvalidHandshake: raise InvalidUsage('Invalid websocket request') # write the 101 response back to the client rv = b'HTTP/1.1 101 Switching Protocols\r\n' for k, v in headers: rv += k.encode('utf-8') + b': ' + v.encode('utf-8') + b'\r\n' rv += b'\r\n' request.transport.write(rv) # hook up the websocket protocol self.websocket = WebSocketCommonProtocol() self.websocket.connection_made(request.transport) return self.websocket
def switch_protocols(): ws_protocol = WebSocketCommonProtocol() transport._protocol = ws_protocol ws_protocol.connection_made(transport) # Ensure aiohttp doesn't interfere. http_protocol.transport = None asyncio. async (run_ws_handler(ws_protocol))
class WebSocketProtocol(HttpProtocol): def request_timeout_callback(self): if self.websocket is None: super().request_timeout_callback() def response_timeout_callback(self): if self.websocket is None: super().response_timeout_callback() def timeout_keep_alive_handler(self): if self.websocket is None: super().timeout_keep_alive_handler() def connection_lost(self, exc): if self.websocket is not None: self.websocket.connection_lost(exc) super().connection_lost(exc) def data_received(self, data): if self.websocket is not None: self.websocket.data_received(data) else: try: super().data_received(data) except httptools.HttpParserUpgrade: pass def write_response(self, response): if self.websocket is not None: self.transport.close() else: super().on_response(response) async def websocket_handshake(self, request, subprotocols=None): headers = {} try: key = handshake.check_request(request.headers) handshake.build_response(headers, key) except InvalidHandshake: msg = "Invalid websocket request received." if self.debug: msg += "\n" + traceback.format_exc() self.logger.error(msg) self.on_response(msg) raise RuntimeError(msg) subprotocol = None if subprotocols and "Sec-Websocket-Protocol" in request.headers: # select a subprotocol client_subprotocols = [ p.strip() for p in request.headers["Sec-Websocket-Protocol"].split(",") ] for p in client_subprotocols: if p in subprotocols: subprotocol = p headers["Sec-Websocket-Protocol"] = subprotocol break # write the 101 response back to the client rv = b"HTTP/1.1 101 Switching Protocols\r\n" for k, v in headers.items(): rv += k.encode("utf-8") + b": " + v.encode("utf-8") + b"\r\n" rv += b"\r\n" request.transport.write(rv) # hook up the websocket protocol self.websocket = WebSocketCommonProtocol( timeout=self.config.ws_timeout, max_size=self.config.ws_max_size, max_queue=self.config.ws_max_queue, read_limit=self.config.ws_read_limit, write_limit=self.config.ws_write_limit, ) self.websocket.subprotocol = subprotocol self.websocket.connection_made(request.transport) self.websocket.connection_open() return self.websocket
class WebSocketProtocol(HttpProtocol): def __init__( self, *args, websocket_timeout=10, websocket_max_size=None, websocket_max_queue=None, websocket_read_limit=2 ** 16, websocket_write_limit=2 ** 16, **kwargs ): super().__init__(*args, **kwargs) self.websocket = None self.websocket_timeout = websocket_timeout self.websocket_max_size = websocket_max_size self.websocket_max_queue = websocket_max_queue self.websocket_read_limit = websocket_read_limit self.websocket_write_limit = websocket_write_limit # timeouts make no sense for websocket routes def request_timeout_callback(self): if self.websocket is None: super().request_timeout_callback() def response_timeout_callback(self): if self.websocket is None: super().response_timeout_callback() def keep_alive_timeout_callback(self): if self.websocket is None: super().keep_alive_timeout_callback() def connection_lost(self, exc): if self.websocket is not None: self.websocket.connection_lost(exc) super().connection_lost(exc) def data_received(self, data): if self.websocket is not None: # pass the data to the websocket protocol self.websocket.data_received(data) else: try: super().data_received(data) except HttpParserUpgrade: # this is okay, it just indicates we've got an upgrade request pass def write_response(self, response): if self.websocket is not None: # websocket requests do not write a response self.transport.close() else: super().write_response(response) async def websocket_handshake(self, request, subprotocols=None): # let the websockets package do the handshake with the client headers = {} try: key = handshake.check_request(request.headers) handshake.build_response(headers, key) except InvalidHandshake: raise InvalidUsage("Invalid websocket request") subprotocol = None if subprotocols and "Sec-Websocket-Protocol" in request.headers: # select a subprotocol client_subprotocols = [ p.strip() for p in request.headers["Sec-Websocket-Protocol"].split(",") ] for p in client_subprotocols: if p in subprotocols: subprotocol = p headers["Sec-Websocket-Protocol"] = subprotocol break # write the 101 response back to the client rv = b"HTTP/1.1 101 Switching Protocols\r\n" for k, v in headers.items(): rv += k.encode("utf-8") + b": " + v.encode("utf-8") + b"\r\n" rv += b"\r\n" request.transport.write(rv) # hook up the websocket protocol self.websocket = WebSocketCommonProtocol( timeout=self.websocket_timeout, max_size=self.websocket_max_size, max_queue=self.websocket_max_queue, read_limit=self.websocket_read_limit, write_limit=self.websocket_write_limit, ) self.websocket.subprotocol = subprotocol self.websocket.connection_made(request.transport) self.websocket.connection_open() return self.websocket
class WebSocketProtocol(HttpProtocol): def __init__( self, *args, websocket_timeout=10, websocket_max_size=None, websocket_max_queue=None, websocket_read_limit=2 ** 16, websocket_write_limit=2 ** 16, **kwargs ): super().__init__(*args, **kwargs) self.websocket = None # self.app = None self.websocket_timeout = websocket_timeout self.websocket_max_size = websocket_max_size self.websocket_max_queue = websocket_max_queue self.websocket_read_limit = websocket_read_limit self.websocket_write_limit = websocket_write_limit # timeouts make no sense for websocket routes def request_timeout_callback(self): if self.websocket is None: super().request_timeout_callback() def response_timeout_callback(self): if self.websocket is None: super().response_timeout_callback() def keep_alive_timeout_callback(self): if self.websocket is None: super().keep_alive_timeout_callback() def connection_lost(self, exc): if self.websocket is not None: self.websocket.connection_lost(exc) super().connection_lost(exc) def data_received(self, data): if self.websocket is not None: # pass the data to the websocket protocol self.websocket.data_received(data) else: try: super().data_received(data) except HttpParserUpgrade: # this is okay, it just indicates we've got an upgrade request pass def write_response(self, response): if self.websocket is not None: # websocket requests do not write a response self.transport.close() else: super().write_response(response) async def websocket_handshake(self, request, subprotocols=None): # let the websockets package do the handshake with the client headers = {} try: key = handshake.check_request(request.headers) handshake.build_response(headers, key) except InvalidHandshake: raise InvalidUsage("Invalid websocket request") subprotocol = None if subprotocols and "Sec-Websocket-Protocol" in request.headers: # select a subprotocol client_subprotocols = [ p.strip() for p in request.headers["Sec-Websocket-Protocol"].split(",") ] for p in client_subprotocols: if p in subprotocols: subprotocol = p headers["Sec-Websocket-Protocol"] = subprotocol break # write the 101 response back to the client rv = b"HTTP/1.1 101 Switching Protocols\r\n" for k, v in headers.items(): rv += k.encode("utf-8") + b": " + v.encode("utf-8") + b"\r\n" rv += b"\r\n" request.transport.write(rv) # hook up the websocket protocol self.websocket = WebSocketCommonProtocol( timeout=self.websocket_timeout, max_size=self.websocket_max_size, max_queue=self.websocket_max_queue, read_limit=self.websocket_read_limit, write_limit=self.websocket_write_limit, ) # Following two lines are required for websockets 8.x self.websocket.is_client = False self.websocket.side = "server" self.websocket.subprotocol = subprotocol self.websocket.connection_made(request.transport) self.websocket.connection_open() return self.websocket
class WebSocketProtocol(HttpProtocol): def __init__(self, *args, websocket_max_size=None, websocket_max_queue=None, **kwargs): super().__init__(*args, **kwargs) self.websocket = None self.websocket_max_size = websocket_max_size self.websocket_max_queue = websocket_max_queue def connection_timeout(self): # timeouts make no sense for websocket routes if self.websocket is None: super().connection_timeout() def connection_lost(self, exc): if self.websocket is not None: self.websocket.connection_lost(exc) super().connection_lost(exc) def data_received(self, data): if self.websocket is not None: # pass the data to the websocket protocol self.websocket.data_received(data) else: try: super().data_received(data) except HttpParserUpgrade: # this is okay, it just indicates we've got an upgrade request pass def write_response(self, response): if self.websocket is not None: # websocket requests do not write a response self.transport.close() else: super().write_response(response) async def websocket_handshake(self, request, subprotocols=None): # let the websockets package do the handshake with the client headers = [] def get_header(k): return request.headers.get(k, '') def set_header(k, v): headers.append((k, v)) try: key = handshake.check_request(get_header) handshake.build_response(set_header, key) except InvalidHandshake: raise InvalidUsage('Invalid websocket request') subprotocol = None if subprotocols and 'Sec-Websocket-Protocol' in request.headers: # select a subprotocol client_subprotocols = [p.strip() for p in request.headers[ 'Sec-Websocket-Protocol'].split(',')] for p in client_subprotocols: if p in subprotocols: subprotocol = p set_header('Sec-Websocket-Protocol', subprotocol) break # write the 101 response back to the client rv = b'HTTP/1.1 101 Switching Protocols\r\n' for k, v in headers: rv += k.encode('utf-8') + b': ' + v.encode('utf-8') + b'\r\n' rv += b'\r\n' request.transport.write(rv) # hook up the websocket protocol self.websocket = WebSocketCommonProtocol( max_size=self.websocket_max_size, max_queue=self.websocket_max_queue ) self.websocket.subprotocol = subprotocol self.websocket.connection_made(request.transport) return self.websocket
class WebSocketProtocol(HttpProtocol): def __init__(self, *args, websocket_max_size=None, websocket_max_queue=None, **kwargs): super().__init__(*args, **kwargs) self.websocket = None self.websocket_max_size = websocket_max_size self.websocket_max_queue = websocket_max_queue # timeouts make no sense for websocket routes def request_timeout_callback(self): if self.websocket is None: super().request_timeout_callback() def response_timeout_callback(self): if self.websocket is None: super().response_timeout_callback() def keep_alive_timeout_callback(self): if self.websocket is None: super().keep_alive_timeout_callback() def connection_lost(self, exc): if self.websocket is not None: self.websocket.connection_lost(exc) super().connection_lost(exc) def data_received(self, data): if self.websocket is not None: # pass the data to the websocket protocol self.websocket.data_received(data) else: try: super().data_received(data) except HttpParserUpgrade: # this is okay, it just indicates we've got an upgrade request pass def write_response(self, response): if self.websocket is not None: # websocket requests do not write a response self.transport.close() else: super().write_response(response) async def websocket_handshake(self, request, subprotocols=None): # let the websockets package do the handshake with the client headers = [] def get_header(k): return request.headers.get(k, '') def set_header(k, v): headers.append((k, v)) try: key = handshake.check_request(get_header) handshake.build_response(set_header, key) except InvalidHandshake: raise InvalidUsage('Invalid websocket request') subprotocol = None if subprotocols and 'Sec-Websocket-Protocol' in request.headers: # select a subprotocol client_subprotocols = [ p.strip() for p in request.headers['Sec-Websocket-Protocol'].split(',') ] for p in client_subprotocols: if p in subprotocols: subprotocol = p set_header('Sec-Websocket-Protocol', subprotocol) break # write the 101 response back to the client rv = b'HTTP/1.1 101 Switching Protocols\r\n' for k, v in headers: rv += k.encode('utf-8') + b': ' + v.encode('utf-8') + b'\r\n' rv += b'\r\n' request.transport.write(rv) # hook up the websocket protocol self.websocket = WebSocketCommonProtocol( max_size=self.websocket_max_size, max_queue=self.websocket_max_queue) self.websocket.subprotocol = subprotocol self.websocket.connection_made(request.transport) self.websocket.connection_open() return self.websocket
class WebSocketProtocol(asyncio.Protocol): def __init__(self, params: panic_datatypes.ServerParams): self.enabled = False self.params = params self.websocket = None self.transport = None self.timeout = params.request_timeout or 10 self.max_size = 2 ** 20 self.max_queue = 2 ** 5 self.read_limit = 2 ** 16 self.write_limit = 2 ** 16 self.url = None self.connections = params.connections self.request = None self.headers = panic_datatypes.HTTPHeaders() self.parser = HttpRequestParser(self) self._last_request_time = None self._identity = uuid.uuid4() def connection_made(self, transport): self.connections.add(self) self._timeout_handler = self.params.loop.call_later(self.timeout, self.connection_timeout) self.transport = transport self._last_request_time = datetime.datetime.utcnow() def connection_lost(self, exc): self.connections.discard(self) self._timeout_handler.cancel() self.cleanup() def cleanup(self): self.websocket = None self.transport = None self.timeout = 10 self.max_size = 1 self.max_queue = 1 self.read_limit = 2 ** 16 self.write_limit = 2 ** 16 self.enabled = False self.url = None logger.warn('handle connections') self.connections = None self.request = None self.headers = None self.parser = None self._last_request_time = None self._request_handler_task = None def connection_timeout(self): time_elapsed = datetime.datetime.utcnow() - self._last_request_time seconds_elapsed = round(time_elapsed.seconds + float('0.%d' % time_elapsed.microseconds)) if seconds_elapsed <= self.timeout: logger.info('Handler Timed out for WebSocket/Channel') #import ipdb; ipdb.set_trace() pass #if self._request_handler_task: # self._request_handler_task.cancel() #exception = panic_exceptions.RequestTimeout('Request Timeout') #self.write_error(exception) else: time_left = self.timeout - seconds_elapsed self._timeout_handler = self.params.loop.call_later(time_left, self.connection_timeout) def data_received(self, data): try: if self.enabled: self.websocket.data_received(data) else: self.parser.feed_data(data) except HttpParserError as err: logger.debug(err) import ipdb; ipdb.set_trace() exception = panic_exceptions.InvalidUsage('Bad Request') self.write_error(exception) except HttpParserUpgrade as err: logger.debug(err) self.enabled = True response = panic_response.Response(b'') try: key = handshake.check_request(lambda x: self.headers.get(x).value) handshake.build_response(response.assimilate, key) except InvalidHandshake: exception = panic_exceptions.InvalidUsage('Invalid websocket request') self.write_error(exception) else: self.transport.write(response.channel('1.1')) self.websocket = WebSocketCommonProtocol( timeout=self.timeout, max_size=self.max_size, max_queue=self.max_queue, read_limit=self.read_limit, write_limit=self.write_limit) self.websocket.subprotocol = None #subprotocol self.websocket.connection_made(self.transport) self.websocket.connection_open() self._request_handler_task = self.params.loop.create_task( self.params.request_handler(self.request, self.websocket, self.transport)) def on_url(self, url): self.url = url def on_message_complete(self): pass #self._request_handler = self.paramsself.params #self._request_handler_task = self.params.loop.create_task( # self.params.request_handler(self.request, self.write_response)) def on_header(self, name, value): self.headers.append(name.decode(), value.decode('utf-8')) def on_headers_complete(self): remote_addr = self.transport.get_extra_info('peername') if remote_addr: self.headers.append(remote_addr[0], str(remote_addr[1])) self.request = panic_request.Request( url = self.url, headers = self.headers, version = self.parser.get_http_version(), method = panic_datatypes.HTTPMethod.channel ) def write_response(self, response): self.transport.close() def request_timeout_callback(self): if self.websocket is None: return super(WebSocketProtocol, self).request_timeout_callback() def write_error(self, exception): try: response = self.params.error_handler(self.request, exception) version = self.request.version if self.request else '1.1' self.transport.write(response.output(float(version))) self.transport.close() except Exception as err: # logger.exception(err) import traceback traceback.print_stack() import ipdb;ipdb.set_trace() self.signal.stopped import sys; sys.exit(1) self.bail_out("Writing error failed, connection closed {}".format(e))