Skip to content

Commit a733ac4

Browse files
committed
quic udp
1 parent dc5a0ee commit a733ac4

File tree

3 files changed

+38
-12
lines changed

3 files changed

+38
-12
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ Protocols
116116
+-------------------+------------+------------+------------+------------+--------------+
117117
| ssh tunnel | || | | ssh:// |
118118
+-------------------+------------+------------+------------+------------+--------------+
119-
| quic ||| | | http+quic:// |
119+
| quic ||| | | http+quic:// |
120120
+-------------------+------------+------------+------------+------------+--------------+
121121
| iptables nat || | | | redir:// |
122122
+-------------------+------------+------------+------------+------------+--------------+

pproxy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from . import server
22

33
Connection = server.proxies_by_uri
4-
Server = server.proxy_by_uri
4+
Server = server.proxies_by_uri
55
Rule = server.compile_rule
66
DIRECT = server.DIRECT

pproxy/server.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ def close():
326326
except Exception:
327327
pass
328328
writer.close = close
329-
async def wait_open_connection(self, *args):
329+
async def wait_quic_connection(self):
330330
if self.handshake is not None:
331331
if not self.handshake.done():
332332
await self.handshake
@@ -340,27 +340,53 @@ def quic_event_received(s, event):
340340
elif isinstance(event, aioquic.quic.events.ConnectionTerminated):
341341
self.handshake = None
342342
self.quic_egress_acm = None
343+
elif isinstance(event, aioquic.quic.events.StreamDataReceived):
344+
if event.stream_id in self.udpmap:
345+
self.udpmap[event.stream_id](self.udp_packet_unpack(event.data))
346+
return
343347
super().quic_event_received(event)
344348
self.quic_egress_acm = aioquic.asyncio.connect(self.host_name, self.port, create_protocol=Protocol, configuration=self.quicclient)
345349
conn = await self.quic_egress_acm.__aenter__()
346350
await self.handshake
351+
async def udp_open_connection(self, host, port, data, addr, reply):
352+
await self.wait_quic_connection()
353+
conn = self.handshake.result()
354+
if addr in self.udpmap:
355+
stream_id = self.udpmap[addr]
356+
else:
357+
stream_id = conn._quic.get_next_available_stream_id(False)
358+
self.udpmap[addr] = stream_id
359+
self.udpmap[stream_id] = reply
360+
conn._quic._get_or_create_stream_for_send(stream_id)
361+
conn._quic.send_stream_data(stream_id, data, False)
362+
conn.transmit()
363+
async def wait_open_connection(self, *args):
364+
await self.wait_quic_connection()
347365
conn = self.handshake.result()
348366
stream_id = conn._quic.get_next_available_stream_id(False)
349367
conn._quic._get_or_create_stream_for_send(stream_id)
350368
reader, writer = conn._create_stream(stream_id)
351369
self.patch_writer(writer)
352370
return reader, writer
371+
async def udp_start_server(self, args):
372+
import aioquic.asyncio, aioquic.quic.events
373+
class Protocol(aioquic.asyncio.QuicConnectionProtocol):
374+
def quic_event_received(s, event):
375+
if isinstance(event, aioquic.quic.events.StreamDataReceived):
376+
stream_id = event.stream_id
377+
addr = ('quic '+self.bind, stream_id)
378+
event.sendto = lambda data, addr: (s._quic.send_stream_data(stream_id, data, False), s.transmit())
379+
event.get_extra_info = {}.get
380+
asyncio.ensure_future(datagram_handler(event, event.data, addr, **vars(self), **args))
381+
return
382+
super().quic_event_received(event)
383+
return await aioquic.asyncio.serve(self.host_name, self.port, configuration=self.quicserver, create_protocol=Protocol), None
353384
def start_server(self, args, stream_handler=stream_handler):
354385
import aioquic.asyncio
355386
def handler(reader, writer):
356387
self.patch_writer(writer)
357388
asyncio.ensure_future(stream_handler(reader, writer, **vars(self), **args))
358-
return aioquic.asyncio.serve(
359-
self.host_name,
360-
self.port,
361-
configuration=self.quicserver,
362-
stream_handler=handler
363-
)
389+
return aioquic.asyncio.serve(self.host_name, self.port, configuration=self.quicserver, stream_handler=handler)
364390

365391
class ProxySSH(ProxySimple):
366392
def __init__(self, **kw):
@@ -654,19 +680,19 @@ def main():
654680
if option.sslclient:
655681
option.sslclient.load_cert_chain(*sslfile)
656682
option.sslserver.load_cert_chain(*sslfile)
657-
for option in args.listen+args.rserver:
683+
for option in args.listen+args.ulisten+args.rserver+args.urserver:
658684
if isinstance(option, ProxyQUIC):
659685
option.quicserver.load_cert_chain(*sslfile)
660686
if isinstance(option, ProxyBackward) and isinstance(option.backward, ProxyQUIC):
661687
option.backward.quicserver.load_cert_chain(*sslfile)
662-
elif any(map(lambda o: o.sslclient or isinstance(o, ProxyQUIC), args.listen)):
688+
elif any(map(lambda o: o.sslclient or isinstance(o, ProxyQUIC), args.listen+args.ulisten)):
663689
print('You must specify --ssl to listen in ssl mode')
664690
return
665691
if args.test:
666692
asyncio.get_event_loop().run_until_complete(test_url(args.test, args.rserver))
667693
return
668694
if not args.listen and not args.ulisten:
669-
args.listen.append(proxy_by_uri('http+socks4+socks5://:8080/'))
695+
args.listen.append(proxies_by_uri('http+socks4+socks5://:8080/'))
670696
args.httpget = {}
671697
if args.pac:
672698
pactext = 'function FindProxyForURL(u,h){' + (f'var b=/^(:?{args.block.__self__.pattern})$/i;if(b.test(h))return "";' if args.block else '')

0 commit comments

Comments
 (0)