mirror of
https://github.com/Flowseal/tg-ws-proxy.git
synced 2026-10-21 02:58:45 +00:00
Optimizations
This commit is contained in:
1 parent
3c54c54d36
commit
3fa281625f
3 files changed
+29
-12
No files matched your search
+5
-2
@@ -72,11 +72,14 @@ class MsgSplitter:
|
|||||||
if packet_len is None:
|
if packet_len is None:
|
||||||
break
|
break
|
||||||
if packet_len <= 0:
|
if packet_len <= 0:
|
||||||
parts.append(bytes(self._cipher_buf[offset:]))
|
parts.append(bytes(self._cipher_buf) if offset == 0 else bytes(self._cipher_buf[offset:]))
|
||||||
offset = buf_len
|
offset = buf_len
|
||||||
self._disabled = True
|
self._disabled = True
|
||||||
break
|
break
|
||||||
parts.append(bytes(self._cipher_buf[offset:offset + packet_len]))
|
if offset == 0 and packet_len == buf_len:
|
||||||
|
parts.append(bytes(self._cipher_buf))
|
||||||
|
else:
|
||||||
|
parts.append(bytes(self._cipher_buf[offset:offset + packet_len]))
|
||||||
offset += packet_len
|
offset += packet_len
|
||||||
|
|
||||||
if offset:
|
if offset:
|
||||||
|
|||||||
+22
-8
@@ -20,6 +20,7 @@ from .utils import create_ssl_context
|
|||||||
|
|
||||||
STREAM_RECEIVE_WINDOW = 256 * 1024
|
STREAM_RECEIVE_WINDOW = 256 * 1024
|
||||||
CONNECTION_RECEIVE_WINDOW = 4 * 1024 * 1024
|
CONNECTION_RECEIVE_WINDOW = 4 * 1024 * 1024
|
||||||
|
IO_BATCH_SIZE = 64 * 1024
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=1)
|
@lru_cache(maxsize=1)
|
||||||
@@ -36,6 +37,7 @@ class _ResponseStream(httpx.AsyncByteStream):
|
|||||||
self.read_timeout = read_timeout
|
self.read_timeout = read_timeout
|
||||||
self.changed = asyncio.Event()
|
self.changed = asyncio.Event()
|
||||||
self.chunks = deque()
|
self.chunks = deque()
|
||||||
|
self.consumed_credit = 0
|
||||||
self.headers = None
|
self.headers = None
|
||||||
self.response_started = None
|
self.response_started = None
|
||||||
self.error = None
|
self.error = None
|
||||||
@@ -100,6 +102,8 @@ class _Connection:
|
|||||||
data = self.h2.data_to_send()
|
data = self.h2.data_to_send()
|
||||||
if data:
|
if data:
|
||||||
self.writer.write(data)
|
self.writer.write(data)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
async def drain(self):
|
async def drain(self):
|
||||||
try:
|
try:
|
||||||
@@ -127,11 +131,12 @@ class _Connection:
|
|||||||
async def read_loop(self):
|
async def read_loop(self):
|
||||||
try:
|
try:
|
||||||
while self.error is None:
|
while self.error is None:
|
||||||
data = await self.reader.read(64 * 1024)
|
data = await self.reader.read(IO_BATCH_SIZE)
|
||||||
if not data:
|
if not data:
|
||||||
raise httpx.ReadError('H2 peer closed the connection')
|
raise httpx.ReadError('H2 peer closed the connection')
|
||||||
events = self.h2.receive_data(data)
|
events = self.h2.receive_data(data)
|
||||||
terminated = any(isinstance(e, ConnectionTerminated) for e in events)
|
terminated = any(isinstance(e, ConnectionTerminated) for e in events)
|
||||||
|
connection_credit = 0
|
||||||
for event in events:
|
for event in events:
|
||||||
if isinstance(event, RemoteSettingsChanged):
|
if isinstance(event, RemoteSettingsChanged):
|
||||||
self.settings_received = True
|
self.settings_received = True
|
||||||
@@ -145,7 +150,7 @@ class _Connection:
|
|||||||
stream = self.streams.get(getattr(event, 'stream_id', None))
|
stream = self.streams.get(getattr(event, 'stream_id', None))
|
||||||
if isinstance(event, DataReceived):
|
if isinstance(event, DataReceived):
|
||||||
if event.flow_controlled_length and not terminated:
|
if event.flow_controlled_length and not terminated:
|
||||||
self.h2.increment_flow_control_window(event.flow_controlled_length)
|
connection_credit += event.flow_controlled_length
|
||||||
if stream is not None:
|
if stream is not None:
|
||||||
if event.data:
|
if event.data:
|
||||||
stream.chunks.append((event.data, event.flow_controlled_length))
|
stream.chunks.append((event.data, event.flow_controlled_length))
|
||||||
@@ -164,8 +169,10 @@ class _Connection:
|
|||||||
self.changed.set()
|
self.changed.set()
|
||||||
if stream is not None:
|
if stream is not None:
|
||||||
stream.changed.set()
|
stream.changed.set()
|
||||||
self.flush()
|
if connection_credit:
|
||||||
await self.drain()
|
self.h2.increment_flow_control_window(connection_credit)
|
||||||
|
if self.flush():
|
||||||
|
await self.drain()
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
self.fail(httpx.ReadError('H2 reader stopped'))
|
self.fail(httpx.ReadError('H2 reader stopped'))
|
||||||
raise
|
raise
|
||||||
@@ -202,7 +209,7 @@ class _Connection:
|
|||||||
self.changed.clear()
|
self.changed.clear()
|
||||||
self.check_error()
|
self.check_error()
|
||||||
stream.check_error()
|
stream.check_error()
|
||||||
count = min(len(data) - offset, self.h2.max_outbound_frame_size,
|
count = min(len(data) - offset, IO_BATCH_SIZE,
|
||||||
self.h2.local_flow_control_window(stream.stream_id))
|
self.h2.local_flow_control_window(stream.stream_id))
|
||||||
if count <= 0:
|
if count <= 0:
|
||||||
try:
|
try:
|
||||||
@@ -210,8 +217,11 @@ class _Connection:
|
|||||||
except asyncio.TimeoutError as exc:
|
except asyncio.TimeoutError as exc:
|
||||||
raise httpx.WriteTimeout('H2 upload flow control timed out') from exc
|
raise httpx.WriteTimeout('H2 upload flow control timed out') from exc
|
||||||
continue
|
continue
|
||||||
self.h2.send_data(stream.stream_id, data[offset:offset + count])
|
batch_end = offset + count
|
||||||
offset += count
|
while offset < batch_end:
|
||||||
|
frame_end = min(batch_end, offset + self.h2.max_outbound_frame_size)
|
||||||
|
self.h2.send_data(stream.stream_id, data[offset:frame_end])
|
||||||
|
offset = frame_end
|
||||||
self.flush()
|
self.flush()
|
||||||
await self.drain()
|
await self.drain()
|
||||||
self.h2.end_stream(stream.stream_id)
|
self.h2.end_stream(stream.stream_id)
|
||||||
@@ -259,8 +269,12 @@ class _Connection:
|
|||||||
|
|
||||||
def consumed(self, stream, credit):
|
def consumed(self, stream, credit):
|
||||||
if credit and not stream.ended and not stream.closed and self.error is None:
|
if credit and not stream.ended and not stream.closed and self.error is None:
|
||||||
|
stream.consumed_credit += credit
|
||||||
|
if stream.chunks and stream.consumed_credit < IO_BATCH_SIZE:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
self.h2.increment_flow_control_window(credit, stream.stream_id)
|
self.h2.increment_flow_control_window(stream.consumed_credit, stream.stream_id)
|
||||||
|
stream.consumed_credit = 0
|
||||||
self.flush()
|
self.flush()
|
||||||
except StreamClosedError:
|
except StreamClosedError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1016,8 +1016,8 @@ class H2WireTest(unittest.IsolatedAsyncioTestCase):
|
|||||||
self.respond(request, b's' * (1024 * 1024))
|
self.respond(request, b's' * (1024 * 1024))
|
||||||
response = await opening
|
response = await opening
|
||||||
fast, fast_request = await self.post()
|
fast, fast_request = await self.post()
|
||||||
self.respond(fast_request, b'f' * (128 * 1024))
|
self.respond(fast_request, b'f' * (4 * 1024 * 1024))
|
||||||
self.assertEqual(await asyncio.wait_for(fast, .5), b'f' * (128 * 1024))
|
self.assertEqual(await asyncio.wait_for(fast, 2), b'f' * (4 * 1024 * 1024))
|
||||||
stream = self.transport.connection.streams[request[1]]
|
stream = self.transport.connection.streams[request[1]]
|
||||||
self.assertLessEqual(sum(len(data) for data, _ in stream.chunks), STREAM_RECEIVE_WINDOW)
|
self.assertLessEqual(sum(len(data) for data, _ in stream.chunks), STREAM_RECEIVE_WINDOW)
|
||||||
await response.aclose()
|
await response.aclose()
|
||||||
|
|||||||
Reference in new issue
Block a user