mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-03-11 06:45:57 +03:00
This means that the TcpClient and the Connection (currently only ConnectionTcpFull) will no longer be concerned about handling errors, but the MTProtoSender will. The foundation of the library will now be based on asyncio.
66 lines
2.0 KiB
Python
66 lines
2.0 KiB
Python
import errno
|
|
import struct
|
|
from datetime import timedelta
|
|
from zlib import crc32
|
|
|
|
from .common import Connection
|
|
from ...errors import InvalidChecksumError
|
|
from ...extensions import TcpClient
|
|
|
|
|
|
class ConnectionTcpFull(Connection):
|
|
"""
|
|
Default Telegram mode. Sends 12 additional bytes and
|
|
needs to calculate the CRC value of the packet itself.
|
|
"""
|
|
def __init__(self, proxy=None, timeout=timedelta(seconds=5)):
|
|
super().__init__(proxy, timeout)
|
|
self._send_counter = 0
|
|
self.conn = TcpClient(proxy=self._proxy, timeout=self._timeout)
|
|
self.read = self.conn.read
|
|
self.write = self.conn.write
|
|
|
|
async def connect(self, ip, port):
|
|
try:
|
|
self.conn.connect(ip, port)
|
|
except OSError as e:
|
|
if e.errno == errno.EISCONN:
|
|
return # Already connected, no need to re-set everything up
|
|
else:
|
|
raise
|
|
|
|
self._send_counter = 0
|
|
|
|
def get_timeout(self):
|
|
return self.conn.timeout
|
|
|
|
def is_connected(self):
|
|
return self.conn.connected
|
|
|
|
async def close(self):
|
|
self.conn.close()
|
|
|
|
def clone(self):
|
|
return ConnectionTcpFull(self._proxy, self._timeout)
|
|
|
|
async def recv(self):
|
|
packet_len_seq = self.read(8) # 4 and 4
|
|
packet_len, seq = struct.unpack('<ii', packet_len_seq)
|
|
body = self.read(packet_len - 12)
|
|
checksum = struct.unpack('<I', self.read(4))[0]
|
|
|
|
valid_checksum = crc32(packet_len_seq + body)
|
|
if checksum != valid_checksum:
|
|
raise InvalidChecksumError(checksum, valid_checksum)
|
|
|
|
return body
|
|
|
|
async def send(self, message):
|
|
# https://core.telegram.org/mtproto#tcp-transport
|
|
# total length, sequence number, packet and checksum (CRC32)
|
|
length = len(message) + 12
|
|
data = struct.pack('<ii', length, self._send_counter) + message
|
|
crc = struct.pack('<I', crc32(data))
|
|
self._send_counter += 1
|
|
self.write(data + crc)
|