Exemplo n.º 1
0
def init_context(certfile, keyfile, pass_phrase):
    from aioquic.h3.connection import H3_ALPN
    from aioquic.quic.configuration import QuicConfiguration
    import ssl

    ctx = QuicConfiguration(alpn_protocols=H3_ALPN, is_client=False)
    ctx.load_cert_chain(certfile, keyfile, pass_phrase)
    ctx.verify_mode = ssl.CERT_NONE
    return ctx
Exemplo n.º 2
0
    async def connection(self, message):

        if message.unresolved_remote is None:
            host = message.opt.uri_host
            port = message.opt.uri_port or self.default_port
            if host is None:
                raise ValueError(
                    "No location found to send message to (neither in .opt.uri_host nor in .remote)"
                )
        else:
            host, port = util.hostportsplit(message.unresolved_remote)
            port = port or self.default_port

        try:
            ipaddress.ip_address(host)
            server_name = None
        except ValueError as ve:
            server_name = host

        infos = await self.loop.getaddrinfo(host, port, type=socket.SOCK_DGRAM)
        self.addr = infos[0][4]

        config = QuicConfiguration(is_client=True,
                                   alpn_protocols='coap',
                                   idle_timeout=864000,
                                   server_name=server_name)
        config.verify_mode = ssl.CERT_NONE

        if config.server_name is None:
            config.server_name = server_name

        connection = QuicConnection(configuration=config)

        self.quic = Quic(connection)
        self.quic.ctx = self

        try:
            transport, protocol = await self.loop.create_datagram_endpoint(
                lambda: self.quic, remote_addr=(host, port))
            protocol.connect(self.addr)
            await protocol.wait_connected()
            self.con = True
        except OSError:
            raise error.NetworkError("Connection failed to %r" % host)

        return protocol
Exemplo n.º 3
0
    args = parser.parse_args()

    logging.basicConfig(
        format="%(asctime)s %(levelname)s %(name)s %(message)s",
        level=logging.DEBUG if args.verbose else logging.INFO,
    )

    # prepare configuration
    configuration = QuicConfiguration(
        is_client=True,
        alpn_protocols=H0_ALPN if args.legacy_http else H3_ALPN)
    if args.ca_certs:
        configuration.load_verify_locations(args.ca_certs)
    if args.insecure:
        configuration.verify_mode = ssl.CERT_NONE
    if args.quic_log:
        configuration.quic_logger = QuicLogger()
    if args.secrets_log:
        configuration.secrets_log_file = open(args.secrets_log, "a")
    if args.session_ticket:
        try:
            with open(args.session_ticket, "rb") as fp:
                configuration.session_ticket = pickle.load(fp)
        except FileNotFoundError:
            pass

    if uvloop is not None:
        uvloop.install()
    loop = asyncio.get_event_loop()
    try:
Exemplo n.º 4
0
def transaction(topic_name, topic_text, parts_list):
    async def perform_http_request(client: HttpClient, url: str, data: str,
                                   print_response: bool) -> None:
        # perform request
        start = time.time()
        if data is not None:
            http_events = await client.post(
                url,
                data=data.encode(),
                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
        if 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()

    def save_session_ticket(ticket):
        """
        Callback which is invoked by the TLS engine when a new session ticket
        is received.
        """
        logger.info("New session ticket received")
        if args.session_ticket:
            with open(args.session_ticket, "wb") as fp:
                pickle.dump(ticket, fp)

    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 = add_item(topic_name, topic_text)
                    # message = add_item()
                    await ws.send(message)
                    # CheckLogin()

                asyncio.run_coroutine_threadsafe(read_user(), new_loop)

                # *** STAYS IN MAIN LOOP ***
                while True:
                    messageRec = await ws.recv()
                    print("< " + messageRec)
                    if messageRec == "inserted_item":
                        print("client update list")
                        root = Tk()
                        app = App(root)
                        app.update_text()
                        root.mainloop()

                # *** 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)

    if __name__ == "__main__":
        parser = argparse.ArgumentParser(description="HTTP/3 client")
        parser.add_argument("url",
                            type=str,
                            help="the URL to query (must be HTTPS)")
        parser.add_argument(
            "--ca-certs",
            type=str,
            help="load CA certificates from the specified file")
        parser.add_argument("-d",
                            "--data",
                            type=str,
                            help="send the specified data in a POST request")
        parser.add_argument(
            "-k",
            "--insecure",
            action="store_true",
            help="do not validate server certificate",
        )
        parser.add_argument("--legacy-http",
                            action="store_true",
                            help="use HTTP/0.9")
        parser.add_argument("-q",
                            "--quic-log",
                            type=str,
                            help="log QUIC events to a file in QLOG format")
        parser.add_argument(
            "-l",
            "--secrets-log",
            type=str,
            help="log secrets to a file, for use with Wireshark",
        )
        parser.add_argument("--parallel",
                            type=int,
                            default=1,
                            help="perform this many requests in parallel")
        parser.add_argument("--print-response",
                            action="store_true",
                            help="print response headers and body")
        parser.add_argument(
            "-s",
            "--session-ticket",
            type=str,
            help="read and write session ticket from the specified file",
        )
        parser.add_argument("-v",
                            "--verbose",
                            action="store_true",
                            help="increase logging verbosity")

        args = parser.parse_args()

        logging.basicConfig(
            format="%(asctime)s %(levelname)s %(name)s %(message)s",
            level=logging.DEBUG if args.verbose else logging.INFO,
        )

        # prepare configuration
        configuration = QuicConfiguration(
            is_client=True,
            alpn_protocols=H0_ALPN if args.legacy_http else H3_ALPN)
        if args.ca_certs:
            configuration.load_verify_locations(args.ca_certs)
        if args.insecure:
            configuration.verify_mode = ssl.CERT_NONE
        if args.quic_log:
            configuration.quic_logger = QuicLogger()
        if args.secrets_log:
            configuration.secrets_log_file = open(args.secrets_log, "a")
        if args.session_ticket:
            try:
                with open(args.session_ticket, "rb") as fp:
                    configuration.session_ticket = pickle.load(fp)
            except FileNotFoundError:
                pass

        if uvloop is not None:
            uvloop.install()
        loop = asyncio.get_event_loop()
        try:
            loop.run_until_complete(
                run(
                    configuration=configuration,
                    url=args.url,
                    data=args.data,
                    parallel=args.parallel,
                    print_response=args.print_response,
                ))
        finally:
            if configuration.quic_logger is not None:
                with open(args.quic_log, "w") as logger_fp:
                    json.dump(configuration.quic_logger.to_dict(),
                              logger_fp,
                              indent=4)