Telegram MTProto Description

传输格式

当使用 TCP 进行通信时,需要确定 MTProto 数据包的边界,有两种情况:

第一种情况

+-+---+----...----+
|f|len|  payload  +
+-+---+----...----+

第二种情况

+-+----...----+
|f|  payload  |
+-+----...----+

:quick_ack 旨在让服务端快速确认是否收到来自客户端的消息。

Quick ack

These MTProto transport protocols have support for quick acknowledgment. In this case, the client sets the highest-order length bit in the query packet, and the server responds with a special 4 bytes as a separate packet. They are the 32 higher-order bits of SHA256 of the encrypted portion of the packet prepended by 32 bytes from the authorization key (the same hash as computed for verifying the message key), with the most significant bit set to make clear that this is not the length of a regular server response packet; if the abridged version is used, bswap is applied to these four bytes.

MTProto 协议格式

同样,MTProto 既可以传输明文,也可以传输密文,还有传输错误,对此有三种情况:

第一种情况:明文

auth_key_id = 0
int64
message_id
int64
message_data_length
int32
message_data
bytes

第二种情况:密文

auth_key_id
int64
msg_key
int128
encrypted_data
bytes
encrypted_data
salt
int64
session_id
int64
message_id
int64
seq_no
int32
message_data_length
int32
message_data
bytes
padding12..1024
bytes

Acknowledgment of Receipt

Receipt of virtually all messages (with the exception of some purely service ones as well as the plain-text messages used in the protocol for creating an authorization key) must be acknowledged. This requires the use of the following service message (not requiring an acknowledgment):

msgs_ack#62d6b459 msg_ids:Vector<long> = MsgsAck;

A server usually acknowledges the receipt of a message from a client (normally, an RPC query) using an RPC response. If a response is a long time coming, a server may first send a receipt acknowledgment, and somewhat later, the RPC response itself.

A client normally acknowledges the receipt of a message from a server (usually, an RPC response) by adding an acknowledgment to the next RPC query if it is not transmitted too late (if it is generated, say, 60-120 seconds following the receipt of a message from the server). However, if for a long period of time there is no reason to send messages to the server or if there is a large number of unacknowledged messages from the server (say, over 16), the client transmits a stand-alone acknowledgment.

Max 8192 IDs are allowed per constructor.

第三种情况:传输错误报告

当遇到传输错误时,比如丢失 auth_key 等,服务端会发一个 4 字节的数据包来表示错误,它的绝对值表示错误代码。

code
int32
[quick_ack]
int32
Result<Transport::ReadResult> Transport::read(MutableSlice message, ...) {
  if (message.size() < 12) {
    if (message.size() < 4) {
      return Status::Error(PSLICE() << "Invalid MTProto message: smaller than 4 bytes");
    }

    int32 code = as<int32>(message.begin());
    if (code == 0) {
      return ReadResult::make_nop();
    } else if (code == -1 && message.size() >= 8) {
      return ReadResult::make_quick_ack(as<uint32>(message.begin() + 4));
    } else {
      return ReadResult::make_error(code);
    }
  }
  // ...
}