async def run_client(self, host=None, port=None, cadata=None, cafile=SERVER_CACERTFILE, configuration=None, request=b"ping", **kwargs): if host is None: host = self.server_host if port is None: port = self.server_port if configuration is None: configuration = QuicConfiguration(is_client=True) configuration.load_verify_locations(cadata=cadata, cafile=cafile) async with connect(host, port, configuration=configuration, **kwargs) as client: # waiting for connected when connected returns immediately await client.wait_connected() reader, writer = await client.create_stream() self.assertEqual(writer.can_write_eof(), True) self.assertEqual(writer.get_extra_info("stream_id"), 0) writer.write(request) writer.write_eof() response = await reader.read() # waiting for closed when closed returns immediately await client.wait_closed() return response
async def run(configuration: QuicConfiguration, url: str) -> None: # parse URL parsed = urlparse(url) assert parsed.scheme == "https", "Only https:// URLs are supported." if ":" in parsed.netloc: host, port_str = parsed.netloc.split(":") port = int(port_str) else: host = parsed.netloc port = 443 async with connect( host, port, configuration=configuration, create_protocol=H3Dispatcher, session_ticket_handler=save_session_ticket, ) as dispatch: client = AsyncClient(dispatch=dispatch) # perform request start = time.time() response = await client.get(url) elapsed = time.time() - start # print speed octets = len(response.content) logger.info("Received %d bytes in %.1f s (%.3f Mbps)" % (octets, elapsed, octets * 8 / elapsed / 1000000)) # print response for header, value in response.headers.items(): sys.stderr.write(header + ": " + value + "\r\n") sys.stdout.buffer.write(response.content) sys.stdout.buffer.flush()
async def run_client_ping(host, port=4433): configuration = QuicConfiguration(is_client=True) configuration.load_verify_locations(cafile=SERVER_CACERTFILE) async with connect(host, port, configuration=configuration) as client: coros = [client.ping() for x in range(16)] await asyncio.gather(*coros)
async def run(configuration, reqs, repeat = 1): if not isinstance (reqs, list): reqs = [reqs] netlocs = set () for req in reqs: assert req.url.scheme == "https", "Only https:// URLs are supported." if ":" in req.url.netloc: host, port_str = req.url.netloc.split(":") port = int(port_str) else: host = req.url.netloc port = 443 netlocs.add ((host, port)) assert len (netlocs) == 1, 'different netloc' async with connect( host, port, configuration=configuration, create_protocol=HttpClient, session_ticket_handler=save_session_ticket, ) as client: client = cast(HttpClient, client) # perform request coros = [] for req in reqs: coros.extend ([perform_http_request(client, i == 0 and req or req.clone ()) for i in range (repeat)]) await asyncio.gather(*coros)
async def probe(self) -> ProbeResult: configuration = QuicConfiguration( alpn_protocols=h3c.H3_ALPN, is_client=True, server_name=self._url.hostname, max_datagram_frame_size=32+MTU, ) def create_protocol(*args, **kwargs): return H3Client(self._url, ORIGIN, MTU, *args, **kwargs) try: ip, port = self._resolve_dns() async with connect( host=ip, port=port, configuration=configuration, create_protocol=create_protocol, wait_connected=False, ) as client: client = T.cast(H3Client, client) await aio.wait_for(client.wait_connected(), CONNECT_TIMEOUT) self._result.connected = True self._result.probes = [ProbeNameResult( ok=False, error="timeout") for name in self._names] self._send_interests(client) received = 0 for _ in range(int(INTEREST_TIMEOUT // INTEREST_TIMEOUT_STEP)): await aio.sleep(INTEREST_TIMEOUT_STEP) received += self._process_received(client) if received >= len(self._names): break except Exception as err: self._result.connectError = str(err) return self._result
async def run_client_no_wait_connected(host, port, configuration): configuration.load_verify_locations(cafile=SERVER_CACERTFILE) async with connect(host, port, configuration=configuration, wait_connected=False) as client: await client.ping()
async def run_client_ping(host, port=4433): configuration = QuicConfiguration(is_client=True) configuration.load_verify_locations(cafile=SERVER_CACERTFILE) async with connect(host, port, configuration=configuration) as client: await client.ping() await client.ping()
async def run( configuration: QuicConfiguration, url: str, data: str, include: bool, output_dir: Optional[str], ) -> None: # parse URL parsed = urlparse(url) assert parsed.scheme == "https", "Only https:// URLs are supported." host = parsed.hostname if parsed.port is not None: port = parsed.port else: port = 443 async with connect( host, port, configuration=configuration, create_protocol=H3Transport, session_ticket_handler=save_session_ticket, ) as transport: async with AsyncClient(transport=cast(httpcore.AsyncHTTPTransport, transport)) as client: # perform request start = time.time() if data is not None: response = await client.post( url, content=data.encode(), headers={ "content-type": "application/x-www-form-urlencoded" }, ) else: response = await client.get(url) elapsed = time.time() - start # print speed octets = len(response.content) logger.info("Received %d bytes in %.1f s (%.3f Mbps)" % (octets, elapsed, octets * 8 / elapsed / 1000000)) # output response if output_dir is not None: output_path = os.path.join( output_dir, os.path.basename(urlparse(url).path) or "index.html") with open(output_path, "wb") as output_file: if include: headers = "" for header, value in response.headers.items(): headers += header + ": " + value + "\r\n" if headers: output_file.write(headers.encode() + b"\r\n") output_file.write(response.content)
async def run( configuration: QuicConfiguration, urls: List[str], data: str, include: bool, output_dir: Optional[str], local_port: int, zero_rtt: bool, ) -> None: # parse URL parsed = urlparse(urls[0]) assert parsed.scheme in ( "https", "wss", ), "Only https:// or wss:// URLs are supported." if ":" in parsed.netloc: host, port_str = parsed.netloc.split(":") port = int(port_str) else: host = parsed.netloc port = 443 async with connect( host, port, configuration=configuration, create_protocol=HttpClient, session_ticket_handler=save_session_ticket, local_port=local_port, wait_connected=not zero_rtt, ) as client: client = cast(HttpClient, client) if parsed.scheme == "wss": ws = await client.websocket(urls[0], subprotocols=["chat", "superchat"]) # send some messages and receive reply for i in range(2): message = "Hello {}, WebSocket!".format(i) print("> " + message) await ws.send(message) message = await ws.recv() print("< " + message) await ws.close() else: # perform request coros = [ perform_http_request( client=client, url=url, data=data, include=include, output_dir=output_dir, ) for url in urls ] await asyncio.gather(*coros)
async def run(configuration: QuicConfiguration, host: str, port: int) -> None: async with connect( host, port, configuration=configuration, create_protocol=SiduckClient ) as client: client = cast(SiduckClient, client) logger.info("sending quack") await client.quack() logger.info("received quack-ack")
async def run_client_key_update(): configuration = QuicConfiguration(is_client=True) configuration.load_verify_locations(cafile=SERVER_CACERTFILE) async with connect(self.server_host, self.server_port, configuration=configuration) as client: await client.ping() client.request_key_update() await client.ping()
async def run_client_writelines(host, port=4433, **kwargs): async with connect(host, port, **kwargs) as client: reader, writer = await client.create_stream() assert writer.can_write_eof() is True writer.writelines([b"01234567", b"89012345"]) writer.write_eof() return await reader.read()
async def _connect_to_server(host: str, port: int) -> None: configuration = QuicConfiguration( alpn_protocols=H3_ALPN, is_client=True, verify_mode=ssl.CERT_NONE, ) async with connect(host, port, configuration=configuration) as protocol: await protocol.ping()
async def run_client_no_wait_connected(configuration): configuration.load_verify_locations(cafile=SERVER_CACERTFILE) async with connect( self.server_host, self.bogus_port, configuration=configuration, wait_connected=False, ) as client: await client.ping()
async def run_client(host, port=4433, request=b"ping", **kwargs): async with connect(host, port, **kwargs) as client: reader, writer = await client.create_stream() assert writer.can_write_eof() is True assert writer.get_extra_info("stream_id") == 0 writer.write(request) writer.write_eof() return await reader.read()
async def run_client_writelines(host, port=4433): configuration = QuicConfiguration(is_client=True) configuration.load_verify_locations(cafile=SERVER_CACERTFILE) async with connect(host, port, configuration=configuration) as client: reader, writer = await client.create_stream() assert writer.can_write_eof() is True writer.writelines([b"01234567", b"89012345"]) writer.write_eof() return await reader.read()
async def run( configuration: QuicConfiguration, url: str, data: str, parallel: int, print_response: bool, ) -> None: # parse URL parsed = urlparse(url) assert parsed.scheme in ( "https", "wss", ), "Only https:// or wss:// URLs are supported." if ":" in parsed.netloc: host, port_str = parsed.netloc.split(":") port = int(port_str) else: host = parsed.netloc port = 443 async with connect( host, port, configuration=configuration, create_protocol=HttpClient, session_ticket_handler=save_session_ticket, ) as client: client = cast(HttpClient, client) if parsed.scheme == "wss": ws = await client.websocket(url, subprotocols=["chat", "superchat"]) # send some messages and receive reply for i in range(9): message = "Palos Client sagt hallo! - Count {}".format(i) print("> " + message) await ws.send(message) message = await ws.recv() print("< " + message) await ws.close() else: # perform request coros = [ perform_http_request(client=client, url=url, data=data, print_response=print_response) for i in range(parallel) ] await asyncio.gather(*coros)
async def request_worker(self): configuration = QuicConfiguration(is_client=True, alpn_protocols=H3_ALPN) while self.recreate_connection_check(): async with connect("youtube.com", 443, configuration=configuration, create_protocol=HttpClient) as client: while True: status = await self._handle_request(client) # Connection has been terminated. if status is False: break
async def run( configuration: QuicConfiguration, host: str, port: int, ) -> None: logger.debug(f"Connecting to {host}:{port}") async with connect( host, port, configuration=configuration, session_ticket_handler=save_session_ticket, create_protocol=ModbusClient, ) as client: client = cast(ModbusClient, client) logger.debug("Sending Modbus query") await start_async_test(client.protocol)
async def run( configuration: QuicConfiguration, host: str, port: int, query_type: str, dns_query: str, ) -> None: logger.debug(f"Connecting to {host}:{port}") async with connect( host, port, configuration=configuration, session_ticket_handler=save_session_ticket, create_protocol=DoQClient, ) as client: client = cast(DoQClient, client) logger.debug("Sending DNS query") await client.query(query_type, dns_query)
async def run_client(host, port=4433, cadata=None, cafile=SERVER_CACERTFILE, configuration=None, request=b"ping", **kwargs): if configuration is None: configuration = QuicConfiguration(is_client=True) configuration.load_verify_locations(cadata=cadata, cafile=cafile) async with connect(host, port, configuration=configuration, **kwargs) as client: reader, writer = await client.create_stream() assert writer.can_write_eof() is True assert writer.get_extra_info("stream_id") == 0 writer.write(request) writer.write_eof() return await reader.read()
async def run_client_without_config(): async with connect(self.server_host, self.server_port) as client: await client.ping()
async def run( configuration: QuicConfiguration, url: str, data: str, parallel: int, print_response: bool, ) -> None: # parse URL parsed = urlparse(url) assert parsed.scheme in ( "https", "wss", ), "Only https:// or wss:// URLs are supported." if ":" in parsed.netloc: host, port_str = parsed.netloc.split(":") port = int(port_str) else: host = parsed.netloc port = 443 async with connect( host, port, configuration=configuration, create_protocol=HttpClient, session_ticket_handler=save_session_ticket, ) as client: client = cast(HttpClient, client) if parsed.scheme == "wss": ws = await client.websocket(url, subprotocols=["chat", "superchat"]) print("Hint: To send a message type and press enter.") # ****************************** # *** ASYNCHRONOUS THREADING *** def start_loop(loop): asyncio.set_event_loop(loop) loop.run_forever() new_loop = asyncio.new_event_loop() t = Thread(target=start_loop, args=(new_loop, )) t.start() async def read_user(): while True: message = stdin.readline() await ws.send("Client 1: " + message) asyncio.run_coroutine_threadsafe(threaded_GUI(ws), new_loop) # *** STAYS IN MAIN LOOP *** while True: messageRec = await ws.recv() print("< " + messageRec) # *** ASYNCHRONOUS THREADING *** # ****************************** # await ws.close() else: # perform request coros = [ perform_http_request(client=client, url=url, data=data, print_response=print_response) for i in range(parallel) ] await asyncio.gather(*coros)
async def run( configuration: QuicConfiguration, urls: List[str], data: str, include: bool, parallel: int, output_dir: Optional[str], ) -> None: url = urls[0] # parse URL parsed = urlparse(urls[0]) assert parsed.scheme in ( "https", "wss", ), "Only https:// or wss:// URLs are supported." if ":" in parsed.netloc: host, port_str = parsed.netloc.split(":") port = int(port_str) else: host = parsed.netloc port = 443 # we can either do 1rtt and 0rtt back to back (default) # or we can first do 1rtt, store the session ticket to disk # then, in a second call to this programme, do 0rtt only, reading the session ticket attempt_1rtt = True attempt_0rtt = True if args.session_ticket_read: attempt_1rtt = False attempt_0rtt = True elif args.session_ticket_write: attempt_1rtt = True attempt_0rtt = False global session_ticket if attempt_1rtt: async with connect( host, port, configuration=configuration, create_protocol=HttpClient, session_ticket_handler=save_session_ticket, ) as client: client = cast(HttpClient, client) # perform request coros = [ perform_http_request(client=client, url=urls[i], data=data, include=include, output_dir=output_dir, counter=i) for i in range(parallel) ] await asyncio.gather(*coros) client.close() await client.wait_closed() # end attempt_1rtt if attempt_0rtt: try: if args.session_ticket_read: logger.info("Read session ticket (delayed) from %s", args.session_ticket_read) session_ticket = configuration.session_ticket elif session_ticket is not None: # when neither reading nor writing, so doing connections back to back configuration.session_ticket = session_ticket else: logger.info( "----------------------------------------------------") logger.error( "No session ticket received, so not doing 0rtt, sorry") logger.error(session_ticket) return logger.info("------------------------------------------") logger.info("------------------------------------------") logger.info("------------------------------------------") logger.info("ATTEMPTING RESUMPTION WITH SESSION TICKET") logger.info(session_ticket) async with connect(host, port, configuration=configuration, create_protocol=HttpClient, session_ticket_handler=save_session_ticket, wait_connected=False) as client2: client2 = cast(HttpClient, client2) logger.info("Attempting 0RTT, not waiting until connected") if configuration.quic_logger is not None: client2._http._quic_logger.log_event( # this gets the correct trace category="transport", event="session_ticket_used", data={ "not_valid_after": str(session_ticket.not_valid_after), "not_valid_before": str(session_ticket.not_valid_before), "age_add": str(session_ticket.age_add), "server_name": session_ticket.server_name, "resumption_secret": str(session_ticket.resumption_secret), "cipher_suite": str(session_ticket.cipher_suite), "max_early_data_size": str(session_ticket.max_early_data_size), } ) allowance = "sendmemore0rtt_" * 370 # pylsqpack buffer size is 4096 bytes long, string is 15 chars, encodes down to less in utf8, 370 was experimentally defined # when cache busting on facebook (or other cdns), make sure the second url is different from the first if url.find("?buster=") >= 0: url += "nr2for0rtt" # amplification factor 0 = normal 0-RTT # 1 = 3.5 packets of 0-RTT # 2 = 7 packets of 0-RTT, split over 2 requests (because pylsqpack doesn't allow very large headers, so we do 2 requests to get the same result) headers = {} # headers["x-fb-debug"] = "True" # works, but headers are encrypted... so useless if zerortt_amplification_factor > 0: headers[ "x-0rtt-allowance"] = allowance # add a large header to make sure the 0-RTT request spans multiple packets (about 3.5 with the above header size) # ONLY ENABLE TO TEST THIS SCENARIO! # Also change the connection.py to that effect! # SHOULD NOT BE NEEDED FOR ALMOST ALL CASES! firstFlightOnly = False if firstFlightOnly: logger.info( "First flight only: aborting after 10 seconds to prevent stalling" ) futures = [ perform_http_request(client=client2, url=url, data=data, headers=headers, include=include, output_dir=output_dir, counter=0), asyncio.sleep(10) ] await asyncio.wait(futures, return_when=asyncio.FIRST_COMPLETED) elif zerortt_amplification_factor < 2: await perform_http_request(client=client2, url=url, data=data, headers=headers, include=include, output_dir=output_dir, counter=0) else: requests2 = [ perform_http_request( client=client2, url=url, data=data, include=include, output_dir=output_dir, counter=i, headers=headers, ) for i in range(zerortt_amplification_factor) ] await asyncio.gather(*requests2) if client2._quic.tls.session_resumed: logger.info("SESSION RESUMED SUCCESSFULLY!") else: logger.error("SESSION NOT RESUMED") if client2._quic.tls.early_data_accepted: logger.info("SESSION EARLY_DATA_ACCEPTED SUCCESSFULLY!") else: logger.error("EARLY_DATA NOT ACCEPTED?!?") client2.close() if not firstFlightOnly: await client2.wait_closed() # with client2 except ConnectionError as ce: logger.error("Connection error encountered") logger.error(ce)
async def run( configuration: QuicConfiguration, urls: List[str], data: str, include: bool, output_dir: Optional[str], local_port: int, zero_rtt: bool, input_file: str, ) -> None: # parse URL parsed = urlparse(urls[0]) assert parsed.scheme in ( "https", "wss", ), "Only https:// or wss:// URLs are supported." host = parsed.hostname if parsed.port is not None: port = parsed.port else: port = 443 async with connect( host, port, configuration=configuration, create_protocol=HttpClient, session_ticket_handler=save_session_ticket, local_port=local_port, wait_connected=not zero_rtt, ) as client: client = cast(HttpClient, client) if parsed.scheme == "wss": ws = await client.websocket(urls[0], subprotocols=["chat", "superchat"]) if input_file is not None: with open(input_file) as csv_file: csv_reader = csv.reader(csv_file, delimiter=',') line_count = 0 for row in csv_reader: if line_count == 0: line_count += 1 else: message = ''.join(row) print("> " + message) await ws.send(message) message = await ws.recv() print("< " + message) line_count += 1 time.sleep(1) else: # send some messages and receive reply for i in range(2): message = "Hello {}, WebSocket!".format(i) print("> " + message) await ws.send(message) message = await ws.recv() print("< " + message) await ws.close() else: # perform request coros = [ perform_http_request( client=client, url=url, data=data, include=include, output_dir=output_dir, ) for url in urls ] await asyncio.gather(*coros) # process http pushes process_http_pushes(client=client, include=include, output_dir=output_dir)
async def run(configuration: QuicConfiguration, url: str, data: str) -> None: # parse URL parsed = urlparse(url) assert parsed.scheme in ( "https", "wss", ), "Only https:// or wss:// URLs are supported." if ":" in parsed.netloc: host, port_str = parsed.netloc.split(":") port = int(port_str) else: host = parsed.netloc port = 443 async with connect( host, port, configuration=configuration, create_protocol=HttpClient, session_ticket_handler=save_session_ticket, ) as client: client = cast(HttpClient, client) if parsed.scheme == "wss": ws = await client.websocket(url, subprotocols=["chat", "superchat"]) # send some messages and receive reply for i in range(2): message = "Hello {}, WebSocket!".format(i) print("> " + message) await ws.send(message) message = await ws.recv() print("< " + message) await ws.close() else: # perform request start = time.time() if data is not None: http_events = await client.post( url, data=data.encode("utf8"), headers={ "content-type": "application/x-www-form-urlencoded" }, ) else: http_events = await client.get(url) elapsed = time.time() - start # print speed octets = 0 for http_event in http_events: if isinstance(http_event, DataReceived): octets += len(http_event.data) logger.info("Received %d bytes in %.1f s (%.3f Mbps)" % (octets, elapsed, octets * 8 / elapsed / 1000000)) # print response for http_event in http_events: if isinstance(http_event, HeadersReceived): headers = b"" for k, v in http_event.headers: headers += k + b": " + v + b"\r\n" if headers: sys.stderr.buffer.write(headers + b"\r\n") sys.stderr.buffer.flush() elif isinstance(http_event, DataReceived): sys.stdout.buffer.write(http_event.data) sys.stdout.buffer.flush()
async def run( configuration: QuicConfiguration, urls: List[str], data: str, include: bool, output_dir: Optional[str], local_port: int, zero_rtt: bool, ) -> None: # parse URL parsed = urlparse(urls[0]) assert parsed.scheme in ( "https", "wss", ), "Only https:// or wss:// URLs are supported." if ":" in parsed.netloc: host, port_str = parsed.netloc.split(":") port = int(port_str) else: host = parsed.netloc port = 443 async with connect( host, port, configuration=configuration, create_protocol=HttpClient, session_ticket_handler=save_session_ticket, local_port=local_port, wait_connected=not zero_rtt, ) as client: client = cast(HttpClient, client) if parsed.scheme == "wss": ws = await client.websocket(urls[0], subprotocols=["chat", "superchat"]) # send some messages and receive reply for i in range(2): message = "Hello {}, WebSocket!".format(i) print("> " + message) await ws.send(message) message = await ws.recv() print("< " + message) await ws.close() else: #DEBUG2 TEST******************* DA SPOSTARE DA QUALCHE PARTE A PIù BASSO LIVELLO hostname = socket.gethostname() ip_address = socket.gethostbyname(hostname) print(f"Hostname: {hostname}") print(f"IP Address: {ip_address}") #DEBUG2 TEST******************* # perform request cont = 0 #DEBUG* while (cont < 5): #DEBUG* await asyncio.sleep(5) #DEBUG* coros = [ perform_http_request( client=client, url=url, data=data, include=include, output_dir=output_dir, counter=cont #DEBUG2 TEST* ) for url in urls ] await asyncio.gather(*coros) cont += 1 #DEBUG*
async def run_client_ping(host, **kwargs): async with connect(host, 4433, **kwargs) as client: await client.ping() await client.ping()
async def run_client_key_update(host, **kwargs): async with connect(host, 4433, **kwargs) as client: await client.ping() client.change_connection_id() await client.ping()
async def run_client_key_update(host, **kwargs): async with connect(host, 4433, **kwargs) as client: await client.ping() client.request_key_update() await client.ping()