forked from aiortc/aioquic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsiduck_client.py
100 lines (84 loc) · 3.06 KB
/
siduck_client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import argparse
import asyncio
import logging
import ssl
from typing import Optional, cast
from aioquic.asyncio.client import connect
from aioquic.asyncio.protocol import QuicConnectionProtocol
from aioquic.quic.configuration import QuicConfiguration
from aioquic.quic.events import DatagramFrameReceived, QuicEvent
from aioquic.quic.logger import QuicFileLogger
logger = logging.getLogger("client")
class SiduckClient(QuicConnectionProtocol):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._ack_waiter: Optional[asyncio.Future[None]] = None
async def quack(self) -> None:
assert self._ack_waiter is None, "Only one quack at a time."
self._quic.send_datagram_frame(b"quack")
waiter = self._loop.create_future()
self._ack_waiter = waiter
self.transmit()
return await asyncio.shield(waiter)
def quic_event_received(self, event: QuicEvent) -> None:
if self._ack_waiter is not None:
if isinstance(event, DatagramFrameReceived) and event.data == b"quack-ack":
waiter = self._ack_waiter
self._ack_waiter = None
waiter.set_result(None)
async def main(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")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="SiDUCK client")
parser.add_argument(
"host", type=str, help="The remote peer's host name or IP address"
)
parser.add_argument("port", type=int, help="The remote peer's port number")
parser.add_argument(
"-k",
"--insecure",
action="store_true",
help="do not validate server certificate",
)
parser.add_argument(
"-q",
"--quic-log",
type=str,
help="log QUIC events to QLOG files in the specified directory",
)
parser.add_argument(
"-l",
"--secrets-log",
type=str,
help="log secrets to a file, for use with Wireshark",
)
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,
)
configuration = QuicConfiguration(
alpn_protocols=["siduck"], is_client=True, max_datagram_frame_size=65536
)
if args.insecure:
configuration.verify_mode = ssl.CERT_NONE
if args.quic_log:
configuration.quic_logger = QuicFileLogger(args.quic_log)
if args.secrets_log:
configuration.secrets_log_file = open(args.secrets_log, "a")
asyncio.run(
main(
configuration=configuration,
host=args.host,
port=args.port,
)
)