mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-03-12 15:38:03 +03:00
Move HTTP codec
This commit is contained in:
parent
f082a27ff8
commit
ce37365bb7
|
@ -2,3 +2,4 @@ from .basecodec import BaseCodec
|
|||
from .fullcodec import FullCodec
|
||||
from .intermediatecodec import IntermediateCodec
|
||||
from .abridgedcodec import AbridgedCodec
|
||||
from .httpcodec import HttpCodec
|
||||
|
|
|
@ -17,7 +17,7 @@ class AbridgedCodec(BaseCodec):
|
|||
def tag():
|
||||
return b'\xef' # note: obfuscated tag is this 4 times
|
||||
|
||||
def encode_packet(self, data):
|
||||
def encode_packet(self, data, ip, port):
|
||||
length = len(data) >> 2
|
||||
if length < 127:
|
||||
length = struct.pack('B', length)
|
||||
|
|
|
@ -24,7 +24,7 @@ class BaseCodec(abc.ABC):
|
|||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def encode_packet(self, data):
|
||||
def encode_packet(self, data, ip, port):
|
||||
"""
|
||||
Encodes the given data with the current codec instance.
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class FullCodec(BaseCodec):
|
|||
def tag():
|
||||
return None
|
||||
|
||||
def encode_packet(self, data):
|
||||
def encode_packet(self, data, ip, port):
|
||||
# https://core.telegram.org/mtproto#tcp-transport
|
||||
# total length, sequence number, packet and checksum (CRC32)
|
||||
length = len(data) + 12
|
||||
|
|
33
telethon/network/codec/httpcodec.py
Normal file
33
telethon/network/codec/httpcodec.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
from .basecodec import BaseCodec
|
||||
|
||||
|
||||
SSL_PORT = 443
|
||||
|
||||
|
||||
class HttpCodec(BaseCodec):
|
||||
@staticmethod
|
||||
def header_length():
|
||||
return 4
|
||||
|
||||
@staticmethod
|
||||
def tag():
|
||||
return None
|
||||
|
||||
def encode_packet(self, data, ip, port):
|
||||
return ('POST /api HTTP/1.1\r\n'
|
||||
'Host: {}:{}\r\n'
|
||||
'Content-Type: application/x-www-form-urlencoded\r\n'
|
||||
'Connection: keep-alive\r\n'
|
||||
'Keep-Alive: timeout=100000, max=10000000\r\n'
|
||||
'Content-Length: {}\r\n\r\n'
|
||||
.format(ip, port, len(data))
|
||||
.encode('ascii') + data)
|
||||
|
||||
def decode_header(self, header):
|
||||
if not header.endswith(b'\r\n\r\n'):
|
||||
return -1
|
||||
|
||||
header = header.lower()
|
||||
start = header.index(b'content-length: ') + 16
|
||||
print(header)
|
||||
return int(header[start:header.index(b'\r', start)])
|
|
@ -18,7 +18,7 @@ class IntermediateCodec(BaseCodec):
|
|||
def tag():
|
||||
return b'\xee\xee\xee\xee' # same as obfuscate tag
|
||||
|
||||
def encode_packet(self, data):
|
||||
def encode_packet(self, data, ip, port):
|
||||
return struct.pack('<i', len(data)) + data
|
||||
|
||||
def decode_header(self, header):
|
||||
|
@ -33,7 +33,7 @@ class RandomizedIntermediateCodec(IntermediateCodec):
|
|||
tag = None
|
||||
obfuscate_tag = b'\xdd\xdd\xdd\xdd'
|
||||
|
||||
def encode_packet(self, data):
|
||||
def encode_packet(self, data, ip, port):
|
||||
pad_size = random.randint(0, 3)
|
||||
padding = os.urandom(pad_size)
|
||||
return super().encode_packet(data + padding)
|
||||
|
|
|
@ -7,6 +7,7 @@ import sys
|
|||
from ...errors import InvalidChecksumError
|
||||
from ... import helpers
|
||||
from .baseconnection import BaseConnection
|
||||
from ..codec import HttpCodec
|
||||
|
||||
|
||||
class AsyncioConnection(BaseConnection):
|
||||
|
@ -35,10 +36,10 @@ class AsyncioConnection(BaseConnection):
|
|||
self._connected = False
|
||||
self._obfuscation = None # TcpObfuscated and MTProxy
|
||||
|
||||
async def _connect(self, timeout=None, ssl=None):
|
||||
async def _connect(self, timeout=None):
|
||||
if not self._proxy:
|
||||
connect_coroutine = asyncio.open_connection(
|
||||
self._ip, self._port, loop=self._loop, ssl=ssl)
|
||||
self._ip, self._port, loop=self._loop)
|
||||
else:
|
||||
import aiosocks
|
||||
|
||||
|
@ -62,8 +63,7 @@ class AsyncioConnection(BaseConnection):
|
|||
proxy_auth=auth,
|
||||
dst=(self._ip, self._port),
|
||||
remote_resolve=self._proxy.get('remote_resolve', True),
|
||||
loop=self._loop,
|
||||
ssl=ssl
|
||||
loop=self._loop
|
||||
)
|
||||
|
||||
self._reader, self._writer = await asyncio.wait_for(
|
||||
|
@ -79,11 +79,11 @@ class AsyncioConnection(BaseConnection):
|
|||
def connected(self):
|
||||
return self._connected
|
||||
|
||||
async def connect(self, timeout=None, ssl=None):
|
||||
async def connect(self, timeout=None):
|
||||
"""
|
||||
Establishes a connection with the server.
|
||||
"""
|
||||
await self._connect(timeout=timeout, ssl=ssl)
|
||||
await self._connect(timeout=timeout)
|
||||
self._connected = True
|
||||
|
||||
async def disconnect(self):
|
||||
|
|
|
@ -48,7 +48,7 @@ class BaseConnection(abc.ABC):
|
|||
raise ConnectionError('Not connected')
|
||||
|
||||
# TODO Handle asyncio.CancelledError, IOError, Exception
|
||||
data = self._codec.encode_packet(data)
|
||||
data = self._codec.encode_packet(data, self._ip, self._port)
|
||||
async with self._send_lock:
|
||||
return await self._send(data)
|
||||
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
import asyncio
|
||||
|
||||
|
||||
SSL_PORT = 443
|
||||
|
||||
|
||||
class HttpPacketCodec:
|
||||
tag = None
|
||||
obfuscate_tag = None
|
||||
|
||||
def __init__(self):
|
||||
raise NotImplementedError('Not migrated yet')
|
||||
|
||||
def encode_packet(self, data):
|
||||
return ('POST /api HTTP/1.1\r\n'
|
||||
'Host: {}:{}\r\n'
|
||||
'Content-Type: application/x-www-form-urlencoded\r\n'
|
||||
'Connection: keep-alive\r\n'
|
||||
'Keep-Alive: timeout=100000, max=10000000\r\n'
|
||||
'Content-Length: {}\r\n\r\n'
|
||||
.format(self._conn._ip, self._conn._port, len(data))
|
||||
.encode('ascii') + data)
|
||||
|
||||
async def read_packet(self, reader):
|
||||
while True:
|
||||
line = await reader.readline()
|
||||
if not line or line[-1] != b'\n':
|
||||
raise asyncio.IncompleteReadError(line, None)
|
||||
|
||||
if line.lower().startswith(b'content-length: '):
|
||||
await reader.readexactly(2)
|
||||
length = int(line[16:-2])
|
||||
return await reader.readexactly(length)
|
||||
|
||||
|
||||
class ConnectionHttp:
|
||||
packet_codec = HttpPacketCodec
|
||||
|
||||
def __init__(self):
|
||||
raise NotImplementedError('Not migrated yet')
|
||||
|
||||
async def connect(self, timeout=None, ssl=None):
|
||||
await super().connect(timeout=timeout, ssl=self._port == SSL_PORT)
|
Loading…
Reference in New Issue
Block a user