def handle_h2_event(self, event: h2.events.Event) -> CommandGenerator[bool]: if isinstance(event, h2.events.RequestReceived): try: host, port, method, scheme, authority, path, headers = parse_h2_request_headers( event.headers) except ValueError as e: yield from self.protocol_error( f"Invalid HTTP/2 request headers: {e}") return True request = http.Request( host=host, port=port, method=method, scheme=scheme, authority=authority, path=path, http_version=b"HTTP/2.0", headers=headers, content=None, trailers=None, timestamp_start=time.time(), timestamp_end=None, ) self.streams[event.stream_id] = StreamState.HEADERS_RECEIVED yield ReceiveHttp( RequestHeaders(event.stream_id, request, end_stream=bool(event.stream_ended))) return False else: return (yield from super().handle_h2_event(event))
def start_handshake(self) -> layer.CommandGenerator[None]: if self.tunnel_connection.tls: # "Secure Web Proxy": We may have negotiated an ALPN when connecting to the upstream proxy. # The semantics are not really clear here, but we make sure that if we negotiated h2, # we act as an h2 client. self.conn.alpn = self.tunnel_connection.alpn if not self.send_connect: return (yield from super().start_handshake()) assert self.conn.address req = http.Request( host=self.conn.address[0], port=self.conn.address[1], method=b"CONNECT", scheme=b"", authority=f"{self.conn.address[0]}:{self.conn.address[1]}".encode( ), path=b"", http_version=b"HTTP/1.1", headers=http.Headers(), content=b"", trailers=None, timestamp_start=time.time(), timestamp_end=time.time(), ) raw = http1.assemble_request(req) yield commands.SendData(self.tunnel_connection, raw)
def twebsocketflow(messages=True, err=None, close_code=None, close_reason='') -> http.HTTPFlow: flow = http.HTTPFlow(tclient_conn(), tserver_conn()) flow.request = http.Request( "example.com", 80, b"GET", b"http", b"example.com", b"/ws", b"HTTP/1.1", headers=http.Headers( connection="upgrade", upgrade="websocket", sec_websocket_version="13", sec_websocket_key="1234", ), content=b'', trailers=None, timestamp_start=946681200, timestamp_end=946681201, ) flow.response = http.Response( b"HTTP/1.1", 101, reason=b"Switching Protocols", headers=http.Headers( connection='upgrade', upgrade='websocket', sec_websocket_accept=b'', ), content=b'', trailers=None, timestamp_start=946681202, timestamp_end=946681203, ) flow.websocket = twebsocket() flow.websocket.close_reason = close_reason if close_code is not None: flow.websocket.close_code = close_code else: if err is True: # ABNORMAL_CLOSURE flow.websocket.close_code = 1006 else: # NORMAL_CLOSURE flow.websocket.close_code = 1000 flow.reply = controller.DummyReply() return flow
def twebsocketflow(messages=True, err=None) -> http.HTTPFlow: flow = http.HTTPFlow(tclient_conn(), tserver_conn()) flow.request = http.Request( "example.com", 80, b"GET", b"http", b"example.com", b"/ws", b"HTTP/1.1", headers=http.Headers( connection="upgrade", upgrade="websocket", sec_websocket_version="13", sec_websocket_key="1234", ), content=b'', trailers=None, timestamp_start=946681200, timestamp_end=946681201, ) flow.response = http.Response( b"HTTP/1.1", 101, reason=b"Switching Protocols", headers=http.Headers( connection='upgrade', upgrade='websocket', sec_websocket_accept=b'', ), content=b'', trailers=None, timestamp_start=946681202, timestamp_end=946681203, ) flow.websocket = websocket.WebSocketData() if messages is True: flow.websocket.messages = [ websocket.WebSocketMessage(Opcode.BINARY, True, b"hello binary", 946681203), websocket.WebSocketMessage(Opcode.TEXT, True, b"hello text", 946681204), websocket.WebSocketMessage(Opcode.TEXT, False, b"it's me", 946681205), ] if err is True: flow.error = terr() flow.reply = controller.DummyReply() return flow
def start_handshake(self) -> layer.CommandGenerator[None]: if not self.send_connect: return (yield from super().start_handshake()) assert self.conn.address flow = http.HTTPFlow(self.context.client, self.tunnel_connection) flow.request = http.Request( host=self.conn.address[0], port=self.conn.address[1], method=b"CONNECT", scheme=b"", authority=f"{self.conn.address[0]}:{self.conn.address[1]}".encode( ), path=b"", http_version=b"HTTP/1.1", headers=http.Headers(), content=b"", trailers=None, timestamp_start=time.time(), timestamp_end=time.time(), ) yield HttpConnectUpstreamHook(flow) raw = http1.assemble_request(flow.request) yield commands.SendData(self.tunnel_connection, raw)
def twebsocketflow(client_conn=True, server_conn=True, messages=True, err=None, handshake_flow=True): if client_conn is True: client_conn = tclient_conn() if server_conn is True: server_conn = tserver_conn() if handshake_flow is True: req = http.Request( "example.com", 80, b"GET", b"http", b"example.com", b"/ws", b"HTTP/1.1", headers=http.Headers( connection="upgrade", upgrade="websocket", sec_websocket_version="13", sec_websocket_key="1234", ), content=b'', trailers=None, timestamp_start=946681200, timestamp_end=946681201, ) resp = http.Response( b"HTTP/1.1", 101, reason=status_codes.RESPONSES.get(101), headers=http.Headers( connection='upgrade', upgrade='websocket', sec_websocket_accept=b'', ), content=b'', trailers=None, timestamp_start=946681202, timestamp_end=946681203, ) handshake_flow = http.HTTPFlow(client_conn, server_conn) handshake_flow.request = req handshake_flow.response = resp f = websocket.WebSocketFlow(client_conn, server_conn, handshake_flow) f.metadata['websocket_handshake'] = handshake_flow.id handshake_flow.metadata['websocket_flow'] = f.id handshake_flow.metadata['websocket'] = True if messages is True: messages = [ websocket.WebSocketMessage(Opcode.BINARY, True, b"hello binary"), websocket.WebSocketMessage(Opcode.TEXT, True, b"hello text"), websocket.WebSocketMessage(Opcode.TEXT, False, b"it's me"), ] if err is True: err = terr() f.messages = messages f.error = err f.reply = controller.DummyReply() return f