Kenny Cason Kenny Cason - 2 months ago 10
Python Question

De-Serializing msg_container objects returned from the telegram.org server

I'm having trouble de-serializing a

msg_container
object. The issue seems to be my understanding of where the
flags
field is located in the
message
as it doesn't make sense to me. My assumptions below come from reading this page: https://core.telegram.org/mtproto/TL

Here is what I am seeing, I'm hoping someone can clarify.

A response from the telegram server looks like this:

('server_answer: ', '\xdc\xf8\xf1s\x02\x00\x00\x00\x018\xcb\x8cCu\xcdW\x01\x00\x00\x00\x1c\x00\x00\x00\x08\t\xc2\x9e\x00t\xbe?Cu\xcdW\x82\x0e:\x11\xe0\xda\xed\x05\xd7\xbezI4\x05Tf\x01\xdc\xcb\x8cCu\xcdW\x02\x00\x00\x00\x14\x00\x00\x00Y\xb4\xd6b\x15\xc4\xb5\x1c\x01\x00\x00\x00\x00t\xbe?Cu\xcdW')

0 | DC F8 F1 73 02 00 00 00
8 | 01 38 CB 8C 43 75 CD 57
16 | 01 00 00 00 1C 00 00 00
24 | 08 09 C2 9E 00 74 BE 3F
32 | 43 75 CD 57 82 0E 3A 11
40 | E0 DA ED 05 D7 BE 7A 49
48 | 34 05 54 66 01 DC CB 8C
56 | 43 75 CD 57 02 00 00 00
64 | 14 00 00 00 59 B4 D6 62
72 | 15 C4 B5 1C 01 00 00 00
80 | 00 74 BE 3F 43 75 CD 57


Which indicates a
MessageContainer
object, which looks like this:

msg_container#73f1f8dc messages:vector<message> = MessageContainer;


(Note: 73f1f8dc is the first four bytes returned, in little-endian order)

Since a
msg_container
is a
vector
of
messages
the next integer is the
message
count, which is
00 00 00 02
, so there are two messages in this vector.

A
message
looks like this:

message#c09be45f flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int = Message;
messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message;


So I am assuming the next four bytes will be the first parameter in the first message, which is the
flags
field. But the value of that four bytes is
8c cb 38 01
which is 2362128385L as an unsigned integer, which is suspiciously large for a simple bit mask. Plus, if I use this value to de-serialize the optional parameters from the rest of the byte stream they don't make sense and eventually fail with a type mismatch. I've tried the
flags
field as a signed integer as well with similar results.

What is incorrect about my understanding of how the telegram server responds with msg_container objects?

Answer

Here is a simple approach to use in handling messages packed in a container:

Container_type_header
Content_count
[messages]

Each message is packed like so:

msgs_id
seq_no
mgs_len
msg_body

given your sample data:

DCF8F173 --> container_type_header
02000000 --> message_count_in_container

0138CB8C4375CD57 --> msg_id of first message
01000000 --> seq_no of first message
1C000000 --> length of first message; 1C == 28 bytes
0809C29E0074BE3F4375CD57820E3A11E0DAED05D7BE7A4934055466 --> 28 byte msg_body

01DCCB8C4375CD57 --> msg_id of second message
02000000 --> seq_number of second message
14000000 --> lenght of second message; 14 == 20 bytes
59B4D66215C4B51C010000000074BE3F4375CD57 --> 20 byte msg_body

when decoded first message gives:

0809C29E0074BE3F4375CD57820E3A11E0DAED05D7BE7A4934055466

New_Session_Created{first_msg_id: 6326841983218119680,  server_salt: 7373524212041563863, unique_id: 427238195566612098}

when decoded second message gives:

0x59B4D66215C4B51C010000000074BE3F4375CD57 

Msgs_Ack{msg_ids: [6326841983218119680]}
Comments