예제 #1
0
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)
예제 #2
0
    def _consume_events(self, connection: QuicConnection) -> None:
        # process events
        event = connection.next_event()
        while event is not None:
            if isinstance(event, aioquic.events.HandshakeCompleted):
                if event.alpn_protocol == "h3-20":
                    self._http[connection] = H3Connection(connection)
                elif event.alpn_protocol == "hq-20":
                    self._http[connection] = H0Connection(connection)
            elif isinstance(event, aioquic.events.ConnectionIdIssued):
                self._connections[event.connection_id] = connection
            elif isinstance(event, aioquic.events.ConnectionIdRetired):
                assert self._connections[event.connection_id] == connection
                del self._connections[event.connection_id]

            #  pass event to the HTTP layer
            http = self._http.get(connection)
            if http is not None:
                for http_event in http.handle_event(event):
                    handle_http_event(http, http_event)

            event = connection.next_event()

        # send datagrams
        for data, addr in connection.datagrams_to_send(now=self._loop.time()):
            self._transport.sendto(data, addr)

        # re-arm timer
        """