Skip to content

Commit cb2669b

Browse files
committed
quic:// protocol
1 parent 19622a0 commit cb2669b

File tree

3 files changed

+365
-406
lines changed

3 files changed

+365
-406
lines changed

pproxy/__init__.py

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

3-
Connection = server.ProxyURI.compile_relay
4-
DIRECT = server.ProxyURI.DIRECT
5-
Server = server.ProxyURI.compile
6-
Rule = server.ProxyURI.compile_rule
3+
Connection = server.proxies_by_uri
4+
Server = server.proxy_by_uri
5+
Rule = server.compile_rule
6+
DIRECT = server.DIRECT

pproxy/proto.py

Lines changed: 4 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ async def channel(self, reader, writer, stat_bytes, stat_conn):
5757
try:
5858
stat_conn(1)
5959
while True:
60-
data = await reader.read_()
60+
data = await reader.read(65536)
6161
if not data:
6262
break
6363
if stat_bytes is None:
@@ -327,7 +327,7 @@ async def http_channel(self, reader, writer, stat_bytes, stat_conn):
327327
try:
328328
stat_conn(1)
329329
while True:
330-
data = await reader.read_()
330+
data = await reader.read(65536)
331331
if not data:
332332
break
333333
if b'\r\n' in data and HTTP_LINE.match(data.split(b'\r\n', 1)[0].decode()):
@@ -513,85 +513,6 @@ class Echo(Transparent):
513513
def query_remote(self, sock):
514514
return 'echo', 0
515515

516-
class Pack(BaseProtocol):
517-
def reuse(self):
518-
return True
519-
def get_handler(self, reader, writer, verbose, tcp_handler=None, udp_handler=None):
520-
class Handler:
521-
def __init__(self):
522-
self.sessions = {}
523-
self.udpmap = {}
524-
self.closed = False
525-
self.ready = False
526-
asyncio.ensure_future(self.reader_handler())
527-
def __bool__(self):
528-
return not self.closed
529-
async def reader_handler(self):
530-
try:
531-
while True:
532-
try:
533-
header = (await reader.readexactly(1))[0]
534-
except Exception:
535-
raise Exception('Connection closed')
536-
sid = await reader.read_n(8)
537-
if header in (0x01, 0x03, 0x04, 0x11, 0x13, 0x14):
538-
host_name, port, _ = await socks_address_stream(reader, header)
539-
if (header & 0x10 == 0) and tcp_handler:
540-
remote_reader, remote_writer = self.get_streams(sid)
541-
asyncio.ensure_future(tcp_handler(remote_reader, remote_writer, host_name, port))
542-
elif (header & 0x10 != 0) and udp_handler:
543-
self.get_datagram(sid, host_name, port)
544-
elif header in (0x20, 0x30):
545-
datalen = int.from_bytes(await reader.read_n(2), 'big')
546-
data = await reader.read_n(datalen)
547-
if header == 0x20 and sid in self.sessions:
548-
self.sessions[sid].feed_data(data)
549-
elif header == 0x30 and sid in self.udpmap and udp_handler:
550-
host_name, port, sendto = self.udpmap[sid]
551-
asyncio.ensure_future(udp_handler(sendto, data, host_name, port, sid))
552-
elif header == 0x40:
553-
if sid in self.sessions:
554-
self.sessions.pop(sid).feed_eof()
555-
else:
556-
raise Exception(f'Unknown header {header}')
557-
except Exception as ex:
558-
if not isinstance(ex, asyncio.TimeoutError) and not str(ex).startswith('Connection closed'):
559-
verbose(f'{str(ex) or "Unsupported protocol"}')
560-
finally:
561-
for sid, session in self.sessions.items():
562-
session.feed_eof()
563-
try: writer.close()
564-
except Exception: pass
565-
self.closed = True
566-
def get_streams(self, sid):
567-
self.sessions[sid] = asyncio.StreamReader()
568-
class Writer():
569-
def write(self, data):
570-
while len(data) >= 32*1024:
571-
writer.write(b'\x20'+sid+(32*1024).to_bytes(2,'big')+data[:32*1024])
572-
data = data[32*1024:]
573-
if data:
574-
writer.write(b'\x20'+sid+len(data).to_bytes(2,'big')+data)
575-
def drain(self):
576-
return writer.drain()
577-
def close(self):
578-
if not writer.transport.is_closing():
579-
writer.write(b'\x40'+sid)
580-
return self.sessions[sid], Writer()
581-
def connect(self, host_name, port):
582-
self.ready = True
583-
sid = os.urandom(8)
584-
writer.write(b'\x03' + sid + packstr(host_name.encode()) + port.to_bytes(2, 'big'))
585-
return self.get_streams(sid)
586-
def get_datagram(self, sid, host_name, port):
587-
def sendto(data):
588-
if data:
589-
writer.write(b'\x30'+sid+len(data).to_bytes(2,'big')+data)
590-
self.udpmap[sid] = (host_name, port, sendto)
591-
return self.udpmap[sid]
592-
writer.get_extra_info('socket').setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
593-
return Handler()
594-
595516
async def accept(protos, reader, **kw):
596517
for proto in protos:
597518
try:
@@ -612,7 +533,7 @@ def udp_accept(protos, data, **kw):
612533
return (proto,) + ret
613534
raise Exception(f'Unsupported protocol {data[:10]}')
614535

615-
MAPPINGS = dict(direct=Direct, http=HTTP, httponly=HTTPOnly, ssh=SSH, socks5=Socks5, socks4=Socks4, socks=Socks5, ss=SS, ssr=SSR, redir=Redir, pf=Pf, tunnel=Tunnel, echo=Echo, pack=Pack, ws=WS, trojan=Trojan, ssl='', secure='')
536+
MAPPINGS = dict(direct=Direct, http=HTTP, httponly=HTTPOnly, ssh=SSH, socks5=Socks5, socks4=Socks4, socks=Socks5, ss=SS, ssr=SSR, redir=Redir, pf=Pf, tunnel=Tunnel, echo=Echo, ws=WS, trojan=Trojan, ssl='', secure='', quic='')
616537
MAPPINGS['in'] = ''
617538

618539
def get_protos(rawprotos):
@@ -662,7 +583,7 @@ def abort(self):
662583
async def channel():
663584
try:
664585
while True:
665-
data = await reader.read_()
586+
data = await reader.read(65536)
666587
if not data:
667588
break
668589
ssl.data_received(data)

0 commit comments

Comments
 (0)