| @@ -30,9 +30,13 @@ import subprocess | |||
| import tempfile | |||
| import unittest | |||
| from functools import wraps | |||
| from . import parsesockstr, connectsockstr, listensockstr | |||
| from . import async_test, _awaitfile | |||
| import aioquic | |||
| from aioquic.asyncio import QuicConnectionProtocol, serve | |||
| from aioquic.asyncio.client import connect | |||
| from aioquic.quic.configuration import QuicConfiguration | |||
| @@ -57,7 +61,30 @@ async def run_connect(dst, rdr, wrr): | |||
| await asyncio.gather(fwd_data(connrdr, wrr), fwd_data(rdr, connwrr)) | |||
| def cmd_quic_serv(args): | |||
| def common_args(parser): | |||
| parser.add_argument('-i', '--initial-window', type=int, | |||
| default=2*1024*1024, help='initial window in bytes (default 2MB)') | |||
| parser.add_argument('-l', '--loss-reduction', type=float, | |||
| default=.95, | |||
| help='factor to reduce the window when loss is detected (default .95)') | |||
| parser.add_argument('-t', '--timeout', type=float, default=120.0, | |||
| help='if no packets are received after timeout seconds, connection will terminate') | |||
| def common_args_proc(fun): | |||
| @wraps(fun) | |||
| def wrapper(args): | |||
| aioquic.quic.recovery.K_INITIAL_WINDOW = args.initial_window | |||
| aioquic.quic.recovery.K_LOSS_REDUCTION_FACTOR = \ | |||
| args.loss_reduction | |||
| confkwargs = dict(idle_timeout=args.timeout) | |||
| return fun(args, confkwargs) | |||
| return wrapper | |||
| @common_args_proc | |||
| def cmd_quic_serv(args, confkwargs): | |||
| privkey = args.servkey | |||
| cert = args.cert | |||
| @@ -67,6 +94,7 @@ def cmd_quic_serv(args): | |||
| alpn_protocols=["ntunnel-01"], | |||
| is_client=False, | |||
| quic_logger=quic_logger, | |||
| **confkwargs, | |||
| ) | |||
| quic_conf.load_cert_chain(cert, privkey) | |||
| @@ -82,8 +110,6 @@ def cmd_quic_serv(args): | |||
| # XXX - await task | |||
| print('foo', repr(slargs)) | |||
| loop = asyncio.get_event_loop() | |||
| loop.run_until_complete(serve(slargs['host'], slargs['port'], | |||
| configuration=quic_conf, retry=True, stream_handler=sh)) | |||
| @@ -100,8 +126,8 @@ async def client_run(conf, liststr, deststr): | |||
| raise ValueError('protocol for destination must be udp') | |||
| # XXX - loop when server restarts? | |||
| async with connect(slargs['host'], slargs['port'], configuration=conf) as \ | |||
| client: | |||
| async with connect(slargs['host'], slargs['port'], | |||
| configuration=conf) as client: | |||
| async def connmaker(rdr, wrr): | |||
| connrdr, connwrr = await client.create_stream() | |||
| @@ -113,13 +139,15 @@ async def client_run(conf, liststr, deststr): | |||
| # XXX - how to break out when new connection needed? | |||
| await ssock.serve_forever() | |||
| def cmd_quic_client(args): | |||
| @common_args_proc | |||
| def cmd_quic_client(args, confkwargs): | |||
| quic_logger = None | |||
| quic_conf = QuicConfiguration( | |||
| alpn_protocols=["ntunnel-01"], | |||
| is_client=True, | |||
| quic_logger=quic_logger, | |||
| **confkwargs, | |||
| ) | |||
| if args.ca_certs: | |||
| @@ -133,21 +161,29 @@ def cmd_quic_client(args): | |||
| def quic_parsers(subparsers): | |||
| parser_quic_serv = subparsers.add_parser('quic_serv', help='run a QUIC server') | |||
| parser_quic_serv = subparsers.add_parser('quic_serv', | |||
| help='run a QUIC server') | |||
| parser_quic_serv.add_argument("-k", "--servkey", type=str, | |||
| help="load the TLS private key from the specified file") | |||
| parser_quic_serv.add_argument("-c", "--cert", type=str, | |||
| required=True, | |||
| help="load the TLS certificate from the specified file") | |||
| parser_quic_serv.add_argument('servlisten', type=str, help='Connection that the server listens on') | |||
| parser_quic_serv.add_argument('servtarget', type=str, help='Connection that the server connects to') | |||
| parser_quic_serv.add_argument('servlisten', type=str, | |||
| help='Connection that the server listens on') | |||
| parser_quic_serv.add_argument('servtarget', type=str, | |||
| help='Connection that the server connects to') | |||
| common_args(parser_quic_serv) | |||
| parser_quic_serv.set_defaults(func=cmd_quic_serv) | |||
| parser_quic_client = subparsers.add_parser('quic_client', help='run a QUIC client') | |||
| parser_quic_client = subparsers.add_parser('quic_client', | |||
| help='run a QUIC client') | |||
| parser_quic_client.add_argument("--ca-certs", type=str, | |||
| help="load CA certificates from the specified file") | |||
| parser_quic_client.add_argument('clientlisten', type=str, help='Connection that the client listens on') | |||
| parser_quic_client.add_argument('clienttarget', type=str, help='Connection that the client connects to') | |||
| parser_quic_client.add_argument('clientlisten', type=str, | |||
| help='Connection that the client listens on') | |||
| parser_quic_client.add_argument('clienttarget', type=str, | |||
| help='Connection that the client connects to') | |||
| common_args(parser_quic_client) | |||
| parser_quic_client.set_defaults(func=cmd_quic_client) | |||
| class Tests(unittest.IsolatedAsyncioTestCase): | |||
| @@ -202,12 +238,20 @@ subjectAltName=DNS:localhost,server.example.com | |||
| return | |||
| # start the destination server | |||
| servsock = await asyncio.start_unix_server(echofun, path=unixservsock) | |||
| servsock = await asyncio.start_unix_server(echofun, | |||
| path=unixservsock) | |||
| # start up ntunnel quic processes | |||
| serv = await asyncio.create_subprocess_exec('ntunnel', 'quic_serv', '-k', self.privkey, '-c', self.cert, 'udp:127.0.0.1:%d' % port, 'unix:' + unixservsock) | |||
| client = await asyncio.create_subprocess_exec('ntunnel', 'quic_client', '--ca-certs', self.cert, 'unix:' + unixclientsock, 'udp:127.0.0.1:%d' % port) | |||
| serv = await asyncio.create_subprocess_exec('ntunnel', | |||
| 'quic_serv', | |||
| '-i', '1024', '-l', '.9', '-t', '15', | |||
| '-k', self.privkey, '-c', self.cert, | |||
| 'udp:127.0.0.1:%d' % port, 'unix:' + unixservsock) | |||
| client = await asyncio.create_subprocess_exec('ntunnel', | |||
| 'quic_client', | |||
| '--ca-certs', self.cert, | |||
| 'unix:' + unixclientsock, 'udp:127.0.0.1:%d' % port) | |||
| # make sure everything has started | |||
| await _awaitfile(unixservsock) | |||