Move HTTP codec

This commit is contained in:
Lonami Exo 2019-06-16 16:07:16 +02:00
parent f082a27ff8
commit ce37365bb7
9 changed files with 46 additions and 55 deletions

View File

@ -2,3 +2,4 @@ from .basecodec import BaseCodec
from .fullcodec import FullCodec from .fullcodec import FullCodec
from .intermediatecodec import IntermediateCodec from .intermediatecodec import IntermediateCodec
from .abridgedcodec import AbridgedCodec from .abridgedcodec import AbridgedCodec
from .httpcodec import HttpCodec

View File

@ -17,7 +17,7 @@ class AbridgedCodec(BaseCodec):
def tag(): def tag():
return b'\xef' # note: obfuscated tag is this 4 times 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 length = len(data) >> 2
if length < 127: if length < 127:
length = struct.pack('B', length) length = struct.pack('B', length)

View File

@ -24,7 +24,7 @@ class BaseCodec(abc.ABC):
raise NotImplementedError raise NotImplementedError
@abc.abstractmethod @abc.abstractmethod
def encode_packet(self, data): def encode_packet(self, data, ip, port):
""" """
Encodes the given data with the current codec instance. Encodes the given data with the current codec instance.

View File

@ -21,7 +21,7 @@ class FullCodec(BaseCodec):
def tag(): def tag():
return None return None
def encode_packet(self, data): def encode_packet(self, data, ip, port):
# https://core.telegram.org/mtproto#tcp-transport # https://core.telegram.org/mtproto#tcp-transport
# total length, sequence number, packet and checksum (CRC32) # total length, sequence number, packet and checksum (CRC32)
length = len(data) + 12 length = len(data) + 12

View 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)])

View File

@ -18,7 +18,7 @@ class IntermediateCodec(BaseCodec):
def tag(): def tag():
return b'\xee\xee\xee\xee' # same as obfuscate 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 return struct.pack('<i', len(data)) + data
def decode_header(self, header): def decode_header(self, header):
@ -33,7 +33,7 @@ class RandomizedIntermediateCodec(IntermediateCodec):
tag = None tag = None
obfuscate_tag = b'\xdd\xdd\xdd\xdd' 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) pad_size = random.randint(0, 3)
padding = os.urandom(pad_size) padding = os.urandom(pad_size)
return super().encode_packet(data + padding) return super().encode_packet(data + padding)

View File

@ -7,6 +7,7 @@ import sys
from ...errors import InvalidChecksumError from ...errors import InvalidChecksumError
from ... import helpers from ... import helpers
from .baseconnection import BaseConnection from .baseconnection import BaseConnection
from ..codec import HttpCodec
class AsyncioConnection(BaseConnection): class AsyncioConnection(BaseConnection):
@ -35,10 +36,10 @@ class AsyncioConnection(BaseConnection):
self._connected = False self._connected = False
self._obfuscation = None # TcpObfuscated and MTProxy self._obfuscation = None # TcpObfuscated and MTProxy
async def _connect(self, timeout=None, ssl=None): async def _connect(self, timeout=None):
if not self._proxy: if not self._proxy:
connect_coroutine = asyncio.open_connection( connect_coroutine = asyncio.open_connection(
self._ip, self._port, loop=self._loop, ssl=ssl) self._ip, self._port, loop=self._loop)
else: else:
import aiosocks import aiosocks
@ -62,8 +63,7 @@ class AsyncioConnection(BaseConnection):
proxy_auth=auth, proxy_auth=auth,
dst=(self._ip, self._port), dst=(self._ip, self._port),
remote_resolve=self._proxy.get('remote_resolve', True), remote_resolve=self._proxy.get('remote_resolve', True),
loop=self._loop, loop=self._loop
ssl=ssl
) )
self._reader, self._writer = await asyncio.wait_for( self._reader, self._writer = await asyncio.wait_for(
@ -79,11 +79,11 @@ class AsyncioConnection(BaseConnection):
def connected(self): def connected(self):
return self._connected return self._connected
async def connect(self, timeout=None, ssl=None): async def connect(self, timeout=None):
""" """
Establishes a connection with the server. Establishes a connection with the server.
""" """
await self._connect(timeout=timeout, ssl=ssl) await self._connect(timeout=timeout)
self._connected = True self._connected = True
async def disconnect(self): async def disconnect(self):

View File

@ -48,7 +48,7 @@ class BaseConnection(abc.ABC):
raise ConnectionError('Not connected') raise ConnectionError('Not connected')
# TODO Handle asyncio.CancelledError, IOError, Exception # 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: async with self._send_lock:
return await self._send(data) return await self._send(data)

View File

@ -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)