From 7d22608fbd465c3c9a55cfec215403e3273ac272 Mon Sep 17 00:00:00 2001 From: Anton Grigoryev Date: Thu, 26 Feb 2015 14:03:41 +0300 Subject: [PATCH] TL schema parsing. PQ factorization TODO: dynamic methods and constructors generator --- mtproto.py | 111 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 20 deletions(-) diff --git a/mtproto.py b/mtproto.py index ac847d01..d8a33f28 100644 --- a/mtproto.py +++ b/mtproto.py @@ -4,12 +4,13 @@ Created on Tue Sep 2 19:26:15 2014 @author: agrigoryev """ -import binascii +from binascii import crc32 import struct import socket import re from datetime import datetime import sys +import io current_module = sys.modules[__name__] @@ -18,33 +19,36 @@ def vis(bs): n = len(bs) // 8 for i in range(n): print(" ".join(["%02X" % b for b in bs[i*8:i*8+8]])) - print(" ".join(["%02X" % b for b in bs[i*8+8:]])) + print(" ".join(["%02X" % b for b in bs[i*8+8:]])+"\n") class TlElement: def __init__(self, type_string): - tl_re = re.compile("""([a-z]\w*) #name - \#([0-9a-f]{8}) #id - \s+(.*)\s+ #arguments list - =\s+([A-Z]\w*); #result""", re.X) + tl_re = re.compile("""([a-z]\w*) #name + \#?([0-9a-f]{8})?\s+ #id + (\{.*\}\s+)? #subtype + (.*)\s+ #arguments list + =\s+([A-Z]\w*) #result + (\s+(\w+))?; #subresult""", re.X) assert isinstance(type_string, str) x = tl_re.match(type_string) if x is not None: self.name = x.groups()[0] - self.id = x.groups()[1] - self.args = self.get_arg_list(x.groups()[2]) - self.result = x.groups()[3] + if x.groups()[1] is not None: + self.id = int(x.groups()[1], 16) + else: + self.id = crc32(re.sub("(#[0-9a-f]{8})|([;\n{}])", "", type_string).encode()) + self.args = self.get_arg_list(x.groups()[3]) + self.result = x.groups()[4] else: raise SyntaxError @staticmethod def get_arg_list(arg_string): - arg_re = re.compile("(\w+):(\w+)(<(\w+)>)?") + arg_re = re.compile("([\w0-9]+)?:?([\w0-9]+)(<([\w0-0]+)>)?") res = [] for s in arg_re.findall(arg_string): - d = {'name': s[0], 'type': s[1]} - if s[2]: - d['subtype'] = s[3] + d = {'name': s[0], 'type': s[1], 'subtype': s[3] if s[2] is not None else None} res.append(d) return res @@ -65,7 +69,7 @@ class TL: try: z = TlElement(line) self.obj_dict_id[z.id] = z - self.obj_dict_name[z.name] = z + self.obj_dict_name[z.result] = z except SyntaxError: pass @@ -81,6 +85,7 @@ class TL: except SyntaxError: pass + def tl_serialize(self, elem, kwargs): assert isinstance(elem, TlElement) for arg in elem.args: @@ -94,6 +99,69 @@ class TL: answer = session.recv_message() return deserialize(answer, TL) + def class_generator(self, tl_element): + class Dummy: + def __init__(self, bstring): + assert isinstance(bstring, bytes) + f = io.BytesIO(bstring) + dict = self.deserialize(f, type=tl_element.type) + + + def deserialize(self, bytes_io, type=None, subtype=None): + assert isinstance(bytes_io, io.BytesIO) + if type == 'int': + x = struct.unpack('>') vis(message) - print() #self.number += 1 data = self.header(message) + message step1 = struct.pack(' 0: # if we have smth. in the socket packet_length = struct.unpack("