С точки зрения компонента высокого уровня, клиент и сервер обмениваются сообщениями внутри сессии. Сессия привязана к девайсу клиента (к приложению, если точнее), а не к конкретному http/https/tcp соединению. Дополнительно, каждая сессия прикреплена к айди пользовательского ключа, которым собственно и завершается авторизация.
Может быть открыто несколько соединений с сервером; сообщения могут быть отправлены в направлении любого из соединений (ответ на запрос необязательно возвращается через то же соединение, которое содержало оригинальный запрос, хотя чаще всего именно так; как бы то ни было, ни в коем случае сообщение не может вернуться через соединение, принадлежащее другой сессии). Когда используется протокол UDP, ответ на запрос должен быть отправлен с помощью другого IP адреса, а не с того, с которого был послан запрос.
Есть несколько типов сообщений:
- RPC вызовы (от клиента к серверу): обращается к методам API
- RPC ответы (от сервера к клиенту): результаты RPC вызовов
- подтверждение получения сообщения (или, точнее, уведомление о статусе группы сообщений)
|
|
- запрос статуса сообщения
- сообщение из нескольких частей или контейнер (контейнер, который содержит несколько сообщений; который должен послать несколько RPC вызовов за раз посредством соединения HTTP, например; также, контейнер может поддерживать gzip).
С точки зрения нижних уровней протокола, сообщение является потоком двоичных данных, выровненных по границе 4- или 16- байт.
Каждое сообщение, как отдельное так и состоящее в контейнере, состоит из идентификатора сообщений (64 бита, см. ниже), порядкового номера сообщения в сессии (32 бита), длины (тела сообщения в байтах; 32 бита), и тела (любого размера, кратного 4 байтам). В дополнение, когда контейнер или одиночное сообщение отправлено, вверху добавляется внутренний заголовок (см. ниже), затем всё сообщение шифруется, и внешний заголовок размещается вверху сообщения (64-битный идентификатор ключа и 128-битный ключ сообщения).
Тело сообщения обычно состоит из 32-битного типа сообщения, сопровождаемого зависимыми от типа параметрами. В частности, каждая функция RPC имеет соответствующий тип сообщения. Больше деталей по ссылке - https://core.telegram.org/mtproto/serialize, https://core.telegram.org/mtproto/service_messages
Все числа записываются в кодировке little endian. Однако очень большие числа (2048-битные) использованные в RSA и DH записываются в формате big endian, т.к. это делает библиотека OpenSSL.