Fix Connection abstraction leak

This commit is contained in:
Lonami Exo 2019-02-21 10:41:33 +01:00
parent 96270bdc18
commit 6de7329ce7
5 changed files with 19 additions and 13 deletions

View File

@ -76,6 +76,9 @@ class Connection(abc.ABC):
await asyncio.open_connection(sock=s, loop=self._loop) await asyncio.open_connection(sock=s, loop=self._loop)
self._connected = True self._connected = True
self._init_conn()
await self._writer.drain()
self._send_task = self._loop.create_task(self._send_loop()) self._send_task = self._loop.create_task(self._send_loop())
self._recv_task = self._loop.create_task(self._recv_loop()) self._recv_task = self._loop.create_task(self._recv_loop())
@ -170,6 +173,18 @@ class Connection(abc.ABC):
except asyncio.CancelledError: except asyncio.CancelledError:
break break
@abc.abstractmethod
def _init_conn(self):
"""
This method will be called after `connect` is called.
After this method finishes, the writer will be drained.
Subclasses should make use of this if they need to send
data to Telegram to indicate which connection mode will
be used.
"""
raise NotImplemented
@abc.abstractmethod @abc.abstractmethod
def _send(self, data): def _send(self, data):
""" """

View File

@ -9,10 +9,8 @@ class ConnectionTcpAbridged(Connection):
only require 1 byte if the packet length is less than only require 1 byte if the packet length is less than
508 bytes (127 << 2, which is very common). 508 bytes (127 << 2, which is very common).
""" """
async def connect(self, timeout=None, ssl=None): def _init_conn(self):
await super().connect(timeout=timeout, ssl=ssl)
self._writer.write(b'\xef') self._writer.write(b'\xef')
await self._writer.drain()
def _write(self, data): def _write(self, data):
""" """

View File

@ -15,8 +15,7 @@ class ConnectionTcpFull(Connection):
ip, port, dc_id, loop=loop, loggers=loggers, proxy=proxy) ip, port, dc_id, loop=loop, loggers=loggers, proxy=proxy)
self._send_counter = 0 self._send_counter = 0
async def connect(self, timeout=None, ssl=None): def _init_conn(self):
await super().connect(timeout=timeout, ssl=ssl)
self._send_counter = 0 # Important or Telegram won't reply self._send_counter = 0 # Important or Telegram won't reply
def _send(self, data): def _send(self, data):

View File

@ -8,10 +8,8 @@ class ConnectionTcpIntermediate(Connection):
Intermediate mode between `ConnectionTcpFull` and `ConnectionTcpAbridged`. Intermediate mode between `ConnectionTcpFull` and `ConnectionTcpAbridged`.
Always sends 4 extra bytes for the packet length. Always sends 4 extra bytes for the packet length.
""" """
async def connect(self, timeout=None, ssl=None): def _init_conn(self):
await super().connect(timeout=timeout, ssl=ssl)
self._writer.write(b'\xee\xee\xee\xee') self._writer.write(b'\xee\xee\xee\xee')
await self._writer.drain()
def _send(self, data): def _send(self, data):
self._writer.write(struct.pack('<i', len(data)) + data) self._writer.write(struct.pack('<i', len(data)) + data)

View File

@ -24,10 +24,7 @@ class ConnectionTcpObfuscated(ConnectionTcpAbridged):
async def _read(self, n): async def _read(self, n):
return self._aes_decrypt.encrypt(await self._reader.readexactly(n)) return self._aes_decrypt.encrypt(await self._reader.readexactly(n))
async def connect(self, timeout=None, ssl=None): def _init_conn(self):
# FIXME: that's an abstraction leak
await Connection.connect(self, timeout=timeout, ssl=ssl)
# Obfuscated messages secrets cannot start with any of these # Obfuscated messages secrets cannot start with any of these
keywords = (b'PVrG', b'GET ', b'POST', b'\xee\xee\xee\xee') keywords = (b'PVrG', b'GET ', b'POST', b'\xee\xee\xee\xee')
while True: while True:
@ -53,7 +50,6 @@ class ConnectionTcpObfuscated(ConnectionTcpAbridged):
random[56:64] = self._compose_tail(bytes(random)) random[56:64] = self._compose_tail(bytes(random))
self._writer.write(random) self._writer.write(random)
await self._writer.drain()
# Next functions provide the variable parts of the connection handshake. # Next functions provide the variable parts of the connection handshake.
# This is necessary to modify obfuscated2 the way that MTProxy requires. # This is necessary to modify obfuscated2 the way that MTProxy requires.