Critique du protocole Telegram et des approches organisationnelles. Partie 1, technique: l'expérience de l'écriture d'un client à partir de zéro - TL, MT

Récemment, des articles sont apparus plus souvent sur Habré sur la qualité du télégramme, la brillance et l'expérience des frères Durov dans la construction de systèmes de réseau, etc. Dans le même temps, très peu de gens se sont vraiment immergés dans le dispositif technique - au maximum, ils utilisent une API Bot assez simple (et très différente de MTProto) basée sur JSON, mais en général, ils ne prennent que les louanges et les relations publiques qui tournent autour du messager. Il y a près d'un an et demi, mon collègue de l'ONG Echelon Vasily (malheureusement, son compte sur Habr effacé avec un brouillon) a commencé à écrire son propre client Telegram à partir de zéro sur Perl, et l'auteur de ces lignes s'est joint plus tard. Pourquoi chez Perl, certains demanderont immédiatement? Parce que dans d'autres langues, de tels projets existent déjà En fait, ce n'est pas le sujet, il pourrait y avoir une autre langue où il n'y a pas encore de bibliothèque prête à l'emploi , et en conséquence l'auteur doit aller jusqu'au bout. De plus, la cryptographie est une telle chose - faites confiance, mais vérifiez. Avec un produit destiné à la sécurité, vous ne pouvez pas simplement vous fier à la bibliothèque finie du fabricant et y croire aveuglément (cependant, c'est un sujet plus pour la deuxième partie). Pour le moment, la bibliothèque fonctionne assez bien au niveau "moyen" (elle vous permet de faire des requêtes API).


Cependant, dans cette série d'articles, il n'y aura pas beaucoup de cryptographie et de mathématiques. Mais il y aura de nombreux autres détails techniques et béquilles architecturales (utiles à ceux qui n'écriront pas à partir de zéro, mais utiliseront la bibliothèque dans n'importe quelle langue). Ainsi, l'objectif principal était d'essayer de mettre en œuvre le client à partir de zéro selon la documentation officielle . Autrement dit, supposons que le code source des clients officiels soit fermé (encore une fois, dans la deuxième partie, nous développerons le sujet de la façon dont cela se produit réellement), mais, comme autrefois, par exemple, il existe une norme comme RFC - est-il possible d'écrire un client en utilisant une seule spécification, "pas lorgnant" à la source, au moins officielle (Telegram Desktop, mobile), au moins non officielle Telethon?


Table des matières:



La documentation ... existe-t-elle? Vraiment? ..


Des fragments de notes pour cet article ont commencé à être collectés l'été dernier. Pendant tout ce temps sur le site officiel https://core.telegram.org la documentation était à partir de la couche 23, c'est-à-dire coincé quelque part en 2014 (rappelez-vous, il n'y avait même pas encore de chaînes?). Bien sûr, en théorie, cela aurait dû permettre d'implémenter un client avec des fonctionnalités à cette époque en 2014. Mais même dans cet état, la documentation était, d'une part, incomplète, et d'autre part, parfois contradictoire. Il y a un peu plus d'un mois, en septembre 2019, il a été accidentellement découvert que le site avait une grande mise à jour de la documentation, sur le Layer 105 complètement frais, avec la note que maintenant tout doit être relu. En effet, de nombreux articles ont été révisés, mais beaucoup sont restés inchangés. Par conséquent, en lisant les critiques ci-dessous concernant la documentation, il convient de garder à l'esprit que certaines de ces choses ne sont plus pertinentes, mais certaines le sont encore. Après tout, 5 ans dans le monde moderne, ce n'est pas seulement beaucoup, mais beaucoup. Depuis ce temps (surtout si vous ne tenez pas compte des géochats éjectés et repris depuis lors), le nombre de méthodes API dans le schéma est passé de cent à plus de deux cent cinquante!


Par où commencer un jeune auteur?


, Telethon Python Madeline PHP, api_id api_hash ( API ), . , , , . , , — , , .


, , , Telegram , , .. , "" , , .. . , , .


, . https://core.telegram.org/ Getting Started , MTProtoOSI , .


, MTProto, , ( , layer violation) , ...


: TL (Type Language) , ,


, , Telegram — . , , .


, . , , JSON Schema, . : . , , . MTProto, , - , :


int ? = Int;
long ? = Long;
double ? = Double;
string ? = String;

vector#1cb5c415 {t:Type} # [ t ] = Vector t;

rpc_error#2144ca19 error_code:int error_message:string = RpcError;

rpc_answer_unknown#5e2ad36e = RpcDropAnswer;
rpc_answer_dropped_running#cd78e586 = RpcDropAnswer;
rpc_answer_dropped#a43ad8b7 msg_id:long seq_no:int bytes:int = RpcDropAnswer;

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

---functions---

set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:bytes = Set_client_DH_params_answer;

ping#7abe77ec ping_id:long = Pong;
ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;

invokeAfterMsg#cb9f372d msg_id:long query:!X = X;
invokeAfterMsgs#3dc4b4f0 msg_ids:Vector<long> query:!X = X;

account.updateProfile#78515775 flags:# first_name:flags.0?string last_name:flags.1?string about:flags.2?string = User;
account.sendChangePhoneCode#8e57deb flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool = auth.SentCode;

, , — , ( , ?), , … . ++ ( , ). , , , , ( ), - , - , — , ( ) ? (, JSON- — ).


Binary Data Serialization 4 . , , , , , , , … ! TL Language, , , , !


, , , , , , , - . :


  • , , ,
  • IT- —
  • , , , TL,

LeoNerd #perl IRC- FreeNode, Telegram Matrix ( ):


, - , , , .

, bare- (int, long ..) - — — . , , , .



TL , …


constructor = Type;
myVec ids:Vector<long> = Type;

fixed#abcdef34 id:int = Type2;

fixedVec set:Vector<Type2> = FixedVec;

constructorOne#crc32 field1:int = PolymorType;
constructorTwo#2crc32 field_a:long field_b:Type3 field_c:int = PolymorType;
constructorThree#deadcrc bit_flags_of_what_really_present:# optional_field4:bit_flags_of_what_really_present.1?Type = PolymorType;

an_id#12abcd34 id:int = Type3;
a_null#6789cdef = Type3;

, ( — ) # CRC32 . , — . , — , , — . , , — .


---functions---, , : RPC-, — ( , , ), " " — . , , — ---types---, " ". , .. , , C++, TL - .


"" "", ? , , - — , — -, final . , , - . — , ( , , ) — , .


? , 4 , 0xcrc32 — , field1 int, .. 4 , PolymorType . 0x2crc32 , , long, 8 . , . , Type3 , , 0x12abcd34, 4 int, 0x6789cdef, . — . 4 int field_c constructorTwo PolymorType.


, 0xdeadcrc constructorThree, . bit_flags_of_what_really_present # — , nat, " ". , , unsigned int — , , , . , , , — on the wire, , ( ). , , , , Type, 2 . ( ), ids ids:Vector<long>.


, generic' Java. . , . , Vector. 4 CRC32 Vector, , 4 — , .


, 4 , — bytes string 4 — , ? TL , , , 4 , JSON ? , , , , ?..


, , , . -, CRC32 ( whitespace ..) — , , CRC32 , , . , , , ?..


-, CRC32, - , (). — , 232, . , CRC32 ( ) , ? , : CRC32 , 4 4 — . ( ), , .


, , CRC32? ( ) -, 239, -!

, , , Vector<int> Vector<PolymorType> CRC32. ? , ? , , Vector<int> , 40000 . Vector<Type2>, int — 10000 0xabcdef34 4 int, fixedVec 80000 40000 ?


— , , id, , — . Telegram .


...


Vector,


, , ( ) tuples . , , , . ? , , — lazy evaluation . : , .. — , — ( (cons) Lisp). , , 4 (CRC32 TL) . , — .


, TL , . :


Serialization always uses the same constructor “vector” (const 0x1cb5c415 = crc32("vector t:Type # [ t ] = Vector t”) that is not dependent on the specific value of the variable of type t.

The value of the optional parameter t is not involved in the serialization since it is derived from the result type (always known prior to deserialization).

: vector {t:Type} # [ t ] = Vector t, ! . , . , :


The Vector t polymorphic pseudotype is a “type” whose value is a sequence of values of any type t, either boxed or bare.

… . , ( ), , : , ( - ACM), . — — .


, . , # nat, :

There are type expressions (type-expr) and numeric expressions (nat-expr). However, they are defined the same way.
type-expr ::= expr
nat-expr ::= expr


, .. .

, (vector<int>, vector<User>) (#1cb5c415), .. ,


users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;

, . , — , bare-, , - — ? - PHP, ?


— TL? , , protobuf, ? , .


TL


TL (), Telegram. . , Telegram. , ( ( ) ).


Templates are not used now. Instead, the same universal constructors (for example, vector {t:Type} [t] = Vector t) are used w

, , , .


#define ZHUKOV_BYTES_HACK

#ifdef ZHUKOV_BYTES_HACK

/* dirty hack for Zhukov request */

, :


    static const char *reserved_words_polymorhic[] = {

      "alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", NULL

      };

— , :


intHash {alpha:Type} vector<coupleInt<alpha>> = IntHash<alpha>;

, int — Type. C++ :


    template <T> class IntHash {
      vector<pair<int,T>> _map;
    }

, alpha — ! C++ T, alpha, beta… 8 , . , - :


--    TL 
-- ...     , ,...     ... , !
-- ?   

-- ,        !
--  ,     ?
--   ,     ,  --  

TL "". Telegram-.


:


Vasily, [09.10.18 17:07]
, , ,
, .jpg
.webp

, , , , - DSL, ?..


telegram-cli , TLO (cli) , — TL , TL?..


16.12 04:18 Vasily: -, - lex+yacc
16.12 04:18 Vasily:
16.12 04:18 Vasily:
16.12 04:19 Vasily: 3+ <censored>

, ? , — Telegram Desktop:


    nametype = re.match(r'([a-zA-Z\.0-9_]+)(#[0-9a-f]+)?([^=]*)=\s*([a-zA-Z\.<>0-9_]+);', line);
    if (not nametype):
      if (not re.match(r'vector#1cb5c415 \{t:Type\} # \[ t \] = Vector t;', line)):
         print('Bad line found: ' + line);

1100+ , + , , , TL, , … , , ?!


… , CRC32? , Telegram Desktop , CRC32 !


Vasily, [18.12 22:49]
, TL
, ,
tdesktop, ,

, .


, telegram-cli — , Telegram Desktop — , ? ?.. Android- ( , ), , .


? , , , :


Vasily: flags.0? true
, true,

Vasily: flags.1? int
, ,

Vasily: , , !
Vasily: - , true — , -
Vasily: ,

, , Telethon? MTProto, — , % " bare-", .. , :


Vasily, [22.06.18 18:38]
:
msg_container#73f1f8dc messages:vector message = MessageContainer;


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


, -

bare

telethon

msg_container

, %. .

Vadim Goncharov, [22.06.18 19:22]
tdesktop?

Vasily, [22.06.18 19:23]
TL

// parsed manually

TL ,

%

,

,

TL,

" ", , "- , , ".


: " ,


    args: /* empty */ { $$ = NULL; }
        | args arg { $$ = g_list_append( $1, $2 ); }
        ;

    arg: LC_ID ':' type-term { $$ = tl_arg_new( $1, $3 ); }
            | LC_ID ':' condition '?' type-term { $$ = tl_arg_new_cond( $1, $5, $3 ); free($3); }
            | UC_ID ':' type-term { $$ = tl_arg_new( $1, $3 ); }
            | type-term { $$ = tl_arg_new( "", $1 ); }
            | '[' LC_ID ']' { $$ = tl_arg_new_mult( "", tl_type_new( $2, TYPE_MOD_NONE ) ); }
            ;

- ,


struct tree *parse_args4 (void) {
  PARSE_INIT (type_args4);
  struct parse so = save_parse ();
  PARSE_TRY (parse_optional_arg_def);
  if (S) {
    tree_add_child (T, S);
  } else {
    load_parse (so);
  }
  if (LEX_CHAR ('!')) {
    PARSE_ADD (type_exclam);
    EXPECT ("!");
  }
  PARSE_TRY_PES (parse_type_term);
  PARSE_OK;
}


        # Regex to match the whole line
        match = re.match(r'''
            ^                  # We want to match from the beginning to the end
            ([\w.]+)           # The .tl object can contain alpha_name or namespace.alpha_name
            (?:
                \#             # After the name, comes the ID of the object
                ([0-9a-f]+)    # The constructor ID is in hexadecimal form
            )?                 # If no constructor ID was given, CRC32 the 'tl' to determine it

            (?:\s              # After that, we want to match its arguments (name:type)
                {?             # For handling the start of the '{X:Type}' case
                \w+            # The argument name will always be an alpha-only name
                :              # Then comes the separator between name:type
                [\w\d<>#.?!]+  # The type is slightly more complex, since it's alphanumeric and it can
                               # also have Vector<type>, flags:# and flags.0?default, plus :!X as type
                }?             # For handling the end of the '{X:Type}' case
            )*                 # Match 0 or more arguments
            \s                 # Leave a space between the arguments and the equal
            =
            \s                 # Leave another space between the equal and the result
            ([\w\d<>#.?]+)     # The result can again be as complex as any argument type
            ;$                 # Finally, the line should always end with ;
            ''', tl, re.IGNORECASE | re.VERBOSE)

:


    ---functions---         return FUNCTIONS;
    ---types---             return TYPES;
    [a-z][a-zA-Z0-9_]*      yylval.string = strdup(yytext); return LC_ID;
    [A-Z][a-zA-Z0-9_]*      yylval.string = strdup(yytext); return UC_ID;
    [0-9]+                  yylval.number = atoi(yytext); return NUM;
    #[0-9a-fA-F]{1,8}       yylval.number = strtol(yytext+1, NULL, 16); return ID_HASH;

    \n                      /* skip new line */
    [ \t]+                  /* skip spaces */
    \/\/.*$                 /* skip comments */
    \/\*.*\*\/              /* skip comments */
    .                       return (int)yytext[0];

.. — ".


, TL 100 ~300 ( print' ), . , — .



— , ? , ( ), TL. , . , , , . ?


, constraints. :


The file’s binary content is then split into parts. All parts must have the same size ( part_size ) and the following conditions must be met:
  • part_size % 1024 = 0 (divisible by 1KB)
  • 524288 % part_size = 0 (512KB must be evenly divisible by part_size)


The last part does not have to satisfy these conditions, provided its size is less than part_size.

Each part should have a sequence number, file_part, with a value ranging from 0 to 2,999.

After the file has been partitioned you need to choose a method for saving it on the server. Use upload.saveBigFilePart in case the full size of the file is more than 10 MB and upload.saveFilePart for smaller files.
[...] one of the following data input errors may be returned:
  • FILE_PARTS_INVALID — Invalid number of parts. The value is not between 1..3000

- ? - TL? . , Turbo Pascal , . , enum — , () . — , , . , … , , , ?


TL . , , JSON Schema. 512 - , , , 1..3000 ( ) , ?..


, . , TL — , TL , . TL . , ( , RPC -, ) — ?.. — .


, ? , , description ( JSON- ), , — ? :


-channelFull#76af5481 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int = ChatFull;
+channelFull#1c87a71a flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int = ChatFull;



-message#44f9b43d 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 post_author:flags.16?string grouped_id:flags.17?long = Message;
+message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?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 post_author:flags.16?string grouped_id:flags.17?long = Message;


, GitHub, , . " 10 ", , , - … , , .


, . ? , ? . , , . :


storage.fileUnknown#aa963b05 = storage.FileType;
storage.filePartial#40bc6f52 = storage.FileType;
storage.fileJpeg#7efe0e = storage.FileType;
storage.fileGif#cae1aadf = storage.FileType;
storage.filePng#a4f63c0 = storage.FileType;
storage.filePdf#ae1e508d = storage.FileType;
storage.fileMp3#528a0677 = storage.FileType;
storage.fileMov#4b09ebbc = storage.FileType;
storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;

, 5 , 32 . . TL .


, . , MTProto ( ) Gzip, — , . , RpcResult, . ?.. , .


, — InputPeerUser InputUser. . ! . ? , , telegram-cli:


  if (tgl_get_peer_type (E->id) != TGL_PEER_CHANNEL || (C && (C->flags & TGLCHF_MEGAGROUP))) {
    out_int (CODE_messages_get_history);
    out_peer_id (TLS, E->id);
  } else {    
    out_int (CODE_channels_get_important_history);

    out_int (CODE_input_channel);
    out_int (tgl_get_peer_id (E->id));
    out_long (E->id.access_hash);
  }
  out_int (E->max_id);
  out_int (E->offset);
  out_int (E->limit);
  out_int (0);
  out_int (0);

, , ! , ?.. , , , ? ? .


. (layers)


, , . , , , , , , . , — "", . , . , — , . 2. TL:


If a client supports Layer 2, then the following constructor must be used:
invokeWithLayer2#289dd1f6 {X:Type} query:!X = X;


In practice, this means that before every API call, an int with the value 0x289dd1f6 must be added before the method number.

. ?


invokeWithLayer3#b7475268 query:!X = X;

? ,


invokeWithLayer4#dea0d430 query:!X = X;

? , , , — , -? 4 — . So,


invokeWithLayer5#417a57ae query:!X = X;

, . :


Update: Starting with Layer 9, helper methods invokeWithLayerN can be used only together with initConnection

! 9 , , , Internet- 80- — !


?..


invokeWithLayer10#39620c41 query:!X = X;
...
invokeWithLayer18#1c900537 query:!X = X;

. 9 , , , , , , . .


?..


Vasily, [16.07.18 14:01]
:
. InvokeWithLayer. , .

.. ,

Vadim Goncharov, [16.07.18 14:02]
InvokeWithLayer ?

Vasily, [16.07.18 14:02]


Vadim Goncharov, [16.07.18 14:02]


, ,

, .. Updates — , API-, . , , , Updates .


, , :


  • , ,
  • ?
  • , ?

, , , ( , )? ! !


. 14 , Telegram - … :


2019-08-15 09:28:35.880640 MSK warn  main: ANON:87: unknown object type: 0x80d182d1 at TL/Object.pm line 213.
2019-08-15 09:28:35.751899 MSK warn  main: ANON:87: unknown object type: 0xb5223b0f at TL/Object.pm line 213.

(, ). TL - — , , . ?


, — . . CRC32 — 73 , 82. — !


, ? , Telegram Desktop 1.2.17 (, Linux), Exception: MTP Unexpected type id #b5223b0f read in MTPMessageMedia...



, - , ...


-? : 91, 73. , , , , .


: , , , , , — , . .


? , . , , "", , , , . "", .


… ?!.. , , . Android TL-, ( ) (). :


public static class TL_message_layer68 extends TL_message {
    public static int constructor = 0xc09be45f;
//...
//  
//...
    public static class TL_message_layer47 extends TL_message {
        public static int constructor = 0xc992e15c;
        public static Message TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
            Message result = null;
            switch (constructor) {
                case 0x1d86f70e:
                    result = new TL_messageService_old2();
                    break;
                case 0xa7ab1991:
                    result = new TL_message_old3();
                    break;
                case 0xc3060325:
                    result = new TL_message_old4();
                    break;
                case 0x555555fa:
                    result = new TL_message_secret();
                    break;
                case 0x555555f9:
                    result = new TL_message_secret_layer72();
                    break;
                case 0x90dddc11:
                    result = new TL_message_layer72();
                    break;
                case 0xc09be45f:
                    result = new TL_message_layer68();
                    break;
                case 0xc992e15c:
                    result = new TL_message_layer47();
                    break;
                case 0x5ba66c13:
                    result = new TL_message_old7();
                    break;
                case 0xc06b9607:
                    result = new TL_messageService_layer48();
                    break;
                case 0x83e5de54:
                    result = new TL_messageEmpty();
                    break;
                case 0x2bebfa86:
                    result = new TL_message_old6();
                    break;
                case 0x44f9b43d:
                    result = new TL_message_layer104();
                    break;
                case 0x1c9b1027:
                    result = new TL_message_layer104_2();
                    break;
                case 0xa367e716:
                    result = new TL_messageForwarded_old2(); //custom
                    break;
                case 0x5f46804:
                    result = new TL_messageForwarded_old(); //custom
                    break;
                case 0x567699b3:
                    result = new TL_message_old2(); //custom
                    break;
                case 0x9f8d60bb:
                    result = new TL_messageService_old(); //custom
                    break;
                case 0x22eb6aba:
                    result = new TL_message_old(); //custom
                    break;
                case 0x555555F8:
                    result = new TL_message_secret_old(); //custom
                    break;
                case 0x9789dac4:
                    result = new TL_message_layer104_3();
                    break;


    boolean fixCaption = !TextUtils.isEmpty(message) &&
    (media instanceof TLRPC.TL_messageMediaPhoto_old ||
     media instanceof TLRPC.TL_messageMediaPhoto_layer68 ||
     media instanceof TLRPC.TL_messageMediaPhoto_layer74 ||
     media instanceof TLRPC.TL_messageMediaDocument_old ||
     media instanceof TLRPC.TL_messageMediaDocument_layer68 ||
     media instanceof TLRPC.TL_messageMediaDocument_layer74)
    && message.startsWith("-1");

… . , , , ?.. ! , , , , _old7 - … ,


TL_message_layer104
TL_message_layer104_2
TL_message_layer104_3

, , ?! , , "", , , , ?.. ? , ?..


Telegram Desktop, , — , , - . , , , ? , , , .


? , -, .


, :


public static class TL_folders_deleteFolder extends TLObject {
    public static int constructor = 0x1c295881;

    public int folder_id;

    public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
        return Updates.TLdeserialize(stream, constructor, exception);
    }

    public void serializeToStream(AbstractSerializedData stream) {
        stream.writeInt32(constructor);
        stream.writeInt32(folder_id);
    }
}

//manually created

//RichText start
public static abstract class RichText extends TLObject {
    public String url;
    public long webpage_id;
    public String email;
    public ArrayList<RichText> texts = new ArrayList<>();
    public RichText parentRichText;

    public static RichText TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
        RichText result = null;
        switch (constructor) {
            case 0x1ccb966a:
                result = new TL_textPhone();
                break;
            case 0xc7fb5e01:
                result = new TL_textSuperscript();
                break;

"manually created" , ( maintenance?), . , — , (- GPL Linux), .


. , .


MTProto


, . . , Telegram — -, , (, API sticker pack — , ).


, "" (message) "" (session) — , Telegram-. , , , "" — , , , , . … .



— . 5 :


  • TCP
  • Websocket
  • Websocket over HTTPS
  • HTTP
  • HTTPS

Vasily, [15.06.18 15:04]
UDP ,

TCP

UDP TCP, sequence number crc
?

, TCP 4 :


  • Abridged
  • Intermediate
  • Padded intermediate
  • Full

, Padded intermediate MTProxy, - . ( ), ? , payload MTProto, :


  • Abridged 1 4 , 0xef,
  • Intermediate 4 , 0xeeeeeeee , Intermediate
  • Full , : , sequence number, , MTProto, , CRC32. , TCP. , , . , , TCP 16- , . , - 16 , — — SHA . CRC32 — .

Abridged, , Intermediate, "In case 4-byte data alignment is needed", - . , , Telegram , ? , ( -...). , Abridged, padding' 16 — 3 ?


, , , .


, .. Web MTProxy, , , , . MTProxy , 2018, , , ! , ( ) MTProxy , ( ), Go, Node.js .


, . 5- OSI, — MTProto session.


, , , Diffie-Hellman


… — , Active sessions. .



. , plaintext — . "" ? Telegram ( 4 , ):


session — UI "current sessions", / OS.
MTProto session, sequence number ( ) , TCP-. MTProto-, .

sessions authorization. , , UI- , authorization, , . :
  • auth_key bounds it to account, SMS — authorization
  • MTProto session, session_id .
  • , authorization session_id instance
  • , MTProto sessions auth_key — DC.
  • , DC — DC auth_key !
  • , , authorization (UI-), API auth.exportAuthorization DC auth.importAuthorization DC.
  • , MTProto sessions ( session_id) DC, auth_key.
  • , Perfect Forward Secrecy. auth_key permanent key — per DC — auth.bindTempAuthKey temporary auth_key — , temp_auth_key per DC, MTProto sessions DC.


, salt ( future salts) auth_key .. shared MTProto sessions DC.

" TCP-"? , - — () TCP- , . HTTP, MTProto , , — , TCP-.


, . — ? — .


, auth_key - Telegram. ...


Vasily, [19.06.18 20:05]
data_with_hash := SHA1(data) + data + (any random bytes); such that the length equal 255 bytes;
encrypted_data := RSA (data_with_hash, server_public_key); a 255-byte long number (big endian) is raised to the requisite power over the requisite modulus, and the result is stored as a 256-byte number.

- DH

DH

— proof of work , . DoS-. RSA- , , new_nonce. , ?


Vasily, [20.06.18 00:26]
appid

DH

, , 4 .

-404, ?

: " -, DH", 404

? ? - ( ).




, -

32 .

, BE

Vadim Goncharov, [20.06.18 15:49]
- 404?

Vasily, [20.06.18 15:49]
!

Vadim Goncharov, [20.06.18 15:50]
, " "

Vasily, [20.06.18 15:50]


%)

error reporting

Vasily, [20.06.18 20:18]
, MD5.

The key fingerprint is computed as follows:
digest = md5(key + iv)
fingerprint = substr(digest, 0, 4) XOR substr(digest, 4, 4)


SHA1 sha2

, , auth_key 2048 - . ? , 1024 … . . TLS-, . , ! , , . .. "-", - ICQ, "-", SSH ( - gitlab/github). . " DC"? " "? , — , .


, "" . , ? ? :


Vasily, [21.06.18 17:53]
2 %)

,

Vasily, [21.06.18 18:02]
, ,

. , ? ( , ) — , :


278     static const char *goodPrime = "c71caeb9c6b1c9048e6c522f70f13f73980d40238e3e21c14934d037563d930f48198a0aa7c14058229493d22530f4dbfa336f6e0ac925139543aed44cce7c3720fd51f69458705ac68cd4fe6b6b13abdc9746512969328454f18faf8c595f642477fe96bb2a941d5bcd1d4ac8cc49880708fa9b378e3c4f3a9060bee67cf9a4a4a695811051907e162753b56b0f6b410dba74d8a84b2a14b3144e0ef1284754fd17ed950d5965b4b9dd46582db1178d169c6bc465b0d6ff9ca3928fef5b9ae4e418fc15e83ebea0f87fa9ff5eed70050ded2849f47bf959d956850ce929851f0d8115f635b105ee2e4e15d04b2454bf6f4fadf034b10403119cd8e3b92fcc5b";
279   if (!strcasecmp(prime, goodPrime)) {

, - , .


, . , .. , , AES.


The message key is defined as the 128 middle bits of the SHA256 of the message body (including session, message ID, etc.), including the padding bytes, prepended by 32 bytes taken from the authorization key.

Vasily, [22.06.18 14:08]
, ,

auth_key. . … . Feel free to study the open source code.

Note that MTProto 2.0 requires from 12 to 1024 bytes of padding, still subject to the condition that the resulting message length be divisible by 16 bytes.

?

, 404

, , MAC . AES , IGE. , , FAQ… , , SHA- , — - silently ignore ( , ?).


, , . , Telegram Desktop. ( D877F783D5D3EF8C) , MTProto ( 1.0), .. , ( - auth_key 256 , msg_key ). , . , — . , , ?.. MAC , . MTProto , . Telegram Desktop user_data — AES CTR.


Vasily, [21.06.18 01:27]
, , IGE: IGE was the first attempt at an "authenticating encryption mode," originally for Kerberos. It was a failed attempt (it does not provide integrity protection), and had to be removed. That was the beginning of a 20 year quest for an authenticating encryption mode that works, which recently culminated in modes like OCB and GCM.

:

The team behind Telegram, led by Nikolai Durov, consists of six ACM champions, half of them Ph.Ds in math. It took them about two years to roll out the current version of MTProto.

.

tls

, , . , , TL ? ? , , initConnection, ?


Vasily, [25.06.18 18:46]
Initializes connection and save information on the user's device and application.

app_id, device_model, system_version, app_version lang_code.

query

. Feel free to study the open source

invokeWithLayer , - ? , — , — , :


Vasily, [25.06.18 19:13]
, , invokewithlayer

initConnection , ? , , , , . ! ! , — , ...


Only a small portion of the API methods are available to unauthorized users:

  • auth.sendCode
  • auth.resendCode
  • account.getPassword
  • auth.checkPassword
  • auth.checkPhone
  • auth.signUp
  • auth.signIn
  • auth.importAuthorization
  • help.getConfig
  • help.getNearestDc
  • help.getAppUpdate
  • help.getCdnConfig
  • langpack.getLangPack
  • langpack.getStrings
  • langpack.getDifference
  • langpack.getLanguages
  • langpack.getLanguage

, auth.sendCode, , api_id api_hash, SMS . DC ( , ), DC. , IP- DC , help.getConfig. - 5 , 2018 .


, . , IP-? , , MTProto? : " , ?". , - RSA-, .. . , , (, MTProto, , ).


, . . , , . ...


Vasily, [10.07.18 14:45]
https://core.telegram.org/method/help.getConfig
config#7dae33e0 [...] = Config;
help.getConfig#c4f9186b = Config;


https://core.telegram.org/api/datacenter
config#232d5905 [...] = Config;
help.getConfig#c4f9186b = Config;


,

tdesktop

, , , . . ? , , ? , — (, ).


… , - API, .. , - MTProto? :


Vasily, [28.06.18 02:04]
, e2e

Mtproto ,

, , mtproto

? PFS, (, Telegram Desktop ). API auth.bindTempAuthKey, .. . — , , initConnection .., . , DC, auth_key_id , "" — , … , future salts, ?..


MTProto .


, msg_id, msg_seqno, ,


? "" , , API. , msg_key , . ( , , padding, ):


  • salt — int64
  • session_id — int64
  • message_id — int64
  • seq_no — int32

, — DC. ? , get_future_salts, , , , "", () — . , , , new_session_created — - , . .


. , MTProto ? , session_id seq_no . , TCP-, . , , , . — TCP- , seq_no . — , , .


seq_no? , . , :


Content-related Message

A message requiring an explicit acknowledgment. These include all the user and many service messages, virtually all with the exception of containers and acknowledgments.

Message Sequence Number (msg_seqno)

A 32-bit number equal to twice the number of “content-related” messages (those requiring acknowledgment, and in particular those that are not containers) created by the sender prior to this message and subsequently incremented by one if the current message is a content-related message. A container is always generated after its entire contents; therefore, its sequence number is greater than or equal to the sequence numbers of the messages contained in it.

1, 2?.. , " ACK, ", — , , , seq_no! ? - , , , . . TCP , - , , TCP seq_no , seq_no — . MTProto seq_no, TCP, msg_id !


msg_id, ? , . 64- , "- ", — Unix timestamp, , 32 . .. ( ). , - , . , — session_id — : Under no circumstances can a message meant for one session be sent into a different session. , , — , , id . , .


, msg_id ...


RPC: , , . .


, , , " RPC-", . content-related ! , ! . msg_id. — :


rpc_result#f35c6d01 req_msg_id:long result:Object = RpcResult;

, . , API, , — , , , , ? , , no workers, : TCP- — -, message_id. , .


?.. ? RPC- msg_id! " !"? , ? ,


msgs_ack#62d6b459 msg_ids:Vector long = MsgsAck;

. ! RpcResult, . , MsgsAck — , " ". RpcResult. .


, ! . . . , , . .


.


rpc_error#2144ca19 error_code:int error_message:string = RpcError;

, -, — ! . , , , . , — HTTP- ( , , ), ___. , PHONE_NUMBER_OCCUPIED FILE_PART__MISSING. , . , FLOOD_WAIT_3600 , , PHONE_MIGRATE_5, 5- DC. , ? , , .


, , , , . . -, , / — RpcError RpcResult. ? ?.. , , RpcError RpcResult, ?.. , , .. req_msg_id ?..


. , , :


rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;

, , , ( , ), (: Telegram Desktop ).


:


, TL, MTProto Telegram , , soft skills , . , , .


, .


bad_msg_notification#a7eff811 bad_msg_id:long bad_msg_seqno:int error_code:int = BadMsgNotification;
bad_server_salt#edab447b bad_msg_id:long bad_msg_seqno:int error_code:int new_server_salt:long = BadMsgNotification;

, MTProto, " — — " — . :


  1. , . - , .
  2. ? 16, 17, 18, 19, 20, 32, 33, 34, 35, 48, 64… , ?

:


The intention is that error_code values are grouped (error_code >> 4): for example, the codes 0x40 — 0x4f correspond to errors in container decomposition.

, -, , -, , ? ?.. , .


:


  • Request for Message Status Information
    If either party has not received information on the status of its outgoing messages for a while, it may explicitly request it from the other party:
    msgs_state_req#da69fb52 msg_ids:Vector long = MsgsStateReq;
  • Informational Message regarding Status of Messages
    msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
    Here, info is a string that contains exactly one byte of message status for each message from the incoming msg_ids list:
    • 1 = nothing is known about the message (msg_id too low, the other party may have forgotten it)
    • 2 = message not received (msg_id falls within the range of stored identifiers; however, the other party has certainly not received a message like that)
    • 3 = message not received (msg_id too high; however, the other party has certainly not received it yet)
    • 4 = message received (note that this response is also at the same time a receipt acknowledgment)
    • +8 = message already acknowledged
    • +16 = message not requiring acknowledgment
    • +32 = RPC query contained in message being processed or processing already complete
    • +64 = content-related response to message already generated
    • +128 = other party knows for a fact that message is already received
      This response does not require an acknowledgment. It is an acknowledgment of the relevant msgs_state_req, in and of itself.
      Note that if it turns out suddenly that the other party does not have a message that looks like it has been sent to it, the message can simply be re-sent. Even if the other party should receive two copies of the message at the same time, the duplicate will be ignored. (If too much time has passed, and the original msg_id is not longer valid, the message is to be wrapped in msg_copy).
  • Voluntary Communication of Status of Messages
    Either party may voluntarily inform the other party of the status of the messages transmitted by the other party.
    msgs_all_info#8cc0d131 msg_ids:Vector long info:string = MsgsAllInfo
  • Extended Voluntary Communication of Status of One Message

    msg_detailed_info#276d3ec6 msg_id:long answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
    msg_new_detailed_info#809db6df answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
  • Explicit Request to Re-Send Messages
    msg_resend_req#7d861a08 msg_ids:Vector long = MsgResendReq;
    The remote party immediately responds by re-sending the requested messages [...]
  • Explicit Request to Re-Send Answers
    msg_resend_ans_req#8610baeb msg_ids:Vector long = MsgResendReq;
    The remote party immediately responds by re-sending answers to the requested messages [...]
  • Message Copies
    In some situations, an old message with a msg_id that is no longer valid needs to be re-sent. Then, it is wrapped in a copy container:
    msg_copy#e06046b2 orig_message:Message = MessageCopy;
    Once received, the message is processed as if the wrapper were not there. However, if it is known for certain that the message orig_message.msg_id was received, then the new message is not processed (while at the same time, it and orig_message.msg_id are acknowledged). The value of orig_message.msg_id must be lower than the container’s msg_id.

, msgs_state_info TL ( , enum, ). . - , ?.. , - , , — , . .


, , , , . , . , ! , -, . , , , TL — () , , , .. .


. .


, ( ), — TCP ( , , ), MTProto — . , , .


— . , - — . ? . , - , , Telegram Desktop 4 , ( , , ; , , MTProto ).


? , , -, . , , TCP — RTT "" ( ) . , — .


, , ? TCP TCP — .


, , , , API? , , , . ? msg_id, , — - (, , , — , - ). , , :


  1. .
  2. msg_id — ; .
  3. ) MsgsAck — , " ".
    ) , - , badmsg — " "
    ) , — , .
  4. RpcResult — ( ) — , .

, . , , msg_id. , - , .


. , , , — , ? (, ).


? " " " , !" ( , , rationale , ), / — , . ?


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.

… : , , , .


:


Ping Messages (PING/PONG)
ping#7abe77ec ping_id:long = Pong;


A response is usually returned to the same connection:
pong#347773c5 msg_id:long ping_id:long = Pong;


These messages do not require acknowledgments. A pong is transmitted only in response to a ping while a ping can be initiated by either side.

Deferred Connection Closure + PING
ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;


Works like ping. In addition, after this is received, the server starts a timer which will close the current connection disconnect_delay seconds later unless it receives a new message of the same type which automatically resets all previous timers. If the client sends these pings once every 60 seconds, for example, it may set disconnect_delay equal to 75 seconds.

?! 60 , - , . 120 , , , . , — " , ", TCP_NODELAY, . , , — 200 . — , , 5 , "User is typing...". .


, . , TCP-. , 10 — , . 3 , — , ?..


. TCP-, , . , , . , SSH- , - , , — ( , ), . , , (, !), , , — .


/ IM , — -. "", . , Jabber ( 20 ) — , , , online ( ). , TCP_KEEPALIVE, , TCP, ( ), — , , , , (, ? Telegram Desktop Ubuntu 18.04 ).


, — , , .


Telegram? ! .. , , . — ping_delay_disconnect, . , , . , , . , , , , ...


?


, Telegram/ ( ) .


, Telegram ? , , TCP-, , . — . , UDP-, ( — ). - , TCP , , ( ), " " — .


? , msg_id , replay-, . , ( Updates, API ), :


  1. , TCP- , — , , , . id', " seq_no" — , TCP ( — seq ). , ?
  2. replay- , - nonce. , . uint32 — , 16 , — ( ).
  3. msg_id — , -, id , -, id , . , seq_no.

, — API , . , , .


API ?


-! , , , , ( , , PUSH, - ).


, Perl! ( , , bless — , — ):


2019.10.24 12:00:51 $1 = {
  'cb' => 'TeleUpd::__ANON__',
  'out' => bless( {
    'filter' => bless( {}, 'Telegram::ChannelMessagesFilterEmpty' ),
    'channel' => bless( {
      'access_hash' => '-6698103710539760874',
      'channel_id' => '1380524958'
    }, 'Telegram::InputPeerChannel' ),
    'pts' => '158503',
    'flags' => 0,
    'limit' => 0
  }, 'Telegram::Updates::GetChannelDifference' ),
  'req_id' => '6751291954012037292'
};

2019.10.24 12:00:51 $1 = {
  'in' => bless( {
    'req_msg_id' => '6751291954012037292',
    'result' => bless( {
      'pts' => 158508,
      'flags' => 3,
      'final' => 1,
      'new_messages' => [],
      'users' => [],
      'chats' => [
        bless( {
          'title' => '',
          'username' => 'hoolinomics',
          'flags' => 8288,
          'id' => 1380524958,
          'access_hash' => '-6698103710539760874',
          'broadcast' => 1,
          'version' => 0,
          'photo' => bless( {
            'photo_small' => bless( {
              'volume_id' => 246933270,
              'file_reference' => '
              'secret' => '1854156056801727328',
              'local_id' => 228648,
              'dc_id' => 2
            }, 'Telegram::FileLocation' ),
            'photo_big' => bless( {
              'dc_id' => 2,
              'local_id' => 228650,
              'file_reference' => '
              'secret' => '1275570353387113110',
              'volume_id' => 246933270
            }, 'Telegram::FileLocation' )
          }, 'Telegram::ChatPhoto' ),
          'date' => 1531221081
        }, 'Telegram::Channel' )
      ],
      'timeout' => 300,
      'other_updates' => [
        bless( {
          'pts_count' => 0,
          'message' => bless( {
            'post' => 1,
            'id' => 852,
            'flags' => 50368,
            'views' => 8013,
            'entities' => [
              bless( {
                'length' => 20,
                'offset' => 0
              }, 'Telegram::MessageEntityBold' ),
              bless( {
                'length' => 18,
                'offset' => 480,
                'url' => 'https://alexeymarkov.livejournal.com/[url_].html'
              }, 'Telegram::MessageEntityTextUrl' )
            ],
            'reply_markup' => bless( {
              'rows' => [
                bless( {
                  'buttons' => [
                    bless( {
                      'text' => '???? 165',
                      'data' => 'send_reaction_0'
                    }, 'Telegram::KeyboardButtonCallback' ),
                    bless( {
                      'data' => 'send_reaction_1',
                      'text' => '???? 9'
                    }, 'Telegram::KeyboardButtonCallback' )
                  ]
                }, 'Telegram::KeyboardButtonRow' )
              ]
            }, 'Telegram::ReplyInlineMarkup' ),
            'message' => '    ! 
// [         ]
 .',
            'to_id' => bless( {
              'channel_id' => 1380524958
            }, 'Telegram::PeerChannel' ),
            'date' => 1571724559,
            'edit_date' => 1571907562
          }, 'Telegram::Message' ),
          'pts' => 158508
        }, 'Telegram::UpdateEditChannelMessage' ),
        bless( {
          'pts' => 158508,
          'message' => bless( {
            'edit_date' => 1571907589,
            'to_id' => bless( {
              'channel_id' => 1380524958
            }, 'Telegram::PeerChannel' ),
            'date' => 1571807301,
            'message' => '   Facebook  ?  ? -,   .  ,   ,     ,      .

    :   Facebook     . ,      ,     .      . -       .  ,             ,     -      .    .

,     :     Whatsapp,  Instagram.     ,    !

    .     . - -   ,    .

# #facebook # #',
            'reply_markup' => bless( {
              'rows' => [
                bless( {
                  'buttons' => [
                    bless( {
                      'data' => 'send_reaction_0',
                      'text' => '???? 452'
                    }, 'Telegram::KeyboardButtonCallback' ),
                    bless( {
                      'text' => '???? 21',
                      'data' => 'send_reaction_1'
                    }, 'Telegram::KeyboardButtonCallback' )
                  ]
                }, 'Telegram::KeyboardButtonRow' )
              ]
            }, 'Telegram::ReplyInlineMarkup' ),
            'entities' => [
              bless( {
                'length' => 199,
                'offset' => 0
              }, 'Telegram::MessageEntityBold' ),
              bless( {
                'length' => 8,
                'offset' => 919
              }, 'Telegram::MessageEntityHashtag' ),
              bless( {
                'offset' => 928,
                'length' => 9
              }, 'Telegram::MessageEntityHashtag' ),
              bless( {
                'length' => 6,
                'offset' => 938
              }, 'Telegram::MessageEntityHashtag' ),
              bless( {
                'length' => 11,
                'offset' => 945
              }, 'Telegram::MessageEntityHashtag' )
            ],
            'views' => 6964,
            'flags' => 50368,
            'id' => 854,
            'post' => 1
          }, 'Telegram::Message' ),
          'pts_count' => 0
        }, 'Telegram::UpdateEditChannelMessage' ),
        bless( {
          'message' => bless( {
            'reply_markup' => bless( {
              'rows' => [
                bless( {
                  'buttons' => [
                    bless( {
                      'data' => 'send_reaction_0',
                      'text' => '???? 213'
                    }, 'Telegram::KeyboardButtonCallback' ),
                    bless( {
                      'data' => 'send_reaction_1',
                      'text' => '???? 8'
                    }, 'Telegram::KeyboardButtonCallback' )
                  ]
                }, 'Telegram::KeyboardButtonRow' )
              ]
            }, 'Telegram::ReplyInlineMarkup' ),
            'views' => 2940,
            'entities' => [
              bless( {
                'length' => 609,
                'offset' => 348
              }, 'Telegram::MessageEntityItalic' )
            ],
            'flags' => 50368,
            'post' => 1,
            'id' => 857,
            'edit_date' => 1571907636,
            'date' => 1571902479,
            'to_id' => bless( {
              'channel_id' => 1380524958
            }, 'Telegram::PeerChannel' ),
            'message' => '  1   .  10 (, 1-)  :
// [         ]

  ,    1 ,  ... , .'
          }, 'Telegram::Message' ),
          'pts_count' => 0,
          'pts' => 158508
        }, 'Telegram::UpdateEditChannelMessage' ),
        bless( {
          'pts' => 158508,
          'pts_count' => 0,
          'message' => bless( {
            'message' => ', , ,    1?

// [         ]
# #it #',
            'edit_date' => 1571907650,
            'date' => 1571893707,
            'to_id' => bless( {
              'channel_id' => 1380524958
            }, 'Telegram::PeerChannel' ),
            'flags' => 50368,
            'post' => 1,
            'id' => 856,
            'reply_markup' => bless( {
              'rows' => [
                bless( {
                  'buttons' => [
                    bless( {
                      'data' => 'send_reaction_0',
                      'text' => '???? 360'
                    }, 'Telegram::KeyboardButtonCallback' ),
                    bless( {
                      'data' => 'send_reaction_1',
                      'text' => '???? 32'
                    }, 'Telegram::KeyboardButtonCallback' )
                  ]
                }, 'Telegram::KeyboardButtonRow' )
              ]
            }, 'Telegram::ReplyInlineMarkup' ),
            'views' => 4416,
            'entities' => [
              bless( {
                'offset' => 0,
                'length' => 64
              }, 'Telegram::MessageEntityBold' ),
              bless( {
                'offset' => 1551,
                'length' => 5
              }, 'Telegram::MessageEntityHashtag' ),
              bless( {
                'length' => 3,
                'offset' => 1557
              }, 'Telegram::MessageEntityHashtag' ),
              bless( {
                'offset' => 1561,
                'length' => 10
              }, 'Telegram::MessageEntityHashtag' )
            ]
          }, 'Telegram::Message' )
        }, 'Telegram::UpdateEditChannelMessage' )
      ]
    }, 'Telegram::Updates::ChannelDifference' )
  }, 'MTProto::RpcResult' )
};

2019.10.24 12:00:51 $1 = {
  'in' => bless( {
    'update' => bless( {
      'user_id' => 2507460,
      'status' => bless( {
        'was_online' => 1571907651
      }, 'Telegram::UserStatusOffline' )
    }, 'Telegram::UpdateUserStatus' ),
    'date' => 1571907650
  }, 'Telegram::UpdateShort' )
};

2019.10.24 12:05:46 $1 = {
  'in' => bless( {
    'chats' => [],
    'date' => 1571907946,
    'seq' => 0,
    'updates' => [
      bless( {
        'max_id' => 141719,
        'channel_id' => 1295963795
      }, 'Telegram::UpdateReadChannelInbox' )
    ],
    'users' => []
  }, 'Telegram::Updates' )
};

2019.10.24 13:01:23 $1 = {
  'in' => bless( {
    'server_salt' => '4914425622822907323',
    'unique_id' => '5297282355827493819',
    'first_msg_id' => '6751307555044380692'
  }, 'MTProto::NewSessionCreated' )
};

2019.10.24 13:24:21 $1 = {
  'in' => bless( {
    'chats' => [
      bless( {
        'username' => 'freebsd_ru',
        'version' => 0,
        'flags' => 5440,
        'title' => 'freebsd_ru',
        'min' => 1,
        'photo' => bless( {
          'photo_small' => bless( {
            'local_id' => 328733,
            'volume_id' => 235140688,
            'dc_id' => 2,
            'file_reference' => '
            'secret' => '4426006807282303416'
          }, 'Telegram::FileLocation' ),
          'photo_big' => bless( {
            'dc_id' => 2,
            'file_reference' => '
            'volume_id' => 235140688,
            'local_id' => 328735,
            'secret' => '71251192991540083'
          }, 'Telegram::FileLocation' )
        }, 'Telegram::ChatPhoto' ),
        'date' => 1461248502,
        'id' => 1038300508,
        'democracy' => 1,
        'megagroup' => 1
      }, 'Telegram::Channel' )
    ],
    'users' => [
      bless( {
        'last_name' => 'Panov',
        'flags' => 1048646,
        'min' => 1,
        'id' => 82234609,
        'status' => bless( {}, 'Telegram::UserStatusRecently' ),
        'first_name' => 'Dima'
      }, 'Telegram::User' )
    ],
    'seq' => 0,
    'date' => 1571912647,
    'updates' => [
      bless( {
        'pts' => 137596,
        'message' => bless( {
          'flags' => 256,
          'message' => '     ??',
          'to_id' => bless( {
            'channel_id' => 1038300508
          }, 'Telegram::PeerChannel' ),
          'id' => 119634,
          'date' => 1571912647,
          'from_id' => 82234609
        }, 'Telegram::Message' ),
        'pts_count' => 1
      }, 'Telegram::UpdateNewChannelMessage' )
    ]
  }, 'Telegram::Updates' )
};

, — , !


Oh, wai~~… ? - … , Web API JSON, ?..


… , ?.. — , Web- ?.. JSON HTTPS ?! ? ?


, TL+MTProto, . , HTTP, "-", , - TLS ?


. , JSON, , . MsgPack , , , CBOR — , , RFC 7049. , , , :


  • 25 + 256 — ,
  • 26 — Perl c
  • 27 —

, TL CBOR . CBOR - :


cborlen=1039673 tl_len=1095092

, : , , .


. RTT ( ) — MTProto, — , , etc. TLS? :


PFS TLS TLS session tickets (RFC 5077) . , ( session ticket). , session ticket, , . ticket (session ticket key), frontend-, SSL .[10]. , session ticket PFS , , (OpenSSL, nginx, Apache ; , ).

RTT , ClientHello ServerHello, Finished . , Web, , , - , Web- — . , , .


- ? .


To be continued!


, — , , , .. , , , .


/ . , :


  • TL-
  • dialogs roster
  • vs
  • photo image

! Stay tuned!

Source: https://habr.com/ru/post/fr472970/


All Articles