def client_and_server( client_options={}, client_patch=lambda x: None, server_options={}, server_patch=lambda x: None, transport_options={}, ): client = QuicConnection( configuration=QuicConfiguration(is_client=True, **client_options)) client._ack_delay = 0 client_patch(client) server = QuicConnection( configuration=QuicConfiguration(is_client=False, certificate=SERVER_CERTIFICATE, private_key=SERVER_PRIVATE_KEY, **server_options)) server._ack_delay = 0 server_patch(server) # perform handshake client.connect(SERVER_ADDR, now=time.time()) for i in range(3): roundtrip(client, server) yield client, server # close client.close() server.close()
def create_standalone_client(self): client = QuicConnection(configuration=QuicConfiguration(is_client=True)) client._ack_delay = 0 # kick-off handshake client.connect(SERVER_ADDR, now=time.time()) self.assertEqual(drop(client), 1) return client
def create_standalone_client(): client = QuicConnection(configuration=QuicConfiguration(is_client=True)) client_transport = FakeTransport(CLIENT_ADDR, loss=0) # kick-off handshake client.connection_made(client_transport) client.connect(SERVER_ADDR) return client, client_transport
def run(url: str) -> None: # parse URL parsed = urlparse(url) assert parsed.scheme == "https", "Only HTTPS URLs are supported." if ":" in parsed.netloc: server_name, port_str = parsed.netloc.split(":") port = int(port_str) else: server_name = parsed.netloc port = 443 # prepare socket server_addr = (socket.gethostbyname(server_name), port) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # prepare QUIC connection quic = QuicConnection(configuration=QuicConfiguration( alpn_protocols=["h3-20"], is_client=True, secrets_log_file=open("/tmp/ssl.log", "w"), server_name=server_name, )) quic.connect(server_addr, now=time.time()) # send request http = H3Connection(quic) stream_id = quic.get_next_available_stream_id() http.send_headers( stream_id=stream_id, headers=[ (b":method", b"GET"), (b":scheme", parsed.scheme.encode("utf8")), (b":authority", parsed.netloc.encode("utf8")), (b":path", parsed.path.encode("utf8")), ], ) http.send_data(stream_id=stream_id, data=b"", end_stream=True) for data, addr in quic.datagrams_to_send(now=time.time()): sock.sendto(data, addr) # handle events stream_ended = False while not stream_ended: data, addr = sock.recvfrom(2048) quic.receive_datagram(data, addr, now=time.time()) for event in http.handle_events(): print(event) if isinstance(event, (DataReceived, ResponseReceived)): stream_ended = event.stream_ended for data, addr in quic.datagrams_to_send(now=time.time()): sock.sendto(data, addr)
def test_connection_lost_with_exception(self): client = QuicConnection(is_client=True) server = QuicConnection( is_client=False, certificate=SERVER_CERTIFICATE, private_key=SERVER_PRIVATE_KEY, ) # perform handshake client_transport, server_transport = create_transport(client, server) self.assertEqual(client_transport.sent, 4) self.assertEqual(server_transport.sent, 4) run(client.connect()) # send data over stream client_reader, client_writer = client.create_stream() client_writer.write(b"ping") run(asyncio.sleep(0)) self.assertEqual(client_transport.sent, 5) self.assertEqual(server_transport.sent, 5) # break connection exc = Exception("some error") client.connection_lost(exc) with self.assertRaises(Exception) as cm: run(client_reader.read()) self.assertEqual(cm.exception, exc)
def _test_connect_with_version(self, client_versions, server_versions): client = QuicConnection(is_client=True) client.supported_versions = client_versions server = QuicConnection( is_client=False, certificate=SERVER_CERTIFICATE, private_key=SERVER_PRIVATE_KEY, ) server.supported_versions = server_versions # perform handshake client_transport, server_transport = create_transport(client, server) self.assertEqual(client_transport.sent, 4) self.assertEqual(server_transport.sent, 4) run(client.connect()) # send data over stream client_reader, client_writer = client.create_stream() client_writer.write(b"ping") run(asyncio.sleep(0)) self.assertEqual(client_transport.sent, 5) self.assertEqual(server_transport.sent, 5) # FIXME: needs an API server_reader, server_writer = ( server.streams[0].reader, server.streams[0].writer, ) self.assertEqual(run(server_reader.read(1024)), b"ping") server_writer.write(b"pong") run(asyncio.sleep(0)) self.assertEqual(client_transport.sent, 6) self.assertEqual(server_transport.sent, 6) # client receives pong self.assertEqual(run(client_reader.read(1024)), b"pong") # client writes EOF client_writer.write_eof() run(asyncio.sleep(0)) self.assertEqual(client_transport.sent, 7) self.assertEqual(server_transport.sent, 7) # server receives EOF self.assertEqual(run(server_reader.read()), b"")
def test_connection_lost(self): client = QuicConnection(is_client=True) server = QuicConnection( is_client=False, certificate=SERVER_CERTIFICATE, private_key=SERVER_PRIVATE_KEY, ) # perform handshake client_transport, server_transport = create_transport(client, server) self.assertEqual(client_transport.sent, 4) self.assertEqual(server_transport.sent, 4) run(client.connect()) # send data over stream client_reader, client_writer = client.create_stream() client_writer.write(b"ping") run(asyncio.sleep(0)) self.assertEqual(client_transport.sent, 5) self.assertEqual(server_transport.sent, 5) # break connection client.connection_lost(None) self.assertEqual(run(client_reader.read()), b"")