2018-05-10 15:22:19 +03:00
|
|
|
import struct
|
|
|
|
from zlib import crc32
|
|
|
|
|
2019-03-12 03:12:55 +03:00
|
|
|
from .connection import Connection, PacketCodec
|
2023-03-12 19:27:22 +03:00
|
|
|
from ...errors import InvalidChecksumError, InvalidBufferError
|
2018-05-10 15:22:19 +03:00
|
|
|
|
|
|
|
|
2019-03-12 03:12:55 +03:00
|
|
|
class FullPacketCodec(PacketCodec):
|
|
|
|
tag = None
|
2018-05-10 15:22:19 +03:00
|
|
|
|
2019-05-03 14:59:17 +03:00
|
|
|
def __init__(self, connection):
|
|
|
|
super().__init__(connection)
|
2018-10-03 15:15:51 +03:00
|
|
|
self._send_counter = 0 # Important or Telegram won't reply
|
|
|
|
|
2019-03-12 03:12:55 +03:00
|
|
|
def encode_packet(self, data):
|
2018-09-27 20:22:35 +03:00
|
|
|
# https://core.telegram.org/mtproto#tcp-transport
|
|
|
|
# total length, sequence number, packet and checksum (CRC32)
|
|
|
|
length = len(data) + 12
|
|
|
|
data = struct.pack('<ii', length, self._send_counter) + data
|
|
|
|
crc = struct.pack('<I', crc32(data))
|
|
|
|
self._send_counter += 1
|
2019-03-12 03:12:55 +03:00
|
|
|
return data + crc
|
2018-05-10 15:22:19 +03:00
|
|
|
|
2019-03-12 03:12:55 +03:00
|
|
|
async def read_packet(self, reader):
|
|
|
|
packet_len_seq = await reader.readexactly(8) # 4 and 4
|
2018-05-10 15:22:19 +03:00
|
|
|
packet_len, seq = struct.unpack('<ii', packet_len_seq)
|
2023-03-12 19:27:22 +03:00
|
|
|
if packet_len < 0 and seq < 0:
|
|
|
|
# It has been observed that the length and seq can be -429,
|
|
|
|
# followed by the body of 4 bytes also being -429.
|
|
|
|
# See https://github.com/LonamiWebs/Telethon/issues/4042.
|
|
|
|
body = await reader.readexactly(4)
|
|
|
|
raise InvalidBufferError(body)
|
2023-04-29 13:33:32 +03:00
|
|
|
elif packet_len < 8:
|
|
|
|
# Currently unknown why packet_len may be less than 8 but not negative.
|
|
|
|
# Attempting to `readexactly` with less than 0 fails without saying what
|
|
|
|
# the number was which is less helpful.
|
|
|
|
raise InvalidBufferError(packet_len_seq)
|
2023-03-12 19:27:22 +03:00
|
|
|
|
2019-03-12 03:12:55 +03:00
|
|
|
body = await reader.readexactly(packet_len - 8)
|
2018-06-06 22:42:48 +03:00
|
|
|
checksum = struct.unpack('<I', body[-4:])[0]
|
|
|
|
body = body[:-4]
|
2018-05-10 15:22:19 +03:00
|
|
|
|
|
|
|
valid_checksum = crc32(packet_len_seq + body)
|
|
|
|
if checksum != valid_checksum:
|
|
|
|
raise InvalidChecksumError(checksum, valid_checksum)
|
|
|
|
|
|
|
|
return body
|
2019-03-12 03:12:55 +03:00
|
|
|
|
|
|
|
|
|
|
|
class ConnectionTcpFull(Connection):
|
|
|
|
"""
|
|
|
|
Default Telegram mode. Sends 12 additional bytes and
|
|
|
|
needs to calculate the CRC value of the packet itself.
|
|
|
|
"""
|
|
|
|
packet_codec = FullPacketCodec
|