Pagsaway sa protocol ug organisasyonal nga pamaagi sa Telegram. Bahin 1, teknikal: kasinatian sa pagsulat sa usa ka kliyente gikan sa wala - TL, MT

Bag-ohay lang, ang mga post bahin sa kung unsa ka maayo ang Telegram, kung unsa ka hayag ug eksperyensiyado ang mga igsoon nga Durov sa pagtukod sa mga sistema sa network, ug uban pa nagsugod nga makita nga mas kanunay sa Habré. Sa parehas nga oras, gamay ra nga mga tawo ang nagsulud gyud sa ilang kaugalingon sa teknikal nga aparato - sa kadaghanan, gigamit nila ang usa ka medyo yano (ug lahi kaayo sa MTProto) nga nakabase sa JSON nga Bot API, ug kasagaran modawat ra. sa pagtuo ang tanan nga pagdayeg ug PR nga naglibot sa mensahero. Hapit usa ka tuig ug tunga ang milabay, ang akong kauban sa Eshelon NGO Vasily (sa kasubo, ang iyang account sa Habré napapas kauban ang draft) nagsugod sa pagsulat sa iyang kaugalingon nga kliyente sa Telegram gikan sa wala sa Perl, ug sa ulahi ang tagsulat niini nga mga linya miapil. Ngano Perl, ang uban mangutana dayon? Tungod kay ang maong mga proyekto anaa na sa ubang mga pinulongan. Sa pagkatinuod, kini dili mao ang punto, mahimong adunay bisan unsa nga lain nga mga pinulongan diin walay andam nga librarya, ug sa ingon ang tagsulat kinahanglan nga magpadayon sa tanan nga paagi gikan sa wala. Dugang pa, ang cryptography usa ka butang sa pagsalig, apan pamatud-i. Uban sa usa ka produkto nga gitumong sa seguridad, dili ka makasalig lamang sa usa ka andam nga librarya gikan sa tiggama ug buta nga mosalig niini (bisan pa, kini usa ka hilisgutan alang sa ikaduha nga bahin). Sa pagkakaron, ang librarya nagtrabaho nga maayo sa "average" nga lebel (gitugotan ka sa paghimo sa bisan unsang mga hangyo sa API).

Bisan pa, wala’y daghang kriptograpiya o matematika sa kini nga serye sa mga post. Apan adunay daghang uban pang mga teknikal nga detalye ug mga crutches sa arkitektura (mapuslan usab alang niadtong dili mosulat gikan sa wala, apan mogamit sa librarya sa bisan unsang pinulongan). Busa, ang nag-unang tumong mao ang pagsulay sa pagpatuman sa kliyente gikan sa wala sumala sa opisyal nga dokumentasyon. Sa ato pa, isipon nato nga ang source code sa opisyal nga mga kliyente sirado (pag-usab, sa ikaduhang bahin atong tabonan sa mas detalyado ang hilisgutan sa kamatuoran nga kini tinuod. mahitabo mao nga), apan, sama sa karaang mga adlaw, pananglitan, adunay usa ka sumbanan sama sa RFC - posible ba nga magsulat sa usa ka kliyente sumala sa espesipikasyon nga nag-inusara, "nga wala magtan-aw" sa source code, mahimong opisyal (Telegram Desktop, mobile), o dili opisyal nga Telethon?

Talaan sa mga sulod:

Dokumentasyon... naa na, di ba? Tinuod ba?..

Ang mga tipik sa mga nota alang niini nga artikulo nagsugod sa pagkolekta sa miaging ting-init. Sa tanan niini nga panahon sa opisyal nga website https://core.telegram.org Ang dokumentasyon kay sa Layer 23, i.e. natanggong sa usa ka dapit sa 2014 (hinumdomi, wala pa gani mga channel kaniadto?). Siyempre, sa teorya, kini kinahanglan nga nagtugot kanamo sa pagpatuman sa usa ka kliyente nga adunay gamit nianang panahona sa 2014. Apan bisan pa niini nga estado, ang dokumentasyon, una, dili kompleto, ug ikaduha, sa mga lugar nga gisupak niini ang kaugalingon. Kapin sa usa ka bulan ang milabay, sa Septyembre 2019, kini sa aksidente Nadiskobrehan nga adunay usa ka dako nga pag-update sa dokumentasyon sa site, alang sa bag-o nga Layer 105, nga adunay usa ka nota nga karon ang tanan kinahanglan nga basahon pag-usab. Sa pagkatinuod, daghang artikulo ang girebisar, apan daghan ang wala mausab. Busa, kung magbasa sa mga pagsaway sa ubos bahin sa dokumentasyon, kinahanglan nimong hinumdoman nga ang pipila niini nga mga butang dili na angay, apan ang uban labi pa. Human sa tanan, ang 5 ka tuig sa modernong kalibutan dili lang usa ka taas nga panahon, apan kaayo daghan sa. Sukad niadtong mga panahona (ilabi na kung wala nimo tagda ang gilabay ug gibuhi nga mga geochat nga mga site sukad niadto), ang gidaghanon sa mga pamaagi sa API sa laraw mitubo gikan sa usa ka gatos ngadto sa kapin sa duha ka gatos ug kalim-an!

Asa magsugod isip usa ka batan-ong awtor?

Dili igsapayan kung nagsulat ka gikan sa wala o gigamit, pananglitan, andam nga mga librarya sama sa Telethon para sa Python o Madeline para sa PHP, sa bisan unsa nga kaso, kinahanglan nimo una irehistro ang imong aplikasyon - pagkuha mga parameter api_id и api_hash (kadtong nagtrabaho sa VKontakte API diha-diha dayon nakasabut) diin ang server makaila sa aplikasyon. Kini adunay buhata kini alang sa legal nga mga rason, apan kita maghisgot og dugang mahitungod kon nganong ang mga tagsulat sa librarya dili makamantala niini sa ikaduhang bahin. Mahimong matagbaw ka sa mga kantidad sa pagsulay, bisan kung kini limitado kaayo - ang kamatuoran mao nga mahimo ka na magparehistro usa ra app, busa ayaw pagdalidali niini.

Karon, gikan sa usa ka teknikal nga punto sa panglantaw, kita kinahanglan nga interesado sa kamatuoran nga human sa pagparehistro kinahanglan kita makadawat og mga pahibalo gikan sa Telegram mahitungod sa mga update sa dokumentasyon, protocol, ug uban pa. Kana mao, ang usa mahimong maghunahuna nga ang site nga adunay mga pantalan gibiyaan ra ug nagpadayon sa pagtrabaho nga piho sa mga nagsugod sa paghimo sa mga kliyente, tungod kay mas sayon. Apan wala, walay ingon niana nga naobserbahan, walay impormasyon nga miabut.

Ug kung nagsulat ka gikan sa wala, nan ang paggamit sa nakuha nga mga parameter sa tinuud layo pa. Bisan pa https://core.telegram.org/ ug naghisgot bahin kanila sa Pagsugod una sa tanan, sa tinuud, kinahanglan nimo nga ipatuman una Protocol sa MTProto - apan kung mituo ka layout sumala sa modelo sa OSI sa katapusan sa panid alang sa usa ka kinatibuk-ang paghulagway sa protocol, unya kini hingpit nga kawang.

Sa tinuud, sa wala pa ug pagkahuman sa MTProto, sa daghang lebel sa usa ka higayon (sama sa giingon sa mga langyaw nga network nga nagtrabaho sa kernel sa OS, paglapas sa layer), usa ka dako, sakit ug makalilisang nga hilisgutan ang makabalda ...

Binary serialization: TL (Type Language) ug ang laraw niini, ug mga layer, ug daghan pang makahadlok nga mga pulong

Kini nga hilisgutan, sa tinuud, mao ang yawe sa mga problema sa Telegram. Ug adunay daghang mga makalilisang nga mga pulong kung imong sulayan ang pagsusi niini.

Busa, ania ang diagram. Kung kini nga pulong moabut sa imong hunahuna, ingna, JSON Schema, Sakto ang imong gihunahuna. Ang tumong mao ang sama nga: ang pipila ka mga pinulongan sa paghulagway sa usa ka posible nga set sa transmitted data. Dinhi natapos ang pagkaparehas. Kung gikan sa page Protocol sa MTProto, o gikan sa punoan nga punoan sa opisyal nga kliyente, sulayan namon nga ablihan ang pipila nga schema, makita namon ang usa ka butang sama sa:

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;

Ang usa ka tawo nga nakakita niini sa unang higayon intuitively makahimo sa pag-ila lamang sa bahin sa kon unsa ang nahisulat - maayo, kini dayag nga mga istruktura (bisan tuod diin ang ngalan, sa wala o sa tuo?), adunay mga uma niini, human niana ang usa ka tipo mosunod human sa usa ka colon... lagmit. Dinhi sa mga anggulo nga bracket tingali adunay mga template sama sa C++ (sa tinuud, dili gyud). Ug unsa ang gipasabut sa tanan nga uban nga mga simbolo, mga marka sa pangutana, mga marka sa pagtuaw, mga porsyento, mga marka sa hash (ug dayag nga kini nagpasabut nga lainlain nga mga butang sa lainlaing mga lugar), usahay karon ug usahay dili, mga numero sa hexadecimal - ug labing hinungdanon, kung giunsa makuha gikan niini husto (nga dili isalikway sa server) byte stream? Kinahanglan nimo nga basahon ang dokumentasyon (oo, adunay mga link sa schema sa JSON nga bersyon sa duol - apan dili kini mas klaro).

Ablihi ang panid Binary Data Serialization ug mosalom sa mahika nga kalibotan sa mga uhong ug discrete mathematics, susama sa matan sa ika-4 nga tuig. Alpabeto, tipo, bili, combinator, functional combinator, normal nga porma, composite type, polymorphic type... ug kana lang ang unang panid! Sunod naghulat kanimo TL nga Pinulongan, nga, bisan kung kini adunay sulud nga usa ka pananglitan sa usa ka gamay nga hangyo ug tubag, wala gyud maghatag usa ka tubag sa labi ka kasagaran nga mga kaso, nga nagpasabut nga kinahanglan ka nga moagi sa usa ka pagsaysay pag-usab sa matematika nga gihubad gikan sa Ruso ngadto sa Ingles sa laing walo nga gilakip. mga panid!

Ang mga magbabasa nga pamilyar sa functional nga mga pinulongan ug automatic type inference, siyempre, makakita sa paghulagway sa pinulongan niini nga pinulongan, bisan gikan sa pananglitan, nga mas pamilyar, ug makaingon nga kini sa pagkatinuod dili daotan sa prinsipyo. Ang mga pagsupak niini mao ang:

  • oo, ang katuyoan paminawon maayo, apan alaot, siya wala makab-ot
  • Ang edukasyon sa mga unibersidad sa Russia lainlain bisan sa mga espesyalista sa IT - dili tanan nakakuha sa katugbang nga kurso
  • Sa katapusan, ingon sa atong makita, sa praktis mao kini dili gikinahanglan, tungod kay limitado ra nga subset bisan ang TL nga gihulagway ang gigamit

Ingon sa giingon LeoNerd sa kanal #perl sa FreeNode IRC network, kinsa misulay sa pagpatuman sa usa ka ganghaan gikan sa Telegram ngadto sa Matrix (ang paghubad sa kinutlo dili tukma gikan sa panumduman):

Morag adunay usa nga gipaila-ila sa pag-type sa teorya sa unang higayon, naghinam-hinam, ug nagsugod sa pagsulay sa pagdula niini, nga wala'y pagtagad kung gikinahanglan ba kini sa praktis.

Tan-awa alang sa imong kaugalingon, kung ang panginahanglan alang sa mga hubo nga tipo (int, taas, ug uban pa) ingon usa ka butang nga elementarya dili magpatunghag mga pangutana - sa katapusan kinahanglan nga ipatuman kini nga mano-mano - pananglitan, sulayan naton nga makuha gikan kanila vector. Kana mao, sa pagkatinuod, han-ay, kon imong tawgon ang resulta nga mga butang sa ilang tukma nga mga ngalan.

Apan kaniadto

Usa ka mubo nga paghulagway sa usa ka subset sa TL syntax alang niadtong wala makabasa sa opisyal nga dokumentasyon

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;

Ang kahulugan kanunay magsugod magtutukod, pagkahuman nga opsyonal (sa praktis - kanunay) pinaagi sa simbolo # kinahanglan CRC32 gikan sa na-normalize nga deskripsyon nga string sa niini nga matang. Sunod moabut ang usa ka paghulagway sa mga uma; kung kini anaa, ang tipo mahimong walay sulod. Kining tanan natapos sa usa ka patas nga ilhanan, ang ngalan sa matang diin kini nga constructor - nga mao, sa pagkatinuod, ang subtype - iya. Ang lalaki sa tuo sa parehas nga timaan mao ang polymorphic - kana mao, daghang mga piho nga tipo ang mahimong katumbas niini.

Kung ang kahulugan mahitabo pagkahuman sa linya ---functions---, unya ang syntax magpabilin nga pareho, apan ang kahulogan magkalahi: ang constructor mahimong ngalan sa RPC function, ang mga field mahimong mga parameter (maayo, nga mao, kini magpabilin nga parehas nga gihatag nga istruktura, sama sa gihulagway sa ubos , kini mao lamang ang gi-assign nga kahulogan), ug ang "polymorphic type" - ang tipo sa gibalik nga resulta. Tinuod, kini magpabilin gihapon nga polymorphic - gihubit lang sa seksyon ---types---, apan kini nga constructor "dili isipon". Ang sobra nga pagkarga sa mga tipo sa gitawag nga mga gimbuhaton pinaagi sa ilang mga argumento, i.e. Sa pila ka rason, daghang mga function nga adunay parehas nga ngalan apan lainlain nga mga pirma, sama sa C++, wala gihatag sa TL.

Ngano nga "constructor" ug "polymorphic" kung dili OOP? Aw, sa tinuud, mas dali alang sa usa ka tawo nga maghunahuna bahin niini sa mga termino sa OOP - usa ka polymorphic nga tipo ingon usa ka abstract nga klase, ug ang mga konstruktor mao ang direkta nga mga klase sa kaliwat, ug final sa terminolohiya sa daghang pinulongan. Sa pagkatinuod, siyempre, dinhi lamang pagkaparehas nga adunay tinuod nga overloaded constructor nga mga pamaagi sa OO programming languages. Tungod kay ania ra ang mga istruktura sa datos, wala’y mga pamaagi (bisan kung ang paghulagway sa mga gimbuhaton ug mga pamaagi labi pa nga makahimo sa paghimo sa kalibog sa ulo nga kini naglungtad, apan lahi kana nga butang) - mahimo nimong hunahunaon ang usa ka tigtukod ingon usa ka kantidad gikan sa nga ginatukod type kung nagbasa sa usa ka byte stream.

Sa unsang paagi kini mahitabo? Ang deserializer, nga kanunay nagbasa sa 4 bytes, nakakita sa kantidad 0xcrc32 - ug nasabtan kung unsa ang sunod nga mahitabo field1 uban sa tipo int, i.e. nagbasa sa eksakto nga 4 bytes, niini ang nag-una nga uma nga adunay tipo PolymorType basaha. Nakakita 0x2crc32 ug nakasabut nga adunay duha pa ka natad, una long, nga nagpasabot nga atong gibasa ang 8 bytes. Ug unya pag-usab sa usa ka komplikado nga matang, nga deserialized sa samang paagi. Pananglitan, Type3 mahimong ipahayag sa sirkito sa diha nga ang duha ka mga konstruktor, sa tinagsa, nan sila kinahanglan nga magkita bisan asa 0x12abcd34, pagkahuman kinahanglan nimo nga basahon ang 4 pa ka byte int, o 0x6789cdef, nga human niana wala nay bisan unsa. Bisan unsa pa - kinahanglan nimo nga ihulog ang usa ka eksepsiyon. Bisan pa, pagkahuman niini mobalik kami sa pagbasa sa 4 bytes int kapatagan field_c в constructorTwo ug uban niana atong tapuson ang pagbasa sa atong PolymorType.

Sa katapusan, kung madakpan ka 0xdeadcrc alang sa constructorThree, unya ang tanan mahimong mas komplikado. Ang among unang field mao bit_flags_of_what_really_present uban sa tipo # - sa tinuud, kini usa lamang ka alyas alang sa tipo nat, nga nagkahulogang "kinaiyanhong numero". Kana mao, sa tinuud, ang unsigned int, sa tinuud, ang bugtong kaso kung ang mga numero nga wala mapirmahan mahitabo sa tinuud nga mga sirkito. Busa, sunod mao ang usa ka pagtukod uban sa usa ka pangutana nga marka, nga nagpasabot nga kini nga uma - kini anaa sa wire lamang kon ang katugbang nga bit gibutang sa uma nga gihisgotan (gibana-bana nga sama sa usa ka ternary operator). Mao nga, atong hunahunaon nga kini nga gamay gitakda, nga nagpasabut nga kinahanglan pa naton basahon ang usa ka uma nga sama Type, nga sa among pananglitan adunay 2 nga mga konstruktor. Ang usa walay sulod (naglangkob lamang sa identifier), ang lain adunay field ids uban sa tipo ids:Vector<long>.

Mahimong maghunahuna ka nga ang mga templates ug generics anaa sa pros o Java. Apan dili. Hapit. Kini ang bugtong kaso sa paggamit sa angle bracket sa tinuod nga mga sirkito, ug kini gigamit LAMANG alang sa Vector. Sa usa ka byte stream, kini mahimong 4 CRC32 bytes para sa Vector type mismo, kanunay parehas, unya 4 bytes - ang gidaghanon sa array elements, ug dayon kini nga mga elemento mismo.

Idugang niini ang kamatuoran nga ang serialization kanunay nga mahitabo sa mga pulong sa 4 bytes, ang tanan nga mga matang mao ang multiples niini - ang mga built-in nga matang gihulagway usab. bytes и string nga adunay manual serialization sa gitas-on ug kini nga pag-align sa 4 - maayo, kini daw normal ug bisan medyo epektibo? Bisan kung ang TL giangkon nga usa ka epektibo nga binary serialization, sa impyerno uban kanila, uban ang pagpalapad sa bisan unsang butang, bisan ang mga kantidad sa Boolean ug mga string nga single-character hangtod sa 4 bytes, mas baga pa ba ang JSON? Tan-awa, bisan ang wala kinahanglana nga mga natad mahimong laktawan sa gamay nga mga bandila, ang tanan maayo kaayo, ug bisan pa nga madugangan alang sa umaabot, busa ngano nga dili magdugang bag-ong mga opsyonal nga natad sa magtutukod sa ulahi?

Apan dili, kung dili nimo basahon ang akong mubo nga paghulagway, apan ang tibuuk nga dokumentasyon, ug hunahunaa ang pagpatuman. Una, ang CRC32 sa constructor gikalkulo sumala sa normalized nga linya sa text description sa scheme (kuhaa ang dugang nga whitespace, ug uban pa) - busa kung ang usa ka bag-ong field idugang, ang tipo nga linya sa paghulagway mausab, ug busa ang CRC32 ug , sa ingon, serialization. Ug unsa ang buhaton sa tigulang nga kliyente kung makadawat siya usa ka uma nga adunay bag-ong mga bandila nga gibutang, ug wala siya mahibal-an kung unsa ang sunod nga buhaton niini?..

Ikaduha, atong hinumdoman CRC32, nga gigamit dinhi sa esensya ingon hash nga mga gimbuhaton aron talagsaon nga mahibal-an kung unsa nga klase ang (de)serialized. Dinhi kita nag-atubang sa problema sa mga bangga - ug dili, ang kalagmitan dili usa sa 232, apan mas dako. Kinsa ang nakahinumdom nga ang CRC32 gidisenyo aron mahibal-an (ug matul-id) ang mga sayup sa channel sa komunikasyon, ug sa ingon gipauswag kini nga mga kabtangan sa makadaot sa uban? Pananglitan, wala kini'y pagtagad sa pag-usab sa mga byte: kung imong kuwentahon ang CRC32 gikan sa duha ka linya, sa ikaduha imong ibaylo ang unang 4 bytes sa sunod nga 4 bytes - parehas ra kini. Kung ang among input kay text strings gikan sa Latin nga alpabeto (ug gamay nga punctuation), ug kini nga mga ngalan dili basta-basta, ang posibilidad sa ingon nga pag-usab sa pag-uswag modako.

By the way, kinsay nagsusi unsay naa? gyud CRC32? Usa sa unang mga source code (bisan sa wala pa ang Waltman) adunay hash function nga nagpadaghan sa matag karakter sa numero nga 239, gihigugma kaayo niining mga tawhana, ha ha!

Sa katapusan, okay, nahibal-an namon nga ang mga konstruktor nga adunay usa ka klase sa uma Vector<int> и Vector<PolymorType> adunay lahi nga CRC32. Komosta ang on-line nga pasundayag? Ug gikan sa teoretikal nga punto sa panglantaw, nahimo ba kini nga bahin sa tipo? Ingnon ta nga gipasa nato ang usa ka han-ay sa napulo ka libo nga mga numero, maayo sa Vector<int> klaro ang tanan, ang gitas-on ug laing 40000 bytes. Unsa kaha kung kini Vector<Type2>, nga naglangkob sa usa lamang ka field int ug kini nag-inusara sa tipo - kinahanglan ba natong balikon ang 10000xabcdef0 34 ka beses ug dayon 4 bytes int, o ang pinulongan makahimo sa INDEPEND niini alang kanato gikan sa constructor fixedVec ug imbes 80000 bytes, 40000 na lang ang transfer?

Dili kini usa ka walay pulos nga teoretikal nga pangutana - hunahunaa nga nakadawat ka usa ka lista sa mga tiggamit sa grupo, nga ang matag usa adunay usa ka id, una nga ngalan, apelyido - ang kalainan sa kantidad sa data nga gibalhin sa usa ka mobile nga koneksyon mahimong hinungdanon. Kini ang tukma nga pagka-epektibo sa serialization sa Telegram nga gi-anunsyo kanamo.

Kaya nga…

Vector, nga wala gayud gipagawas

Kung mosulay ka sa pag-agi sa mga panid sa paghulagway sa mga combinator ug uban pa, imong makita nga ang usa ka vector (ug bisan usa ka matrix) pormal nga naningkamot nga ma-output pinaagi sa mga tuple sa daghang mga sheet. Apan sa katapusan nakalimtan nila, ang katapusang lakang gilaktawan, ug ang usa ka kahulugan sa usa ka vector gihatag ra, nga wala pa nahigot sa usa ka tipo. Unsay problema? Sa mga pinulongan programa, labi na ang mga magamit, kasagaran nga ihulagway ang istruktura nga balikbalik - ang compiler nga adunay tapulan nga pagtimbang-timbang makasabut ug buhaton ang tanan sa iyang kaugalingon. Sa pinulongan data serialization ang gikinahanglan kay EFFICIENCY: igo na lang ihulagway listahan, i.e. usa ka istruktura sa duha ka elemento - ang una usa ka elemento sa datos, ang ikaduha mao ang parehas nga istruktura mismo o usa ka walay sulod nga wanang alang sa ikog (pack (cons) sa Lisp). Apan kini klaro nga magkinahanglan matag usa Ang elemento naggasto ug dugang nga 4 bytes (CRC32 sa kaso sa TL) aron ihulagway ang tipo niini. Ang usa ka array dali usab nga mahulagway fixed nga gidak-on, apan sa kaso sa usa ka han-ay sa wala mahibal-an nga gitas-on nga abante, kami magbulag.

Busa, tungod kay ang TL wala magtugot sa pag-output sa usa ka vector, kini kinahanglan nga idugang sa kilid. Sa katapusan ang dokumentasyon nag-ingon:

Ang serialization kanunay naggamit sa samang constructor nga "vector" (const 0x1cb5c415 = crc32("vector t: Type # [t ] = Vector t") nga wala magdepende sa espesipikong bili sa variable sa tipo nga t.

Ang bili sa opsyonal nga parametro t wala maapil sa serialization tungod kay kini nakuha gikan sa resulta nga matang (kanunay nahibal-an sa wala pa ang deserialization).

Tan-awa pag-ayo: vector {t:Type} # [ t ] = Vector t - apan wala Kini nga kahulugan mismo wala mag-ingon nga ang una nga numero kinahanglan nga katumbas sa gitas-on sa vector! Ug kini dili gikan sa bisan asa. Kini usa ka gihatag nga kinahanglan ibutang sa hunahuna ug ipatuman sa imong mga kamot. Sa bisan diin, ang dokumentasyon bisan matinud-anon nga naghisgot nga ang tipo dili tinuod:

Ang Vector t polymorphic pseudotype usa ka "tipo" kansang kantidad usa ka han-ay sa mga kantidad sa bisan unsang tipo t, bisan sa kahon o hubo.

... apan wala mag-focus niini. Kung ikaw, gikapoy sa pag-uswag sa matematika (tingali nahibal-an nimo gikan sa usa ka kurso sa unibersidad), nakahukom nga mohunong ug tan-awa kung giunsa kini pagtrabaho sa praktis, ang nahabilin nga impresyon sa imong ulo mao nga kini Seryoso. Ang matematika sa kinauyokan, kini tin-aw nga naimbento sa Cool People (duha ka mathematician - ACM winner), ug dili kay bisan kinsa. Nakab-ot na ang tumong - ang pagpasigarbo.

Pinaagi sa dalan, mahitungod sa gidaghanon. Pahinumdoman ka namo niana # kini usa ka synonym nat, natural nga numero:

Adunay mga tipo nga ekspresyon (tipo-expr) ug numeric nga mga ekspresyon (nat-expr). Apan, sila gihubit sa samang paagi.

type-expr ::= expr
nat-expr ::= expr

apan sa gramatika sila gihulagway sa samang paagi, i.e. Kini nga kalainan kinahanglan nga hinumdoman pag-usab ug ipatuman nga mano-mano.

Aw, oo, mga tipo sa template (vector<int>, vector<User>) adunay komon nga identifier (#1cb5c415), i.e. kung nahibal-an nimo nga ang tawag gipahibalo ingon

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

unya dili ka na maghulat alang lamang sa usa ka vector, apan usa ka vector sa mga tiggamit. Mas tukma, kinahanglan paghulat - sa tinuud nga code, ang matag elemento, kung dili usa ka hubo nga tipo, adunay usa ka konstruktor, ug sa maayong paagi sa pagpatuman kinahanglan nga susihon - apan gipadala kami sa eksakto sa matag elemento niini nga vector kana nga tipo? Unsa kaha kung kini usa ka matang sa PHP, diin ang usa ka array mahimong adunay lainlaing mga lahi sa lainlaing mga elemento?

Niini nga punto nagsugod ka sa paghunahuna - kinahanglan ba ang ingon nga TL? Tingali alang sa kariton posible nga mogamit usa ka serializer sa tawo, ang parehas nga protobuf nga naglungtad na kaniadto? Kana ang teorya, tan-awon naton ang praktis.

Anaa nga mga pagpatuman sa TL sa code

Ang TL natawo sa kahiladman sa VKontakte bisan sa wala pa ang bantog nga mga panghitabo sa pagbaligya sa bahin ni Durov ug (sa pagkatinuod), bisan sa wala pa magsugod ang pag-uswag sa Telegram. Ug sa open source source code sa unang pagpatuman makit-an nimo ang daghang kataw-anan nga crutches. Ug ang pinulongan mismo gipatuman didto nga mas bug-os kay sa karon sa Telegram. Pananglitan, ang mga hash wala gigamit sa laraw (nagpasabot nga usa ka built-in nga pseudotype (sama sa usa ka vector) nga adunay dili maayo nga pamatasan). O

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

apan atong tagdon, alang sa kahingpitan, sa pagsubay, ingnon ta, ang ebolusyon sa Higante sa Panghunahuna.

#define ZHUKOV_BYTES_HACK

#ifdef ZHUKOV_BYTES_HACK

/* dirty hack for Zhukov request */

O kining nindot:

    static const char *reserved_words_polymorhic[] = {

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

      };

Kini nga tipik mahitungod sa mga templates sama sa:

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

Kini ang kahulugan sa usa ka tipo sa template sa hashmap ingon usa ka vector sa int - Type nga mga pares. Sa C++ kini tan-awon sama niini:

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

mao nga, alpha - keyword! Apan sa C ++ lamang nga mahimo nimong isulat ang T, apan kinahanglan nimo nga isulat ang alpha, beta ... Apan dili molapas sa 8 nga mga parameter, diin natapos ang pantasya. Morag kaniadto sa St. Petersburg nahitabo ang pipila ka mga dayalogo nga sama niini:

-- Надо сделать в TL шаблоны
-- Бл... Ну пусть параметры зовут альфа, бета,... Какие там ещё буквы есть... О, тэта!
-- Грамматика? Ну потом напишем

-- Смотрите, какой я синтаксис придумал для шаблонов и вектора!
-- Ты долбанулся, как мы это парсить будем?
-- Да не ссыте, он там один в схеме, захаркодить -- и ок

Apan kini mahitungod sa unang gipatik nga pagpatuman sa TL "sa kinatibuk-an". Magpadayon kita sa pagkonsiderar sa mga pagpatuman sa mga kliyente sa Telegram mismo.

Pulong kang Vasily:

Vasily, [09.10.18 17:07] Labaw sa tanan, init ang asno tungod kay nagmugna sila og pundok sa mga abstraction, ug dayon gimartilyo kini og bolt, ug gitabonan ang code generator og mga saklay.
Ingon usa ka sangputanan, una gikan sa pantalan pilot.jpg
Unya gikan sa code dzhekichan.webp

Siyempre, gikan sa mga tawo nga pamilyar sa mga algorithm ug matematika, makadahom kita nga ilang nabasa ang Aho, Ullmann, ug pamilyar sa mga himan nga nahimong de facto nga sumbanan sa industriya sulod sa mga dekada alang sa pagsulat sa ilang DSL compiler, di ba?..

Pinaagi sa telegrama-cli mao si Vitaly Valtman, ingon nga masabtan gikan sa pagkahitabo sa TLO format sa gawas sa (cli) mga utlanan niini, usa ka miyembro sa team - karon usa ka librarya alang sa TL parsing ang gigahin gilain, unsay impresyon niya TL parser? ..

16.12 04:18 Vasily: Sa akong hunahuna adunay usa nga wala mag-master sa lex+yacc
16.12 04:18 Vasily: Dili nako mapasabut kini kung dili
16.12 04:18 Vasily: maayo, o gibayran sila alang sa gidaghanon sa mga linya sa VK
16.12 04:19 Vasily: 3k+ nga linya ug uban pa.<censored> imbes nga parser

Tingali usa ka eksepsiyon? Tan-awon nato kung giunsa nagahimo Kini ang OPISYAL nga kliyente - 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+ nga mga linya sa Python, usa ka magtiayon nga mga regular nga ekspresyon + espesyal nga mga kaso sama sa usa ka vector, nga, siyempre, gipahayag sa laraw ingon nga kini kinahanglan nga sumala sa TL syntax, apan sila nagsalig niini nga syntax sa parse niini... Mitungha ang pangutana, nganong milagro man kining tanan?иMas lut-od kini kung walay usa nga mag-parse niini sumala sa dokumentasyon gihapon?!

By the way... Hinumdumi nga naghisgot kami bahin sa pagsusi sa CRC32? Mao nga, sa Telegram Desktop code generator adunay usa ka lista sa mga eksepsiyon alang sa mga tipo diin ang kalkulado nga CRC32 dili tugma uban sa gipakita sa dayagram!

Vasily, [18.12/22 49:XNUMX] ug dinhi maghunahuna ko kung gikinahanglan ba ang ingon nga TL
kung gusto nako nga magsamok sa mga alternatibong pagpatuman, magsugod ako sa pagsal-ot sa mga linya sa linya, ang katunga sa mga parser mabuak sa mga kahulugan sa multi-line
tdesktop, bisan pa, usab

Hinumdumi ang punto mahitungod sa usa ka liner, kita mobalik niini sa ulahi.

Okay, dili opisyal ang telegram-cli, opisyal ang Telegram Desktop, apan komosta ang uban? Kinsay nahibalo?.. Sa Android client code walay schema parser sa tanan (nga nagpatunghag mga pangutana mahitungod sa open source, apan kini alang sa ikaduhang bahin), apan adunay daghang uban pang mga kataw-anan nga mga piraso sa code, apan labaw pa sa kanila sa subseksyon sa ubos.

Unsa pa nga mga pangutana ang gipatungha sa serialization sa praktis? Pananglitan, naghimo sila og daghang mga butang, siyempre, nga adunay mga bit field ug conditional field:

Vasily: flags.0? true
nagpasabot nga ang natad anaa ug katumbas sa tinuod kung ang bandila gibutang

Vasily: flags.1? int
nagpasabot nga ang uma anaa ug kinahanglan nga deserialized

Vasily: Ass, ayaw kabalaka sa imong gibuhat!
Vasily: Adunay usa ka paghisgot sa usa ka dapit sa doc nga tinuod mao ang usa ka hubo nga zero-gitas-on nga tipo, apan imposible nga mag-assemble bisan unsa gikan sa ilang doc
Vasily: Sa bukas nga gigikanan nga mga pagpatuman dili usab kini ang kaso, apan adunay daghang mga saklay ug suporta.

Unsa man ang bahin sa Telethon? Pagtan-aw sa unahan sa hilisgutan sa MTProto, usa ka pananglitan - sa dokumentasyon adunay mga piraso nga sama niini, apan ang timaan % kini gihulagway lamang nga "katugbang sa usa ka gihatag nga hubo-type", i.e. sa mga pananglitan sa ubos adunay usa ka sayup o usa ka butang nga wala’y dokumento:

Vasily, [22.06.18 18:38] Sa usa ka dapit:

msg_container#73f1f8dc messages:vector message = MessageContainer;

Sa lahi nga:

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

Ug kini ang duha ka dagkong kalainan, sa tinuud nga kinabuhi adunay usa ka matang sa hubo nga vector nga moabut

Wala koy nakita nga hubo nga kahulugan sa vector ug wala pa ako makit-an

Ang pagtuki gisulat pinaagi sa kamot sa telethon

Sa iyang diagram ang kahulugan gikomentaryo msg_container

Pag-usab, ang pangutana nagpabilin mahitungod sa%. Wala kini gihulagway.

Vadim Goncharov, [22.06.18 19:22] ug sa tdesktop?

Vasily, [22.06.18 19:23] Apan ang ilang TL parser sa regular nga mga makina lagmit dili usab mokaon niini

// parsed manually

Ang TL usa ka matahum nga abstraction, walay usa nga nagpatuman niini sa hingpit

Ug ang % wala sa ilang bersyon sa laraw

Apan dinhi ang dokumentasyon nagkasumpaki sa iyang kaugalingon, busa idk

Nakit-an kini sa gramatika, nakalimtan na lang nila ang paghulagway sa mga semantiko

Nakita nimo ang dokumento sa TL, dili nimo mahibal-an kung wala’y tunga sa litro

"Bueno, ingnon ta," ang usa ka magbabasa moingon, "gisaway nimo ang usa ka butang, busa ipakita kanako kung giunsa kini buhaton."

Si Vasily mitubag: “Kon bahin sa parser, ganahan ko sa mga butang nga sama niini

    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 ) ); }
            ;

sa usa ka paagi ganahan kini kay sa

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;
}

o

        # 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
                [wd<>#.?!]+  # 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
            ([wd<>#.?]+)     # The result can again be as complex as any argument type
            ;$                 # Finally, the line should always end with ;
            ''', tl, re.IGNORECASE | re.VERBOSE)

kini ang TIBUOK lexer:

    ---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];

mga. ang mas simple mao ang pagbutang niini nga malumo.”

Sa kinatibuk-an, isip resulta, ang parser ug code generator para sa aktuwal nga gigamit nga subset sa TL mohaum sa gibana-bana nga 100 ka linya sa gramatika ug ~300 ka linya sa generator (nag-ihap sa tanan. print's generated code), lakip ang type information buns para sa introspection sa matag klase. Ang matag polymorphic type nahimo nga usa ka walay sulod nga abstract base nga klase, ug ang mga konstruktor nakapanunod gikan niini ug adunay mga pamaagi alang sa serialization ug deserialization.

Kakulang sa mga tipo sa tipo nga pinulongan

Ang kusog nga pag-type usa ka maayong butang, di ba? Dili, kini dili usa ka holivar (bisan kung gusto nako ang dinamikong mga pinulongan), apan usa ka postulate sulod sa gambalay sa TL. Pinasukad niini, ang lengguwahe kinahanglan maghatag sa tanan nga mga matang sa mga pagsusi alang kanamo. Aw, okay, tingali dili siya sa iyang kaugalingon, apan ang pagpatuman, apan siya kinahanglan nga labing menos ihulagway sila. Ug unsa nga matang sa mga oportunidad ang gusto nato?

Una sa tanan, mga limitasyon. Dinhi atong makita sa dokumentasyon alang sa pag-upload sa mga file:

Ang binary nga sulod sa file gibahin ngadto sa mga bahin. Ang tanan nga mga bahin kinahanglan adunay parehas nga gidak-on ( bahin_kadako ) ug ang mosunod nga mga kondisyon kinahanglang matuman:

  • part_size % 1024 = 0 (mabahin sa 1KB)
  • 524288 % part_size = 0 (512KB kinahanglan nga parehas nga bahinon sa part_size)

Ang katapusan nga bahin dili kinahanglan nga makatagbaw niini nga mga kondisyon, basta ang gidak-on niini mas gamay kay sa part_size.

Ang matag bahin kinahanglan adunay sequence number, file_part, nga adunay kantidad gikan sa 0 hangtod 2,999.

Human mabahin ang file kinahanglan nimo nga pilion ang pamaagi sa pagtipig niini sa server. Paggamit upload.saveBigFilePart kung ang tibuuk nga gidak-on sa file labaw pa sa 10 MB ug upload.saveFilePart alang sa gagmay nga mga file.
[...] usa sa mosunod nga mga sayop sa pag-input sa datos mahimong ibalik:

  • FILE_PARTS_INVALID — Dili balido nga gidaghanon sa mga bahin. Ang bili dili sa taliwala 1..3000

Aduna bay usa niini sa diagram? Kini ba sa usa ka paagi mapahayag gamit ang TL? Dili. Apan pasayloa ako, bisan ang Turbo Pascal sa apohan nakahimo sa paghulagway sa mga tipo nga gipiho mga han-ay. Ug nahibal-an niya ang usa pa ka butang, karon mas nailhan nga enum - usa ka tipo nga gilangkuban sa usa ka enumeration sa usa ka pirmi (gamay) nga gidaghanon sa mga kantidad. Sa mga pinulongan sama sa C - numeric, timan-i nga hangtod karon naghisgot lang kami bahin sa mga tipo mga numero. Apan adunay usab mga arrays, mga kuwerdas ... pananglitan, nindot nga ihulagway nga kini nga pisi mahimo ra nga adunay usa ka numero sa telepono, di ba?

Walay usa niini ang naa sa TL. Apan adunay, pananglitan, sa JSON Schema. Ug kung adunay lain nga makiglalis bahin sa pagkabahinbahin sa 512 KB, nga kinahanglan pa kini susihon sa code, nan siguroha nga ang kliyente yano ra. wala koy mahimo magpadala ug numero nga wala sa range 1..3000 (ug ang katugbang nga sayop dili unta motumaw) kini mahimo unta, dili ba?..

Pinaagi sa dalan, mahitungod sa mga kasaypanan ug pagbalik sa mga bili. Bisan ang mga nagtrabaho kauban ang TL nagpaburot sa ilang mga mata - wala dayon kini nahibal-an kanamo matag usa Ang usa ka function sa TL mahimo nga makabalik dili lamang sa gihulagway nga tipo sa pagbalik, apan usa usab ka sayup. Apan dili kini matukib sa bisan unsang paagi gamit ang TL mismo. Siyempre, kini klaro na ug wala'y kinahanglan sa bisan unsa sa praktis (bisan pa sa pagkatinuod, RPC mahimong buhaton sa lain-laing mga paagi, kita mobalik niini sa ulahi) - apan unsa ang mahitungod sa Kaputli sa mga konsepto sa Matematika sa Abstract Types gikan sa langitnong kalibutan?.. Gipunit nako ang tug - so match it.

Ug sa katapusan, unsa ang bahin sa pagkabasa? Aw, didto, sa kinatibuk-an, gusto ko paghulagway naa ba kini sa husto sa schema (sa JSON schema, pag-usab, kini mao ang), apan kung ikaw na strained uban niini, nan unsa ang bahin sa praktikal nga bahin - sa labing menos trivially pagtan-aw sa mga diffs sa panahon sa updates? Tan-awa ang imong kaugalingon sa tinuod nga mga ehemplo:

-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;

o

-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;

Nagdepende kini sa tanan, apan ang GitHub, pananglitan, nagdumili sa pag-highlight sa mga pagbag-o sa sulod sa ingon ka taas nga linya. Ang dula nga "pagpangita sa 10 nga mga kalainan", ug kung unsa ang nakita dayon sa utok mao nga ang mga sinugdanan ug katapusan sa duha nga mga pananglitan managsama, kinahanglan nimo nga makalaay nga basahon sa usa ka dapit sa tunga-tunga... Sa akong opinyon, kini dili lamang sa teorya, pero puro visually hugaw ug palpak.

Pinaagi sa dalan, mahitungod sa kaputli sa teorya. Ngano nga kinahanglan naton ang mga bit field? Di ba murag sila baho dili maayo gikan sa punto sa panglantaw sa type theory? Ang katin-awan makita sa naunang mga bersyon sa diagram. Sa sinugdan, oo, ingon niana kini, alang sa matag pagbahin usa ka bag-ong tipo ang nahimo. Kini nga mga sukaranan anaa gihapon niini nga porma, pananglitan:

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;

Apan karon hunahunaa, kung ikaw adunay 5 nga opsyonal nga mga natad sa imong istruktura, nan kinahanglan nimo ang 32 nga mga tipo alang sa tanan nga posible nga kapilian. Kombinatoryal nga pagbuto. Sa ingon, ang kristal nga kaputli sa teorya sa TL sa makausa pa nabuak batok sa cast-iron nga asno sa mapintas nga kamatuoran sa serialization.

Dugang pa, sa pipila ka mga lugar kini nga mga lalaki mismo naglapas sa ilang kaugalingon nga tipolohiya. Pananglitan, sa MTProto (sunod nga kapitulo) ang tubag mahimong ma-compress sa Gzip, ang tanan maayo - gawas nga ang mga lut-od ug sirkito gilapas. Sa makausa pa, dili ang RpcResult mismo ang naani, kondili ang sulod niini. Aw, nganong buhaton kini?.. Kinahanglan kong magputol sa usa ka saklay aron ang compression molihok bisan asa.

O lain nga pananglitan, nadiskubrehan namon kaniadto ang usa ka sayup - gipadala kini InputPeerUser imbis nga InputUser. O vice versa. Apan kini milampos! Kana mao, ang server wala magtagad sa tipo. Sa unsang paagi mahimo kini? Ang tubag mahimong ihatag kanamo pinaagi sa mga tipik sa code gikan sa 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);

Sa laing pagkasulti, dinhi gihimo ang serialization MANUAL, dili namugna nga code! Tingali ang server gipatuman sa susama nga paagi?.. Sa prinsipyo, kini molihok kung buhaton kausa, apan unsaon kini pagsuporta sa ulahi sa panahon sa mga update? Mao ba kini ang hinungdan nga ang laraw giimbento? Ug dinhi kita magpadayon sa sunod nga pangutana.

Pag-bersyon. Mga lut-od

Ngano nga ang mga bersyon sa eskematiko gitawag nga mga sapaw mahimo ra nga mahunahuna base sa kasaysayan sa gipatik nga mga eskema. Dayag, sa sinugdan ang mga tagsulat naghunahuna nga ang sukaranang mga butang mahimo gamit ang wala mausab nga laraw, ug kung gikinahanglan, alang sa piho nga mga hangyo, nagpakita nga kini gihimo gamit ang usa ka lahi nga bersyon. Sa prinsipyo, bisan ang usa ka maayo nga ideya - ug ang bag-o, ingon nga kini, "gisagol", gipatong sa ibabaw sa daan. Apan tan-awon nato kung giunsa kini nahimo. Tinuod, dili nako kini matan-aw gikan sa sinugdanan - kini kataw-anan, apan ang diagram sa base layer wala gyud. Ang mga layer nagsugod sa 2. Ang dokumentasyon nagsulti kanamo bahin sa usa ka espesyal nga bahin sa TL:

Kung ang usa ka kliyente nagsuporta sa Layer 2, nan ang mosunod nga constructor kinahanglan gamiton:

invokeWithLayer2#289dd1f6 {X:Type} query:!X = X;

Sa praktis, kini nagpasabut nga sa wala pa ang matag tawag sa API, usa ka int nga adunay kantidad 0x289dd1f6 kinahanglan idugang sa wala pa ang numero sa pamaagi.

Morag normal. Apan unsay sunod nga nahitabo? Unya nagpakita

invokeWithLayer3#b7475268 query:!X = X;

Busa unsa ang sunod? Sama sa imong gihunahuna,

invokeWithLayer4#dea0d430 query:!X = X;

Kataw-anan? Dili, sayo pa kaayo para magkatawa, hunahunaa ang kamatuoran nga matag usa Ang usa ka hangyo gikan sa lain nga layer kinahanglan nga maputos sa usa ka espesyal nga tipo - kung naa nimo silang tanan nga lahi, unsaon pa nimo mailhan sila? Ug ang pagdugang lang sa 4 bytes sa atubangan usa ka maayo nga pamaagi. Busa,

invokeWithLayer5#417a57ae query:!X = X;

Apan kini mao ang dayag nga human sa usa ka samtang kini mahimong usa ka matang sa bacchanalia. Ug ang solusyon miabut:

Update: Sugod sa Layer 9, mga pamaagi sa katabang invokeWithLayerN magamit lamang uban sa initConnection

Hooray! Pagkahuman sa 9 nga mga bersyon, sa katapusan nahibal-an namon kung unsa ang nahimo sa mga protocol sa Internet kaniadtong 80s - nagkauyon sa bersyon kausa sa pagsugod sa koneksyon!

Busa unsa ang sunod?..

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

Pero karon makatawa ka pa. Pagkahuman lamang sa lain nga 9 nga mga layer, usa ka unibersal nga konstruktor nga adunay usa ka numero sa bersyon ang sa katapusan gidugang, nga kinahanglan tawagan kausa ra sa pagsugod sa koneksyon, ug ang kahulugan sa mga layer ingon og nawala, karon kini usa ka kondisyon nga bersyon, sama sa. bisan asa pa. Nasulbad ang problema.

Sakto?..

Vasily, [16.07.18 14:01] Bisan sa Biyernes naghunahuna ko:
Ang teleserver nagpadala sa mga panghitabo nga walay hangyo. Ang mga hangyo kinahanglang maputos sa InvokeWithLayer. Ang server wala magputos sa mga update; walay istruktura alang sa pagputos sa mga tubag ug mga update.

Mga. dili matino sa kliyente ang layer diin gusto niya ang mga update

Vadim Goncharov, [16.07.18 14:02] dili ba ang InvokeWithLayer usa ka crutch sa prinsipyo?

Vasily, [16.07.18 14:02] Kini ang bugtong paagi

Vadim Goncharov, [16.07.18 14:02] nga kinahanglan magpasabot sa pag-uyon sa layer sa sinugdanan sa sesyon

Pinaagi sa dalan, kini nagsunod nga ang pag-downgrade sa kliyente wala gihatag

Mga update, i.e. matang Updates sa laraw, kini ang gipadala sa server sa kliyente dili sa pagtubag sa usa ka hangyo sa API, apan independente kung adunay usa ka panghitabo. Kini usa ka komplikado nga hilisgutan nga hisgutan sa lain nga post, apan sa pagkakaron importante nga mahibal-an nga ang server nagtipig sa mga Update bisan kung offline ang kliyente.

Busa, kung magdumili ka sa pagputos matag usa package aron ipakita ang bersyon niini, kini lohikal nga mosangpot sa mosunod nga posibleng mga problema:

  • ang server nagpadala sa mga update sa kliyente bisan sa wala pa ang kliyente nagpahibalo kung unsang bersyon ang gisuportahan niini
  • unsa ang akong buhaton pagkahuman sa pag-upgrade sa kliyente?
  • kinsa garantiyanga ang opinyon sa server bahin sa numero sa layer dili mausab sa panahon sa proseso?

Sa imong hunahuna kini ba puro teoretikal nga pangagpas, ug sa praktis dili kini mahitabo, tungod kay ang server gisulat sa husto (labing menos, kini gisulayan pag-ayo)? Ha! Bisag unsaon!

Mao gyud kini ang among nasugatan kaniadtong Agosto. Kaniadtong Agosto 14, adunay mga mensahe nga adunay gi-update sa mga server sa Telegram ... ug dayon sa mga troso:

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.

ug dayon pipila ka megabytes sa stack traces (maayo, sa samang higayon ang logging naayo). Pagkahuman, kung adunay dili mailhan sa imong TL, kini binary pinaagi sa pirma, labi pa sa linya TANAN moadto, decoding mahimong imposible. Unsay angay nimong buhaton sa maong sitwasyon?

Aw, ang unang butang nga mosantop sa hunahuna ni bisan kinsa mao ang pagdiskonekta ug pagsulay pag-usab. Wala makatabang. Gi-google namo ang CRC32 - kini nahimo nga mga butang gikan sa scheme 73, bisan kung nagtrabaho kami sa 82. Gitan-aw namon pag-ayo ang mga troso - adunay mga identifier gikan sa duha nga lainlaing mga laraw!

Basin naa ra sa among unofficial nga kliyente ang problema? Dili, gilusad namo ang Telegram Desktop 1.2.17 (bersyon nga gihatag sa daghang mga distribusyon sa Linux), nagsulat kini sa Exception log: MTP Wala damha nga type id #b5223b0f gibasa sa MTPMessageMedia…

Pagsaway sa protocol ug organisasyonal nga pamaagi sa Telegram. Bahin 1, teknikal: kasinatian sa pagsulat sa usa ka kliyente gikan sa wala - TL, MT

Gipakita sa Google nga ang usa ka susama nga problema nahitabo na sa usa sa dili opisyal nga mga kliyente, apan unya ang mga numero sa bersyon ug, sumala niana, ang mga pangagpas lahi ...

Busa unsay angay natong buhaton? Kami ni Vasily nagbulag: gisulayan niya nga i-update ang circuit sa 91, nakahukom ko nga maghulat pipila ka adlaw ug sulayan ang 73. Ang duha nga mga pamaagi nagtrabaho, apan tungod kay kini empirical, wala’y pagsabut kung pila ang mga bersyon pataas o paubos nga kinahanglan nimo. sa paglukso, o unsa ka dugay kinahanglan ka maghulat .

Sa ulahi nahimo nako nga kopyahon ang sitwasyon: gilansad namo ang kliyente, i-off kini, i-recompile ang circuit sa lain nga layer, i-restart, kuhaa pag-usab ang problema, ibalik ang nauna - oops, wala’y kantidad sa pagbalhin sa circuit ug pag-restart sa kliyente alang sa usa ka pipila ka minuto makatabang. Makadawat ka usa ka pagsagol sa mga istruktura sa datos gikan sa lainlaing mga layer.

Katin-awan? Sama sa imong matag-an gikan sa lainlaing dili direkta nga mga sintomas, ang server naglangkob sa daghang mga proseso sa lainlaing mga lahi sa lainlaing mga makina. Lagmit, ang server nga responsable sa "buffering" nagbutang sa pila kung unsa ang gihatag sa mga superyor niini, ug gihatag nila kini sa laraw nga naa sa lugar sa panahon sa henerasyon. Ug hangtod nga kini nga pila "dunot", wala’y mahimo bahin niini.

Tingali... apan kini usa ka makalilisang nga saklay?!.. Dili, sa wala pa maghunahuna bahin sa buang nga mga ideya, atong tan-awon ang code sa opisyal nga mga kliyente. Sa bersyon sa Android wala kami makit-an nga bisan unsang TL parser, apan nakit-an namon ang usa ka mabug-at nga file (GitHub nagdumili sa paghikap niini) nga adunay (de)serialization. Ania ang mga snippet sa code:

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;

o

    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");

Hmm... murag wild. Apan, lagmit, kini namugna code, unya okay?.. Apan kini sa pagkatinuod nagsuporta sa tanan nga mga bersyon! Tinuod, dili klaro kung ngano nga ang tanan gisagol, sekreto nga mga chat, ug tanan nga matang sa _old7 sa usa ka paagi dili tan-awon sama sa makina nga henerasyon ... Apan, labaw sa tanan ako gihuyop sa

TL_message_layer104
TL_message_layer104_2
TL_message_layer104_3

Guys, dili ka ba makadesisyon kung unsa ang sulod sa usa ka layer?! Aw, okay, ingnon ta nga "duha" gibuhian nga adunay usa ka sayup, maayo, kini mahitabo, apan TULO?.. Diha-diha dayon, ang samang rake na usab? Unsa kini nga matang sa pornograpiya, pasensya?..

Sa source code sa Telegram Desktop, sa laing bahin, usa ka susama nga butang ang mahitabo - kung mao, daghang mga commit sa usa ka laray sa laraw wala magbag-o sa numero sa layer niini, apan ayohon ang usa ka butang. Sa mga kondisyon diin walay opisyal nga tinubdan sa datos alang sa laraw, diin kini makuha, gawas sa source code sa opisyal nga kliyente? Ug kung kuhaon nimo kini gikan didto, dili ka makasiguro nga ang laraw hingpit nga husto hangtod nga imong sulayan ang tanan nga mga pamaagi.

Sa unsang paagi kini masulayan? Nanghinaut ko nga ang mga fans sa unit, functional ug uban pang mga pagsulay mopaambit sa mga komento.

Okay, tan-awon nato ang laing piraso sa code:

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;

Kini nga komentaryo nga "manual nga gibuhat" nagsugyot nga bahin ra sa kini nga file ang gisulat nga mano-mano (mahunahuna ba nimo ang tibuuk nga damgo sa pagmentinar?), Ug ang nahabilin gihimo sa makina. Apan, unya mitungha ang laing pangutana - nga ang mga tinubdan anaa dili hingpit (a la GPL blobs sa Linux kernel), apan kini usa na ka hilisgutan alang sa ikaduhang bahin.

Apan igo na. Mopadayon kita ngadto sa protocol sa ibabaw diin ang tanan niini nga serialization midagan.

MT Proto

So, abli ta kinatibuk-ang paghulagway и detalyado nga paghulagway sa protocol ug ang unang butang nga atong mapandol mao ang terminolohiya. Ug sa kadagaya sa tanan. Sa kinatibuk-an, kini daw usa ka proprietary nga bahin sa Telegram - pagtawag sa mga butang nga lahi sa lainlaing mga lugar, o lainlaing mga butang sa usa ka pulong, o vice versa (pananglitan, sa usa ka taas nga lebel nga API, kung makakita ka usa ka sticker pack, dili kini unsay imong gihunahuna).

Pananglitan, ang "mensahe" ug "sesyon" nagpasabut nga lahi dinhi kaysa sa naandan nga interface sa kliyente sa Telegram. Aw, ang tanan klaro sa mensahe, mahimo kini mahubad sa mga termino sa OOP, o yano nga gitawag nga pulong nga "packet" - kini usa ka ubos, lebel sa transportasyon, wala’y parehas nga mga mensahe sama sa interface, adunay daghang mga mensahe sa serbisyo. . Apan ang sesyon ... apan una sa tanan.

layer sa transportasyon

Ang nag-unang butang mao ang transportasyon. Isulti nila kanamo ang bahin sa 5 nga kapilian:

  • TCP
  • Websocket
  • Websocket sa HTTPS
  • http
  • https

Vasily, [15.06.18 15:04] Adunay usab transportasyon sa UDP, apan wala kini dokumentado

Ug ang TCP sa tulo ka mga variant

Ang una susama sa UDP sa TCP, ang matag pakete naglakip sa sequence number ug crc
Ngano nga sakit kaayo ang pagbasa sa mga dokumento sa cart?

Aw, naa na karon Ang TCP naa na sa 4 nga mga variant:

  • Gipamub-an
  • Intermediate
  • Padded intermediate
  • Full

Aw, ok, Padded intermediate alang sa MTProxy, kini sa ulahi gidugang tungod sa iladong mga panghitabo. Apan nganong duha pa ka bersyon (tulo sa kinatibuk-an) kung mahimo nimo ang usa? Ang tanan nga upat lahi ra kung giunsa ang pagtakda sa gitas-on ug kargamento sa nag-unang MTProto, nga hisgutan pa:

  • sa Abridged kini 1 o 4 bytes, apan dili 0xef, unya ang lawas
  • sa Intermediate kini mao ang 4 bytes sa gitas-on ug usa ka uma, ug sa unang higayon nga ang kliyente kinahanglan ipadala 0xeeeeeeee aron ipakita nga kini Intermediate
  • sa bug-os ang labing makaadik, gikan sa punto sa panglantaw sa usa ka networker: gitas-on, sunod-sunod nga numero, ug DILI ANG USA nga nag-una MTProto, lawas, CRC32. Oo, kining tanan anaa sa ibabaw sa TCP. Nga naghatag kanamo ug kasaligan nga transportasyon sa porma sa usa ka sunud-sunod nga byte stream; wala’y kinahanglan nga mga han-ay, labi na ang mga checksum. Okay, karon adunay mosupak kanako nga ang TCP adunay 16-bit checksum, mao nga mahitabo ang pagkadunot sa datos. Maayo, apan kami adunay usa ka cryptographic protocol nga adunay mga hash nga mas taas sa 16 bytes, kining tanan nga mga kasaypanan - ug labaw pa - madakpan sa usa ka SHA mismatch sa mas taas nga lebel. WALAY punto sa CRC32 sa ibabaw niini.

Atong itandi ang Abridged, diin ang usa ka byte nga gitas-on posible, uban sa Intermediate, nga nagpakamatarong "Kung gikinahanglan ang 4-byte nga pag-align sa datos," nga wala'y pulos. Unsa, gituohan nga ang mga programmer sa Telegram dili kaayo makahimo nga dili sila makabasa sa datos gikan sa usa ka socket ngadto sa usa ka aligned buffer? Kinahanglan nimo nga buhaton kini, tungod kay ang pagbasa makabalik kanimo bisan unsang gidaghanon sa mga byte (ug adunay mga proxy server usab, pananglitan ...). O sa laing bahin, nganong i-block ang Abridged kung aduna pa kitay daghang padding sa ibabaw sa 16 bytes - save 3 bytes paghigugma ?

Ang usa nakakuha sa impresyon nga si Nikolai Durov ganahan kaayo nga mag-reinvent sa mga ligid, lakip ang mga protocol sa network, nga walay bisan unsang tinuod nga praktikal nga panginahanglan.

Ang ubang mga kapilian sa transportasyon, lakip. Web ug MTProxy, dili na nato hisgotan karon, basin sa laing post, kung naay hangyo. Mahitungod niining parehas nga MTProxy, hinumdoman lang nato karon nga wala madugay pagkahuman sa pagpagawas niini sa 2018, ang mga provider dali nga nakakat-on sa pagbabag niini, gituyo alang sa bypass blocking, sa gidak-on sa pakete! Ug usab ang kamatuoran nga ang server sa MTProxy nga gisulat (pag-usab ni Waltman) sa C sobra nga nahigot sa mga detalye sa Linux, bisan kung wala kini kinahanglana (gikumpirma ni Phil Kulin), ug nga ang usa ka parehas nga server sa Go o Node.js mahimo mohaum sa ubos sa usa ka gatos ka linya.

Apan maghimo kami mga konklusyon bahin sa teknikal nga literasiya sa kini nga mga tawo sa katapusan sa seksyon, pagkahuman sa pagkonsiderar sa ubang mga isyu. Sa pagkakaron, magpadayon kita sa OSI layer 5, session - diin ilang gibutang ang MTProto session.

Mga yawe, mensahe, sesyon, Diffie-Hellman

Gibutang nila kini didto nga dili hingpit nga husto ... Ang usa ka sesyon dili parehas nga sesyon nga makita sa interface sa ilawom sa mga Aktibo nga sesyon. Apan sa pagkasunodsunod.

Pagsaway sa protocol ug organisasyonal nga pamaagi sa Telegram. Bahin 1, teknikal: kasinatian sa pagsulat sa usa ka kliyente gikan sa wala - TL, MT

Mao nga nakadawat kami usa ka byte string nga nahibal-an ang gitas-on gikan sa layer sa transportasyon. Kini usa ka naka-encrypt nga mensahe o plaintext - kung naa pa kita sa yawe nga yugto sa kasabutan ug aktuwal nga nagbuhat niini. Asa sa pundok sa mga konsepto nga gitawag og "key" ang atong gihisgutan? Atong klaruhon kini nga isyu alang sa Telegram team mismo (Ako nangayo og pasaylo sa paghubad sa akong kaugalingon nga dokumentasyon gikan sa English nga adunay gikapoy nga utok sa alas-4 sa buntag, mas sayon ​​​​ang pagbilin sa pipila ka mga hugpong sa mga pulong nga ingon niini):

Adunay duha ka entidad nga gitawag sesyon - usa sa UI sa mga opisyal nga kliyente ubos sa "kasamtangan nga mga sesyon", diin ang matag sesyon katumbas sa usa ka tibuuk nga aparato / OS.
Ikaduha - Sesyon sa MTProto, nga adunay sequence number sa mensahe (sa ubos nga lebel nga diwa) niini, ug diin mahimong molungtad tali sa lain-laing mga koneksyon sa TCP. Daghang mga sesyon sa MTProto mahimong ma-install sa parehas nga oras, pananglitan, aron mapadali ang pag-download sa file.

Taliwala niining duha sesyon adunay usa ka konsepto pagtugot. Sa degenerate nga kaso, makaingon kita niana Sesyon sa UI mao ang sama sa pagtugot, pero alaut, ang tanan komplikado. Atong tan-awon:

  • Ang user sa bag-ong device unang makamugna auth_key ug i-bound kini sa account, pananglitan pinaagi sa SMS - mao kana ang hinungdan pagtugot
  • Nahitabo kini sa sulod sa una Sesyon sa MTProto, nga adunay session_id sulod sa imong kaugalingon.
  • Niini nga lakang, ang kombinasyon pagtugot и session_id matawagan awtoridad - kini nga pulong makita sa dokumentasyon ug code sa pipila ka mga kliyente
  • Unya, ang kliyente makaabli daghan Mga sesyon sa MTProto ubos sa samang auth_key - sa parehas nga DC.
  • Unya, usa ka adlaw ang kliyente kinahanglan nga mohangyo sa file gikan sa laing DC - ug alang niini nga DC usa ka bag-o ang mabuhat auth_key !
  • Aron ipahibalo sa sistema nga dili bag-ong tiggamit ang nagparehistro, apan parehas pagtugot (Sesyon sa UI), ang kliyente naggamit sa mga tawag sa API auth.exportAuthorization sa balay DC auth.importAuthorization sa bag-ong DC.
  • Ang tanan parehas ra, daghang mahimong bukas Mga sesyon sa MTProto (ang matag usa adunay iyang kaugalingon session_id) niining bag-ong DC, ubos sa iyang auth_key.
  • Sa katapusan, ang kliyente mahimo’g gusto ang Perfect Forward Secrecy. Matag auth_key maoy Permanente yawe - kada DC - ug ang kliyente makatawag auth.bindTempAuthKey para gamiton temporaryo auth_key - ug usab, usa ra temp_auth_key kada DC, komon sa tanan Mga sesyon sa MTProto niini nga DC.

pahibalo, kana asin (ug umaabot nga mga asin) usa usab sa auth_key mga. gipaambit sa tanan Mga sesyon sa MTProto sa parehas nga DC.

Unsa ang gipasabut sa "tali sa lainlaing mga koneksyon sa TCP"? Busa kini nagpasabot usa ka butang sama sa cookie sa pagtugot sa usa ka website - nagpadayon kini (nabuhi) daghang mga koneksyon sa TCP sa usa ka gihatag nga server, apan usa ka adlaw kini madaot. Dili sama sa HTTP, sa MTProto nga mga mensahe sa sulod sa usa ka sesyon ang sunud-sunod nga numero ug gikumpirma; kung sila mosulod sa tunel, ang koneksyon nabuak - pagkahuman sa pag-establisar sa usa ka bag-ong koneksyon, ang server maluloton nga ipadala ang tanan sa kini nga sesyon nga wala kini gihatag sa miaging Koneksyon sa TCP.

Bisan pa, ang kasayuran sa ibabaw gi-summarize pagkahuman sa daghang mga bulan nga imbestigasyon. Sa kasamtangan, gipatuman ba nato ang atong kliyente gikan sa wala? - balik ta sa sinugdanan.

Busa mag-generate ta auth_key sa Mga bersyon sa Diffie-Hellman gikan sa Telegram. Atong sulayan nga masabtan ang dokumentasyon ...

Vasily, [19.06.18 20:05] data_with_hash := SHA1(data) + data + (bisan unsang random bytes); sa ingon nga ang gitas-on katumbas sa 255 bytes;
encrypted_data := RSA(data_with_hash, server_public_key); usa ka 255-byte nga taas nga numero (dako nga endian) gipataas sa gikinahanglan nga gahum sa gikinahanglan nga modulus, ug ang resulta gitipigan ingon nga usa ka 256-byte nga numero.

Naa silay dope nga DH

Dili daw DH sa usa ka himsog nga tawo
Walay duha ka publikong yawe sa dx

Aw, sa katapusan kini gihusay, apan ang nahabilin nagpabilin - pamatuod sa trabaho nga gihimo sa kliyente nga siya nakahimo sa hinungdan sa numero. Matang sa panalipod batok sa mga pag-atake sa DoS. Ug ang RSA nga yawe gigamit ra kausa sa usa ka direksyon, hinungdanon alang sa pag-encrypt new_nonce. Apan samtang kining morag yanong operasyon molampos, unsay imong kinahanglang atubangon?

Vasily, [20.06.18/00/26 XNUMX:XNUMX] Wala pa ko nakaabot sa appid request

Gipadala nako kini nga hangyo sa DH

Ug, sa transport dock kini nag-ingon nga kini makatubag sa 4 bytes sa usa ka error code. Mao ra

Aw, giingnan ko niya -404, unsa man?

Mao nga giingnan nako siya: "Dakpa ang imong kabuang nga naka-encrypt gamit ang usa ka yawe sa server nga adunay fingerprint nga sama niini, gusto ko ang DH," ug kini mitubag sa usa ka buang nga 404

Unsa ang imong hunahuna sa tubag sa server? Unsay buhaton? Walay usa nga mangutana (apan labaw pa niana sa ikaduhang bahin).

Dinhi ang tanan nga interes gihimo sa pantalan

Wala koy laing buhaton, nagdamgo lang ko nga mag-convert og mga numero balik-balik

Duha ka 32 bit nga numero. Giputos ko sila sama sa uban

Apan dili, kining duha kinahanglan nga idugang una sa linya isip BE

Vadim Goncharov, [20.06.18 15:49] ug tungod niini 404?

Vasily, [20.06.18 15:49] OO!

Vadim Goncharov, [20.06.18 15:50] mao nga dili nako masabtan kung unsa ang iyang "wala makit-an"

Vasily, [20.06.18 15:50] gibana-bana

Dili nako makit-an ang ingon nga pagkadunot sa panguna nga mga hinungdan%)

Wala gani mi nagdumala sa pagreport sa sayop

Vasily, [20.06.18 20:18] Oh, aduna usab MD5. Naa nay tulo ka lainlaing hash

Ang yawe nga fingerprint gikalkula sama sa mosunod:

digest = md5(key + iv)
fingerprint = substr(digest, 0, 4) XOR substr(digest, 4, 4)

SHA1 ug sha2

Busa atong ibutang kini auth_key nakadawat kami og 2048 bits sa gidak-on gamit ang Diffie-Hellman. Unsay sunod? Sunod atong nadiskobrehan nga ang ubos nga 1024 bits niini nga yawe wala gigamit sa bisan unsa nga paagi ... apan atong hunahunaon kini sa pagkakaron. Niini nga lakang, kami adunay gipaambit nga sekreto sa server. Ang usa ka analogue sa sesyon sa TLS natukod, nga usa ka mahal kaayo nga pamaagi. Apan ang server wala gihapon nahibal-an kung kinsa kami! Dili pa, sa tinuod. pagtugot. Mga. kung naghunahuna ka sa termino sa "login-password", sama sa imong gibuhat kaniadto sa ICQ, o labing menos "login-key", sama sa SSH (pananglitan, sa pipila ka gitlab / github). Nakadawat mi og anonymous. Unsa kaha kung gisultihan kami sa server nga "kini nga mga numero sa telepono giserbisyuhan sa laing DC"? O bisan ang "imong numero sa telepono gidili"? Ang labing maayo nga atong mahimo mao ang pagtipig sa yawe sa paglaum nga kini mapuslanon ug dili madunot unya.

Pinaagi sa dalan, kami "nakadawat" niini uban ang mga reserbasyon. Pananglitan, misalig ba kita sa server? Unsa kaha kung peke? Ang mga pagsusi sa cryptographic kinahanglan:

Vasily, [21.06.18 17:53] Nagtanyag sila sa mga kliyente sa mobile nga susihon ang usa ka 2kbit nga numero alang sa panguna%)

Apan dili kini klaro, nafeijoa

Vasily, [21.06.18 18:02] Ang dokumento wala magsulti kung unsa ang buhaton kung kini nahimo nga dili yano

Wala giingon. Atong tan-awon kung unsa ang gihimo sa opisyal nga kliyente sa Android sa kini nga kaso? A mao na (ug oo, ang tibuok nga file makapaikag) - sama sa ilang giingon, ibilin ko kini dinhi:

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

Dili, siyempre naa gihapon pipila Adunay mga pagsulay alang sa primality sa usa ka numero, apan sa personal wala na akoy igong kahibalo sa matematika.

Okay, nakuha namo ang master key. Aron maka-log in, i.e. ipadala ang mga hangyo, kinahanglan nimo nga himuon ang dugang nga pag-encrypt, gamit ang AES.

Ang yawe sa mensahe gihubit ingon ang 128 ka tunga nga mga bit sa SHA256 sa lawas sa mensahe (lakip ang sesyon, ID sa mensahe, ug uban pa), lakip ang mga padding byte, nga giandam sa 32 ka byte nga gikuha gikan sa yawe sa pagtugot.

Vasily, [22.06.18 14:08] Average, bitch, gamay

Nakadawat auth_key. Tanan. Sa unahan nila... dili klaro sa dokumento. Mobati nga gawasnon sa pagtuon sa open source code.

Timan-i nga ang MTProto 2.0 nanginahanglan gikan sa 12 hangtod 1024 bytes sa padding, sa gihapon ubos sa kondisyon nga ang resulta nga gitas-on sa mensahe mahimong bahinon sa 16 bytes.

Busa pila ka padding ang imong idugang?

Ug oo, adunay usab usa ka 404 kung adunay sayup

Kung adunay mabinantayon nga nagtuon sa diagram ug teksto sa dokumentasyon, namatikdan nila nga wala’y MAC didto. Ug kana nga AES gigamit sa usa ka mode nga IGE nga wala gigamit bisan diin. Sila, siyempre, nagsulat mahitungod niini sa ilang FAQ ... Dinhi, sama, ang yawe sa mensahe mismo mao usab ang SHA hash sa decrypted data, nga gigamit sa pagsusi sa integridad - ug sa kaso sa usa ka mismatch, ang dokumentasyon alang sa pipila ka rason nagrekomendar sa hilom nga dili pagtagad kanila (apan unsa ang mahitungod sa seguridad, unsa man kon sila makaguba kanato?).

Dili ako usa ka cryptographer, tingali wala’y sayup sa kini nga mode sa kini nga kaso gikan sa usa ka teoretikal nga punto sa pagtan-aw. Apan klaro nakong mahatag ang usa ka praktikal nga problema, gamit ang Telegram Desktop isip usa ka pananglitan. Gi-encrypt niini ang lokal nga cache (tanan kini nga D877F783D5D3EF8C) sa parehas nga paagi sa mga mensahe sa MTProto (sa kini nga kaso nga bersyon 1.0), i.e. una ang yawe sa mensahe, dayon ang datos mismo (ug bisan diin gawas sa panguna nga dako auth_key 256 bytes, nga wala msg_key walay pulos). Busa, ang problema mahimong mamatikdan sa dagkong mga file. Sa ato pa, kinahanglan nimo nga tipigan ang duha ka kopya sa datos - gi-encrypt ug gi-decrypted. Ug kung adunay mga megabytes, o streaming nga video, pananglitan?.. Ang mga klasiko nga laraw nga adunay MAC pagkahuman sa ciphertext nagtugot kanimo sa pagbasa niini nga stream, dayon nga ipadala kini. Apan sa MTProto kinahanglan nimo sa una i-encrypt o i-decrypt ang tibuok nga mensahe, dayon ibalhin kini sa network o sa disk. Busa, sa pinakabag-o nga bersyon sa Telegram Desktop sa cache sa user_data Laing format ang gigamit usab - nga adunay AES sa CTR mode.

Vasily, [21.06.18 01:27] Oh, nahibal-an nako kung unsa ang IGE: Ang IGE mao ang una nga pagsulay sa usa ka "mode sa pag-encrypt sa pag-authenticate," nga orihinal alang sa Kerberos. Kini usa ka napakyas nga pagsulay (wala kini maghatag proteksyon sa integridad), ug kinahanglan nga tangtangon. Kana ang sinugdanan sa usa ka 20 ka tuig nga pagpangita alang sa usa ka authenticating encryption mode nga molihok, nga bag-o lang natapos sa mga mode sama sa OCB ug GCM.

Ug karon ang mga argumento gikan sa kilid sa kariton:

Ang team luyo sa Telegram, nga gipangulohan ni Nikolai Durov, naglangkob sa unom ka ACM champions, katunga niini Ph.Ds sa math. Nagkinahanglan sila og mga duha ka tuig aron ilusad ang kasamtangan nga bersyon sa MTProto.

Kataw-anan. Duha ka tuig sa ubos nga lebel

O mahimo nimong kuhaon ang tls

Okay, ingnon ta nga nahimo na namon ang pag-encrypt ug uban pang mga nuances. Posible ba nga ipadala ang mga hangyo nga serialized sa TL ug deserialize ang mga tubag? Busa unsa ug unsaon nimo ipadala? Dinhi, ingnon ta, ang pamaagi initConnection, basin mao ni?

Vasily, [25.06.18 18:46] Nagsugod sa koneksyon ug nagtipig og impormasyon sa device ug aplikasyon sa user.

Gidawat niini ang app_id, device_model, system_version, app_version ug lang_code.

Ug pipila ka pangutana

Dokumentasyon sama sa kanunay. Mobati nga gawasnon sa pagtuon sa open source

Kung ang tanan halos klaro sa invokeWithLayer, nan unsa ang sayup dinhi? Mogawas, ingnon ta nga naa - ang kliyente adunay usa ka butang nga ipangutana sa server - adunay usa ka hangyo nga gusto namon ipadala:

Vasily, [25.06.18 19:13] Paghukom pinaagi sa code, ang unang tawag giputos niini nga crap, ug ang crap sa iyang kaugalingon giputos sa invokewithlayer

Ngano nga ang initConnection dili mahimo nga usa ka bulag nga tawag, apan kinahanglan usa ka wrapper? Oo, ingon nga kini nahimo, kinahanglan kini buhaton matag higayon sa pagsugod sa matag sesyon, ug dili kausa, sama sa panguna nga yawe. Apan! Dili kini matawag sa dili awtorisado nga tiggamit! Karon nakaabot na kami sa yugto diin kini magamit Kini usa panid sa dokumentasyon - ug kini nagsulti kanato nga...

Gamay ra nga bahin sa mga pamaagi sa API ang magamit sa dili awtorisado nga mga tiggamit:

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

Ang labing una kanila, auth.sendCode, ug adunay gimahal nga una nga hangyo diin kami nagpadala sa api_id ug api_hash, ug pagkahuman makadawat kami usa ka SMS nga adunay code. Ug kung naa kita sa sayup nga DC (ang mga numero sa telepono sa kini nga nasud gisilbihan sa lain, pananglitan), nan makadawat kita usa ka sayup sa numero sa gusto nga DC. Aron mahibal-an kung unsang IP address pinaagi sa numero sa DC ang kinahanglan nimo nga makonektar, tabangi kami help.getConfig. Sa usa ka higayon adunay 5 ra nga mga entries, apan pagkahuman sa bantog nga mga panghitabo sa 2018, ang gidaghanon miuswag pag-ayo.

Karon atong hinumdoman nga nakaabot kita niini nga yugto sa server nga dili mailhan. Dili ba mahal kaayo ang pagkuha lang og IP address? Ngano nga dili kini buhaton, ug uban pang mga operasyon, sa wala ma-encrypt nga bahin sa MTProto? Nadungog nako ang pagsupak: "unsaon naton masiguro nga dili RKN ang motubag sa dili tinuod nga mga adres?" Niini atong nahinumduman nga, sa kinatibuk-an, opisyal nga mga kliyente Ang mga yawe sa RSA gilakip, i.e. pwede lang aron mopirma kini nga impormasyon. Sa tinuud, gihimo na kini alang sa kasayuran sa pag-bypass sa pag-block nga madawat sa mga kliyente pinaagi sa ubang mga kanal (lohikal, dili kini mahimo sa MTProto mismo; kinahanglan usab nimo mahibal-an kung asa magkonektar).

OK ra. Niini nga yugto sa pagtugot sa kliyente, wala pa kami awtorisado ug wala marehistro ang among aplikasyon. Gusto lang namon nga makita sa karon kung unsa ang tubag sa server sa mga pamaagi nga magamit sa usa ka dili awtorisado nga tiggamit. Ug dinhi…

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;

Sa laraw, una ang ikaduha

Sa tdesktop schema ang ikatulo nga kantidad mao ang

Oo, sukad niadto, siyempre, ang dokumentasyon gi-update. Bisan tuod kini sa dili madugay mahimo nga walay kalabutan pag-usab. Giunsa mahibal-an sa usa ka bag-ong developer? Basin kung magparehistro ka sa imong aplikasyon, ipahibalo ka nila? Gibuhat kini ni Vasily, apan alaut, wala sila nagpadala kaniya bisan unsa (pag-usab, atong hisgutan kini sa ikaduhang bahin).

...Namatikdan nimo nga sa usa ka paagi mibalhin na kami sa API, i.e. ngadto sa sunod nga ang-ang, ug nasipyat sa usa ka butang sa MTProto nga hilisgutan? Dili ikatingala:

Vasily, [28.06.18 02:04] Mm, gisusi nila ang pipila ka mga algorithm sa e2e

Gihubit sa Mtproto ang mga algorithm sa pag-encrypt ug mga yawe alang sa duha ka domain, ingon man usa ka gamay nga istruktura sa wrapper.

Apan kanunay nilang gisagol ang lainlaing lebel sa stack, mao nga dili kanunay klaro kung diin natapos ang mtproto ug nagsugod ang sunod nga lebel

Giunsa nila pagsagol? Aw, ania ang parehas nga temporaryo nga yawe alang sa PFS, pananglitan (sa paagi, ang Telegram Desktop dili makahimo niini). Gipatuman kini pinaagi sa usa ka hangyo sa API auth.bindTempAuthKey, i.e. gikan sa taas nga lebel. Apan sa samang higayon kini makabalda sa pag-encrypt sa ubos nga lebel - human niini, pananglitan, kinahanglan nimo nga buhaton kini pag-usab initConnection ug uban pa, dili kini makatarunganon normal nga hangyo. Ang espesyal usab mao nga mahimo ka adunay usa ra ka temporaryo nga yawe matag DC, bisan kung ang uma auth_key_id sa matag mensahe nagtugot kanimo sa pag-usab sa yawe sa labing menos sa matag mensahe, ug nga ang server adunay katungod sa "pagkalimot" sa temporaryo nga yawe sa bisan unsa nga panahon - ang dokumentasyon wala mag-ingon kon unsa ang buhaton niini nga kaso... maayo, nganong mahimo Dili ka ba adunay daghang mga yawe, sama sa usa ka set sa umaabot nga mga asin, ug ?..

Adunay pipila ka mga butang nga angay hinumdoman bahin sa tema sa MTProto.

Mga mensahe sa mensahe, msg_id, msg_seqno, kumpirmasyon, ping sa sayop nga direksyon ug uban pang mga idiosyncrasie

Nganong kinahanglang mahibalo ka bahin kanila? Tungod kay sila "nag-leak" sa mas taas nga lebel, ug kinahanglan nimo nga mahibal-an sila kung nagtrabaho kauban ang API. Ibutang nato nga dili kita interesado sa msg_key; ang ubos nga lebel nag-decrypted sa tanan alang kanato. Apan sa sulod sa na-decrypted nga datos aduna kitay mosunod nga mga field (usab ang gitas-on sa datos, aron mahibal-an nato kung asa ang padding, apan dili kana importante):

  • asin - int64
  • session_id - int64
  • message_id — int64
  • seq_no - int32

Atong pahinumduman nga adunay usa lamang ka asin alang sa tibuok DC. Nganong nakahibalo bahin niya? Dili lang kay naay hangyo get_future_salts, nga nagsulti kanimo kung unsang mga agwat ang mahimong balido, apan tungod usab kung ang imong asin "dunot", nan ang mensahe (hangyo) mawala ra. Ang server, siyempre, magreport sa bag-ong asin pinaagi sa pag-isyu new_session_created - apan sa daan kinahanglan nimo kini ipadala pag-usab, pananglitan. Ug kini nga isyu makaapekto sa arkitektura sa aplikasyon.

Gitugotan ang server nga ihulog ang tanan nga mga sesyon ug tubagon kini nga paagi sa daghang mga hinungdan. Sa tinuud, unsa ang sesyon sa MTProto gikan sa bahin sa kliyente? Duha kini ka numero session_id и seq_no mga mensahe sulod niini nga sesyon. Aw, ug ang nagpahiping koneksyon sa TCP, siyempre. Ingnon ta nga ang among kliyente wala pa mahibal-an kung unsaon pagbuhat sa daghang mga butang, iyang gidiskonekta ug gibalik ang koneksyon. Kung kini nahitabo dayon - ang daan nga sesyon nagpadayon sa bag-ong koneksyon sa TCP, pagdugang seq_no dugang pa. Kung magdugay, mahimo kini ma-delete sa server, tungod kay sa kilid niini usa usab kini ka pila, ingon sa among nahibal-an.

Unsa man kini seq_no? Oh, kana usa ka lisud nga pangutana. Sulayi nga matinud-anon nga masabtan kung unsa ang gipasabut:

Mensahe nga may kalabotan sa sulud

Usa ka mensahe nga nanginahanglan usa ka klaro nga pag-ila. Naglakip kini sa tanan nga tiggamit ug daghang mga mensahe sa serbisyo, halos tanan gawas sa mga sudlanan ug mga pag-ila.

Numero sa Pagkasunod-sunod sa Mensahe (msg_seqno)

Usa ka 32-bit nga numero nga katumbas sa doble ang gidaghanon sa mga mensahe nga "may kalabotan sa sulud" (kadtong nanginahanglan pag-ila, ug labi na kadtong dili mga sulud) nga gihimo sa nagpadala sa wala pa kini nga mensahe ug pagkahuman gidugangan sa usa kung ang karon nga mensahe usa ka mensahe nga may kalabotan sa sulod. Ang usa ka sudlanan kanunay nga gihimo pagkahuman sa tibuuk nga sulud niini; busa, ang han-ay nga numero niini mas dako o katumbas sa han-ay nga mga numero sa mga mensahe nga anaa niini.

Unsang klaseha sa sirkos kini nga adunay pagtaas sa 1, ug dayon usa pa sa 2?.. Nagduda ko nga sa sinugdan gipasabut nila ang "labing gamay nga hinungdanon alang sa ACK, ang nahabilin usa ka numero", apan ang sangputanan dili parehas - sa partikular, kini mogawas, mahimong ipadala daghan mga kumpirmasyon nga adunay parehas seq_no! Giunsa? Aw, pananglitan, ang server nagpadala kanamo og usa ka butang, gipadala kini, ug kami mismo nagpakahilom, nagtubag lamang sa mga mensahe sa serbisyo nga nagpamatuod sa pagkadawat sa mga mensahe niini. Sa kini nga kaso, ang among mga outgoing confirmations adunay parehas nga outgoing nga numero. Kung pamilyar ka sa TCP ug naghunahuna nga kini ingon og ihalas, apan ingon og dili kaayo ihalas, tungod kay sa TCP seq_no dili mausab, apan ang kumpirmasyon moadto sa seq_no sa pikas bahin, ako magdali sa pagsamok kanimo. Ang mga kumpirmasyon gihatag sa MTProto DILI sa seq_no, sama sa TCP, apan pinaagi sa msg_id !

Unsa man ni msg_id, ang labing importante niini nga mga natad? Usa ka talagsaon nga pag-ila sa mensahe, ingon sa gisugyot sa ngalan. Gihubit kini ingon usa ka 64-bit nga numero, ang labing ubos nga mga piraso diin adunay usab "server-not-server" nga salamangka, ug ang nahabilin usa ka timestamp sa Unix, lakip ang fractional nga bahin, gibalhin ang 32 bits sa wala. Mga. timestamp per se (ug ang mga mensahe nga adunay mga oras nga lahi kaayo ang isalikway sa server). Gikan niini nahimo nga sa kinatibuk-an kini usa ka identifier nga global alang sa kliyente. Gihatag kana - atong hinumdoman session_id - kami gigarantiyahan: Sa bisan unsa nga kahimtang nga ang usa ka mensahe alang sa usa ka sesyon ipadala sa lain nga sesyon. Sa ato pa, naa na diay tulo lebel - sesyon, numero sa sesyon, id sa mensahe. Ngano nga ang sobra nga komplikasyon, kini nga misteryo dako kaayo.

Ug busa, msg_id gikinahanglan para...

RPC: hangyo, tubag, sayop. Mga kumpirmasyon.

Sama sa imong namatikdan, walay espesyal nga "paghangyo sa RPC" nga tipo o function bisan asa sa diagram, bisan kung adunay mga tubag. Human sa tanan, kami adunay mga mensahe nga may kalabotan sa sulud! Sa ato pa, bisan unsa ang mensahe mahimong usa ka hangyo! O dili mahimong. Human sa tanan, matag usa mao msg_id. Apan adunay mga tubag:

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

Dinhi diin gipakita kung unsang mensahe kini nga tubag. Busa, sa pinakataas nga lebel sa API, kinahanglan nimong hinumdoman kung unsa ang gidaghanon sa imong hangyo - Sa akong hunahuna dili kinahanglan nga ipasabut nga ang trabaho kay asynchronous, ug adunay daghang mga hangyo nga nagpadayon sa parehas nga oras, ang mga tubag nga mahimong ibalik sa bisan unsang pagkahan-ay? Sa prinsipyo, gikan niini ug mga mensahe sa sayop sama sa walay mga trabahante, ang arkitektura sa luyo niini masubay: ang server nga nagmintinar sa koneksyon sa TCP uban kanimo usa ka front-end balancer, kini nagpasa sa mga hangyo ngadto sa mga backend ug gikolekta kini balik pinaagi sa message_id. Morag klaro, lohikal ug maayo ang tanan dinhi.

Oo?.. Ug kung imong hunahunaon kini? Pagkahuman, ang tubag sa RPC mismo adunay usa usab ka uma msg_id! Kinahanglan ba natong isinggit ang server nga "wala nimo tubaga ang akong tubag!"? Ug oo, unsa may bahin sa mga pagkumpirma? Mahitungod sa panid mga mensahe bahin sa mga mensahe nagsulti kanato kung unsa

msgs_ack#62d6b459 msg_ids:Vector long = MsgsAck;

ug kini kinahanglan buhaton sa matag kilid. Apan dili kanunay! Kung nakadawat ka ug RpcResult, kini mismo nagsilbi nga kumpirmasyon. Kana mao, ang server makatubag sa imong hangyo gamit ang MsgsAck - sama sa, "Nadawat ko kini." Makatubag dayon ang RpcResult. Mahimong duha.

Ug oo, kinahanglan nimo nga tubagon ang tubag! Pagkumpirma. Kung dili, isipon sa server nga dili kini madala ug ipadala kini kanimo pag-usab. Bisan human sa pagkonektar pag-usab. Apan dinhi, siyempre, ang isyu sa mga timeout mitungha. Atong tan-awon sila sa ulahi.

Sa kasamtangan, atong tan-awon ang posibleng mga sayop sa pagpatuman sa pangutana.

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

Oh, adunay mosinggit, ania ang mas tawhanon nga pormat - adunay linya! Paggahin sa imong panahon. Dinhi listahan sa mga sayop, pero siyempre dili kompleto. Gikan niini atong nakat-unan nga ang code mao usa ka butang sama sa Ang mga kasaypanan sa HTTP (siyempre, ang mga semantiko sa mga tubag wala gitahud, sa pipila ka mga lugar sila giapod-apod nga random sa mga code), ug ang linya sama sa CAPITAL_LETTERS_AND_NUMBERS. Pananglitan, PHONE_NUMBER_OCCUPIED o FILE_PART_Х_MISSING. Bueno, kana, kinahanglan nimo kini nga linya parse. Pananglitan FLOOD_WAIT_3600 nagpasabut nga kinahanglan ka maghulat usa ka oras, ug PHONE_MIGRATE_5, nga ang numero sa telepono nga adunay kini nga prefix kinahanglan nga marehistro sa 5th DC. Naa tay type nga lengguwahe, di ba? Dili nato kinahanglan ang usa ka argumento gikan sa usa ka pisi, ang mga regular nga mahimo, okay.

Pag-usab, wala kini sa panid sa mga mensahe sa serbisyo, apan, sama sa naandan na niini nga proyekto, ang impormasyon makita sa laing panid sa dokumentasyon. O pagduda. Una, tan-awa, paglapas sa pag-type/layer - RpcError mahimong nested sa RpcResult. Nganong dili sa gawas? Unsa ang wala nato tagda?.. Sumala niana, asa ang garantiya nga RpcError mahimong DILI ma-embed sa RpcResult, apan direkta o nested sa laing matang?.. Ug kung kini dili mahimo, nganong dili kini sa ibabaw nga lebel, i.e. kini kulang req_msg_id ? ..

Apan magpadayon kita bahin sa mga mensahe sa serbisyo. Ang kliyente tingali maghunahuna nga ang server naghunahuna sa dugay nga panahon ug naghimo niining talagsaon nga hangyo:

rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;

Adunay tulo ka posible nga mga tubag niini nga pangutana, pag-usab interseksyon sa mekanismo sa pagkumpirma; naningkamot nga masabtan kung unsa sila kinahanglan (ug kung unsa ang kinatibuk-ang lista sa mga tipo nga wala magkinahanglan og kumpirmasyon) ibilin sa magbabasa ingon homework (timan-i: ang impormasyon sa ang Telegram Desktop source code dili kompleto).

Pagkaadik sa droga: mga status sa mensahe

Sa kinatibuk-an, daghang mga lugar sa TL, MTProto ug Telegram sa kinatibuk-an nagbilin usa ka pagbati sa pagkagahi sa ulo, apan tungod sa pagkamatinahuron, taktika ug uban pa hinay nga mga kahanas Matinahuron kami nga nagpakahilom bahin niini, ug gisensor ang mga malaw-ay nga mga diyalogo. Apan, kini nga dapitОkadaghanan sa panid mahitungod sa mga mensahe bahin sa mga mensahe Kini makapakurat bisan alang kanako, nga nagtrabaho uban ang mga protocol sa network sa dugay nga panahon ug nakakita sa mga bisikleta nga lainlain ang lebel sa pagkaliko.

Nagsugod kini nga dili makadaot, nga adunay mga pagkumpirma. Sunod ila kaming gisultihan

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;

Aw, ang tanan nga nagsugod sa pagtrabaho kauban ang MTProto kinahanglan nga mag-atubang niini; sa "gitul-id - gi-recompiled - gilunsad" nga siklo, ang pagkuha sa mga sayup sa numero o asin nga nakahimo nga dili maayo sa panahon sa mga pag-edit usa ka kasagaran nga butang. Apan, adunay duha ka punto dinhi:

  1. Kini nagpasabot nga ang orihinal nga mensahe nawala. Kinahanglan namon nga maghimo pila ka pila, tan-awon namon kana sa ulahi.
  2. Unsa kining talagsaon nga mga numero sa sayup? 16, 17, 18, 19, 20, 32, 33, 34, 35, 48, 64... asa ang ubang numero, Tommy?

Ang dokumentasyon nag-ingon:

Ang tuyo mao nga ang error_code values ​​​​gigrupo (error_code >> 4): pananglitan, ang mga code 0x40 — 0x4f katumbas sa mga sayop sa container decomposition.

apan, una, usa ka pagbalhin sa laing direksyon, ug ikaduha, dili igsapayan, asa ang ubang mga code? Sa ulo sa tagsulat?.. Apan, kini mao ang mga trifles.

Ang pagkaadik nagsugod sa mga mensahe bahin sa mga status sa mensahe ug mga kopya sa mensahe:

  • Paghangyo alang sa Impormasyon sa Status sa Mensahe
    Kung ang bisan hain nga partido wala makadawat og impormasyon sa status sa mga outgoing messages niini sa makadiyot, kini mahimong dayag nga mohangyo niini gikan sa laing partido:
    msgs_state_req#da69fb52 msg_ids:Vector long = MsgsStateReq;
  • Mensahe sa Impormasyon bahin sa Status sa mga Mensahe
    msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
    Dinhi, info usa ka hilo nga adunay eksaktong usa ka byte sa status sa mensahe alang sa matag mensahe gikan sa umaabot nga msg_ids list:

    • 1 = walay nahibal-an mahitungod sa mensahe (msg_id ubos kaayo, ang laing partido mahimong nakalimot niini)
    • 2 = mensahe nga wala madawat (msg_id naa sa sulod sa gitipigan nga mga identifier; bisan pa, ang pikas nga partido wala gyud makadawat usa ka mensahe nga ingon niana)
    • 3 = mensahe wala madawat (msg_id taas kaayo; bisan pa, ang laing partido wala pa makadawat niini)
    • 4 = mensahe nga nadawat (timan-i nga kini nga tubag sa samang higayon usa ka resibo nga pag-ila)
    • +8 = mensahe nga giila na
    • +16 = mensahe nga wala magkinahanglan og acknowledgement
    • +32 = RPC nga pangutana nga anaa sa mensahe nga giproseso o kompleto na ang pagproseso
    • +64 = tubag nga may kalabotan sa sulud sa mensahe nga nahimo na
    • +128 = ang ubang partido nahibalo sa tinuod nga ang mensahe nadawat na
      Kini nga tubag wala magkinahanglan og pag-ila. Kini usa ka pag-ila sa may kalabutan nga msgs_state_req, sa ug sa iyang kaugalingon.
      Timan-i nga kung kini kalit nga makita nga ang pikas nga partido wala’y mensahe nga morag gipadala kini, ang mensahe mahimo ra ipadala pag-usab. Bisan kung ang pikas nga partido makadawat og duha ka kopya sa mensahe sa samang higayon, ang duplicate dili tagdon. (Kung dugay na kaayo nga panahon ang milabay, ug ang orihinal nga msg_id dili na balido, ang mensahe kinahanglang iputos sa msg_copy).
  • Boluntaryong Komunikasyon sa Status sa mga Mensahe
    Ang bisan asa nga partido mahimong boluntaryong mopahibalo sa laing partido sa kahimtang sa mga mensahe nga gipasa sa pikas partido.
    msgs_all_info#8cc0d131 msg_ids:Vector long info:string = MsgsAllInfo
  • Gilugwayan nga Boluntaryong Komunikasyon sa Status sa Usa ka Mensahe
    ...
    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;
  • Tin-aw nga Paghangyo sa Pagpadala Pag-usab sa mga Mensahe
    msg_resend_req#7d861a08 msg_ids:Vector long = MsgResendReq;
    Ang hilit nga partido mitubag dayon pinaagi sa pagpadala pag-usab sa gihangyo nga mga mensahe […]
  • Tin-aw nga Paghangyo nga Ipadala Pag-usab ang mga Tubag
    msg_resend_ans_req#8610baeb msg_ids:Vector long = MsgResendReq;
    Ang hilit nga partido motubag dayon pinaagi sa pagpadala pag-usab mga tubag sa gihangyo nga mga mensahe […]
  • Mga Kopya sa Mensahe
    Sa pipila ka mga sitwasyon, usa ka daan nga mensahe nga adunay msg_id nga dili na balido kinahanglan ipadala pag-usab. Dayon, kini giputos sa usa ka kopya nga sudlanan:
    msg_copy#e06046b2 orig_message:Message = MessageCopy;
    Sa dihang nadawat, ang mensahe giproseso nga daw wala didto ang wrapper. Apan, kung nahibal-an nga ang mensahe nga orig_message.msg_id nadawat, nan ang bag-ong mensahe wala maproseso (samtang sa samang higayon, kini ug orig_message.msg_id giila). Ang bili sa orig_message.msg_id kinahanglang mas ubos kay sa msg_id sa sudlanan.

Maghilom lang ta sa unsa msgs_state_info pag-usab ang mga dalunggan sa wala pa mahuman nga TL migawas (nagkinahanglan kami og vector sa bytes, ug sa ubos nga duha ka bits adunay usa ka enum, ug sa mas taas nga duha ka bits adunay mga bandila). Lahi ang punto. Aduna bay nakasabot ngano nga kining tanan anaa sa praktis? sa tinuod nga kliyente gikinahanglan?.. Kini lisud, apan ang usa ka mahanduraw sa pipila ka kaayohan kon ang usa ka tawo moapil sa debugging, ug sa usa ka interactive nga paagi - pangutana sa server unsa ug sa unsa nga paagi. Apan dinhi gihulagway ang mga hangyo round trip.

Nagsunod kini nga ang matag partido kinahanglan dili lamang mag-encrypt ug magpadala mga mensahe, apan magtipig usab mga datos bahin sa ilang kaugalingon, bahin sa mga tubag sa kanila, sa wala mailhi nga oras. Ang dokumentasyon wala maghulagway sa mga timing o sa praktikal nga paggamit niini nga mga bahin. walay paagi. Ang labing katingad-an mao nga gigamit gyud sila sa code sa opisyal nga mga kliyente! Dayag nga gisultihan sila sa usa ka butang nga wala maapil sa dokumentasyon sa publiko. Sabta gikan sa code ngano, dili na ingon ka yano sama sa kaso sa TL - dili kini usa ka (medyo) lohikal nga nahilain nga bahin, apan usa ka piraso nga nahigot sa arkitektura sa aplikasyon, i.e. manginahanglan ug daghang oras aron masabtan ang code sa aplikasyon.

Mga ping ug timing. Mga pila.

Gikan sa tanan, kung nahinumduman namon ang mga panagna bahin sa arkitektura sa server (pag-apod-apod sa mga hangyo sa tibuuk nga mga backend), usa ka labi ka makapasubo nga butang ang nagsunod - bisan pa sa tanan nga mga garantiya sa pagpadala sa TCP (bisan ang datos gihatag, o ipahibalo ka bahin sa break, apan ang datos ihatud hangtod mahitabo ang problema), nga ang mga pagkumpirma sa MTProto mismo - walay garantiya. Ang server dali nga mawala o ilabay ang imong mensahe, ug wala’y mahimo bahin niini, gamita lang ang lainlaing mga lahi sa crutches.

Ug una sa tanan - mga pila sa mensahe. Aw, sa usa ka butang ang tanan klaro gikan sa sinugdanan - ang usa ka wala makumpirma nga mensahe kinahanglan tipigan ug masuko. Ug pagkahuman sa unsang orasa? Ug ang jester nakaila kaniya. Tingali ang mga naadik nga mga mensahe sa serbisyo sa usa ka paagi makasulbad sa kini nga problema sa mga saklay, ingon, sa Telegram Desktop adunay mga 4 nga pila nga katumbas sa kanila (tingali labi pa, ingon sa nahisgutan na, alang niini kinahanglan nimo nga susihon ang code ug arkitektura nga labi ka seryoso; sa parehas nga oras. oras, nahibal-an namon nga dili kini mahimo nga usa ka sample; usa ka piho nga gidaghanon sa mga tipo gikan sa laraw sa MTProto wala gigamit niini).

Nganong nahitabo kini? Tingali, ang mga programmer sa server wala makasiguro sa kasaligan sa sulod sa cluster, o bisan ang pag-buffer sa front balancer, ug gibalhin kini nga problema sa kliyente. Tungod sa pagkawalay paglaum, gisulayan ni Vasily nga ipatuman ang usa ka alternatibo nga kapilian, nga adunay duha ra nga pila, gamit ang mga algorithm gikan sa TCP - pagsukod sa RTT sa server ug pag-adjust sa gidak-on sa "window" (sa mga mensahe) depende sa gidaghanon sa mga wala kumpirma nga hangyo. Sa ato pa, ang ingon nga usa ka bagis nga heuristic alang sa pag-assess sa load sa server mao ang pila sa among mga hangyo nga mahimo nga chew sa parehas nga oras ug dili mawala.

Aw, sa ato pa, nakasabot ka, di ba? Kung kinahanglan nimo nga ipatuman pag-usab ang TCP sa ibabaw sa usa ka protocol nga nagdagan sa TCP, kini nagpakita sa usa ka dili maayo nga pagkadisenyo nga protocol.

Oh oo, nganong kinahanglan nimo ang labaw pa sa usa ka pila, ug unsa ang gipasabut niini alang sa usa ka tawo nga nagtrabaho sa usa ka taas nga lebel nga API bisan pa? Tan-awa, nangayo ka, i-serialize kini, apan kasagaran dili nimo kini ipadala dayon. Ngano man? Kay ang tubag mao na msg_id, nga temporaryoаUsa ako ka label, ang buluhaton nga labing maayo nga i-postpone hangtod sa labing ulahi nga mahimo - kung isalikway kini sa server tungod sa dili pagtugma sa oras tali kanamo ug niya (siyempre, makahimo kami usa ka saklay nga magbalhin sa among oras gikan sa karon. sa server pinaagi sa pagdugang ug delta nga kalkulado gikan sa mga tubag sa server - ang mga opisyal nga kliyente nagbuhat niini, apan kini dili maayo ug dili tukma tungod sa buffering). Busa, kung maghimo ka usa ka hangyo gamit ang lokal nga tawag sa function gikan sa librarya, ang mensahe moagi sa mga mosunud nga yugto:

  1. Kini nahimutang sa usa ka pila ug naghulat sa pag-encrypt.
  2. Gitudlo msg_id ug ang mensahe miadto sa laing pila - posible nga pagpasa; ipadala sa socket.
  3. a) Gitubag sa server ang MsgsAck - ang mensahe gihatag, among gitangtang kini gikan sa "ubang pila".
    b) O vice versa, dili siya ganahan sa usa ka butang, mitubag siya badmsg - resend gikan sa "laing pila"
    c) Wala'y nahibal-an, ang mensahe kinahanglan nga masuko gikan sa lain nga pila - apan wala mahibal-an kung kanus-a.
  4. Ang server sa katapusan mitubag RpcResult - ang aktuwal nga tubag (o sayup) - dili lang gihatag, apan giproseso usab.

Tingali, ang paggamit sa mga sudlanan mahimong partially makasulbad sa problema. Kini kung ang usa ka hugpong sa mga mensahe giputos sa usa, ug ang server mitubag nga adunay usa ka kumpirmasyon sa tanan sa usa ka higayon, sa usa. msg_id. Apan isalikway usab niya kini nga pakete, kung adunay sayup, sa kinatibuk-an.

Ug sa niini nga punto dili teknikal nga mga konsiderasyon moabut sa pagdula. Gikan sa kasinatian, nakakita kami daghang mga crutches, ug dugang pa, makakita na kami karon og daghang mga pananglitan sa dili maayo nga tambag ug arkitektura - sa ingon nga mga kahimtang, takus ba ang pagsalig ug paghimo sa ingon nga mga desisyon? Ang pangutana kay retorika (siyempre dili).

Unsa man ang atong gihisgutan? Kung sa hisgutanan nga "mga mensahe sa droga bahin sa mga mensahe" mahimo ka gihapon nga mangagpas nga adunay mga pagsupak sama sa "tanga ka, wala ka kasabot sa among maayo nga plano!" (mao nga isulat una ang dokumentasyon, ingon nga ang normal nga mga tawo kinahanglan, nga adunay katarungan ug mga pananglitan sa pagbayloay sa pakete, unya maghisgot kami), unya ang mga timing/timeout usa ka praktikal ug piho nga pangutana, ang tanan dinhi nahibal-an sa dugay nga panahon. Unsa ang gisulti kanato sa dokumentasyon mahitungod sa mga timeout?

Ang usa ka server kasagarang moila sa resibo sa usa ka mensahe gikan sa usa ka kliyente (kasagaran, usa ka pangutana sa RPC) gamit ang usa ka tubag sa RPC. Kung ang usa ka tubag dugay nga moabut, ang usa ka server mahimo una nga magpadala usa ka resibo nga pag-ila, ug sa ulahi, ang tubag sa RPC mismo.

Ang usa ka kliyente kasagarang moila sa resibo sa usa ka mensahe gikan sa usa ka server (kasagaran, usa ka RPC nga tubag) pinaagi sa pagdugang sa usa ka pag-ila sa sunod nga RPC nga pangutana kon kini dili kaayo ipadala sa ulahi (kon kini namugna, ingnon, 60-120 segundos human sa resibo. sa usa ka mensahe gikan sa server). Bisan pa, kung sa dugay nga panahon wala’y hinungdan nga magpadala mga mensahe sa server o kung adunay daghang wala mailhi nga mga mensahe gikan sa server (ingon, labaw sa 16), ang kliyente nagpadala usa ka stand-alone nga pag-ila.

... Akong gihubad: kita sa atong kaugalingon wala masayud kon unsa ka daghan ug unsa ang atong gikinahanglan niini, mao nga atong hunahunaon nga kini mahimong ingon niini.

Ug mahitungod sa mga ping:

Mga Mensahe sa Ping (PING/PONG)

ping#7abe77ec ping_id:long = Pong;

Ang tubag sagad ibalik sa parehas nga koneksyon:

pong#347773c5 msg_id:long ping_id:long = Pong;

Kini nga mga mensahe wala magkinahanglan og mga pag-ila. Ang usa ka pong gipasa lamang isip tubag sa usa ka ping samtang ang usa ka ping mahimong masugdan sa bisan asa nga kilid.

Gi-defer nga Pagsira sa Koneksyon + PING

ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;

Naglihok sama sa ping. Dugang pa, human kini madawat, ang server magsugod sa usa ka timer nga magsira sa kasamtangan nga koneksyon disconnect_delay segundos sa ulahi gawas kon kini makadawat sa usa ka bag-o nga mensahe sa sama nga matang nga awtomatikong resets sa tanan nga miaging timers. Kung ipadala sa kliyente kini nga mga ping kausa sa matag 60 segundos, pananglitan, mahimo’g itakda ang disconnect_delay nga katumbas sa 75 segundos.

Nabuang ka?! Sa 60 segundos, ang tren mosulod sa estasyon, ihulog ug kuhaon ang mga pasahero, ug mawad-an na usab og kontak sa tunel. Sa 120 segundos, samtang imong madungog kini, moabot kini sa lain, ug ang koneksyon lagmit maputol. Aw, klaro kung diin gikan ang mga bitiis - "Nakadungog ako usa ka tugtog, apan wala mahibal-an kung diin kini", adunay algorithm sa Nagl ug ang kapilian nga TCP_NODELAY, nga gituyo alang sa interactive nga trabaho. Apan, pasayloa ako, hupti ang default nga kantidad niini - 200 Millisegundos Kung gusto nimo nga maghulagway sa usa ka butang nga susama ug makatipig sa usa ka posible nga magtiayon nga mga pakete, unya ibutang kini sa 5 segundos, o bisan unsa ang "Gumagamit nga nag-type ..." nga timeout sa mensahe karon. Apan wala na.

Ug sa katapusan, pings. Nga mao, pagsusi sa liveness sa TCP koneksyon. Kataw-anan, apan mga 10 ka tuig na ang milabay nagsulat ako usa ka kritikal nga teksto bahin sa messenger sa dorm sa among faculty - ang mga tagsulat didto nag-ping usab sa server gikan sa kliyente, ug dili vice versa. Apan ang mga estudyante sa 3rd year usa ka butang, ug ang usa ka internasyonal nga opisina usa pa, dili ba?..

Una, usa ka gamay nga programa sa edukasyon. Ang koneksyon sa TCP, kung wala ang packet exchange, mahimong mabuhi sulod sa mga semana. Kini maayo ug daotan, depende sa katuyoan. Maayo kung adunay ka koneksyon sa SSH nga bukas sa server, mibangon ka gikan sa kompyuter, gi-reboot ang router alang sa gahum, mibalik sa imong lugar - ang sesyon pinaagi sa kini nga server wala gisi (wala ka nag-type bisan unsa, wala mga pakete), kini sayon. Dili maayo kung adunay libu-libo nga mga kliyente sa server, ang matag usa naggamit mga kapanguhaan (hello, Postgres!), Ug ang host sa kliyente tingali dugay na nga nag-reboot - apan wala kami mahibal-an bahin niini.

Ang mga sistema sa chat/IM nahulog sa ikaduha nga kaso alang sa usa ka dugang nga hinungdan - mga status sa online. Kung ang tiggamit "nahulog", kinahanglan nimo nga ipahibalo sa iyang mga interlocutors bahin niini. Kung dili, makuha nimo ang sayup nga nahimo sa mga tiglalang sa Jabber (ug gitul-id sulod sa 20 ka tuig) - ang user na-disconnect, apan nagpadayon sila sa pagsulat sa mga mensahe ngadto kaniya, nga nagtuo nga siya online (nga hingpit usab nga nawala niining pipila ka minuto. sa wala pa nadiskobrehan ang pagkadiskonekta). Dili, ang TCP_KEEPALIVE nga kapilian, nga daghang mga tawo nga wala makasabut kung giunsa ang pagtrabaho sa mga TCP timers, nga gibalhin bisan diin (pinaagi sa pagtakda sa mga ihalas nga kantidad sama sa napulo ka segundo), dili makatabang dinhi - kinahanglan nimo nga sigurohon nga dili lamang ang OS kernel sa makina sa user buhi, apan usab naglihok sa normal, sa makahimo sa pagtubag, ug ang aplikasyon sa iyang kaugalingon (sa imong hunahuna kini dili freeze? Telegram Desktop sa Ubuntu 18.04 froze alang kanako labaw pa kay sa makausa).

Mao nga kinahanglan nimo nga i-ping server kliyente, ug dili vice versa - kung buhaton kini sa kliyente, kung ang koneksyon nabuak, ang ping dili mahatag, ang katuyoan dili makab-ot.

Unsa ang atong makita sa Telegram? Kabaliktaran gyud! Aw, mao kana. Sa pormal, siyempre, ang duha ka kilid mahimong mag-ping sa usag usa. Sa praktis, ang mga kliyente naggamit og saklay ping_delay_disconnect, nga nagtakda sa timer sa server. Aw, pasayloa ko, dili ang kliyente ang magdesisyon kung unsa ka dugay siya gusto nga mopuyo didto nga wala’y ping. Ang server, base sa load niini, mas nahibalo. Apan, siyempre, kung dili nimo igsapayan ang mga kahinguhaan, nan ikaw ang imong kaugalingon nga daotan nga Pinocchio, ug usa ka saklay ang mobuhat ...

Giunsa kini pagkadisenyo?

Nagtuo ko nga ang mga kamatuoran sa ibabaw klaro nga nagpakita sa dili kaayo taas nga katakus sa Telegram/VKontakte team sa natad sa transportasyon (ug ubos) nga lebel sa mga network sa kompyuter ug sa ilang ubos nga mga kwalipikasyon sa may kalabutan nga mga butang.

Ngano nga kini nahimo nga labi ka komplikado, ug giunsa ang pagsulay sa mga arkitekto sa Telegram sa pagsupak? Ang kamatuoran nga sila misulay sa paghimo sa usa ka sesyon nga mabuhi sa TCP koneksyon break, i.e., unsa ang wala ipadala karon, kita ipadala sa ulahi. Tingali gisulayan usab nila ang paghimo sa usa ka transportasyon sa UDP, apan nakasugat sila og mga kalisud ug gibiyaan kini (mao kana ang hinungdan nga wala’y sulod ang dokumentasyon - wala’y ipanghambog). Apan tungod sa kakulang sa pagsabot kon sa unsang paagi ang mga network sa kinatibuk-an ug TCP sa partikular nga trabaho, diin kamo makasalig niini, ug diin kamo kinahanglan nga sa pagbuhat niini sa imong kaugalingon (ug sa unsa nga paagi), ug ang usa ka pagsulay sa combine niini uban sa cryptography “duha ka langgam uban sa usa ka bato”, mao kini ang resulta.

Sa unsang paagi kini gikinahanglan? Base sa kamatuoran nga msg_id usa ka timestamp nga gikinahanglan gikan sa usa ka cryptographic nga punto sa pagtan-aw aron mapugngan ang mga pag-atake sa pag-replay, usa ka sayup ang pag-attach sa usa ka talagsaon nga function sa identifier niini. Busa, kung wala’y sukaranan nga pagbag-o sa karon nga arkitektura (kung namugna ang sapa sa Mga Update, kana usa ka taas nga lebel nga hilisgutan sa API alang sa lain nga bahin sa kini nga serye sa mga post), ang usa kinahanglan nga:

  1. Ang server nga nagkupot sa koneksyon sa TCP sa kliyente adunay responsibilidad - kung nabasa kini gikan sa socket, palihug ilha, iproseso o ibalik ang usa ka sayup, walay mga pagkawala. Unya ang kumpirmasyon dili usa ka vector sa mga id, apan yano nga "ang katapusan nga nadawat seq_no" - usa ra ka numero, sama sa TCP (duha ka numero - ang imong seq ug ang gikumpirma). Kanunay kami sulod sa sesyon, dili ba?
  2. Ang timestamp aron mapugngan ang mga pag-atake sa pag-replay mahimong usa ka lahi nga field, usa ka la nonce. Gisusi kini, apan wala’y epekto sa bisan unsang butang. Igo na ug uint32 - kung ang atong asin mausab labing menos matag tunga sa adlaw, mahimo natong igahin ang 16 ka bits ngadto sa ubos nga order bits sa integer nga bahin sa kasamtangan nga panahon, ang uban - ngadto sa fractional nga bahin sa usa ka segundo (sama karon).
  3. Gitangtang msg_id sa tanan - gikan sa punto sa panglantaw sa pag-ila sa mga hangyo sa backends, adunay, una, ang kliyente id, ug ikaduha, ang session id, concatenate kanila. Tungod niini, usa ra ka butang ang igo ingon usa ka identifier sa hangyo seq_no.

Dili usab kini ang labing malampuson nga kapilian; ang usa ka kompleto nga random mahimong magsilbing usa ka identifier - nahimo na kini sa taas nga lebel nga API kung magpadala usa ka mensahe, sa paagi. Mas maayo nga hingpit nga himuon ang arkitektura gikan sa paryente hangtod sa hingpit, apan kini usa ka hilisgutan alang sa lain nga bahin, dili kini nga post.

API?

Ta-daam! Busa, nga nanlimbasug sa usa ka dalan nga puno sa kasakit ug crutches, sa katapusan nakahimo kami sa pagpadala sa bisan unsa nga mga hangyo ngadto sa server ug makadawat sa bisan unsa nga mga tubag ngadto kanila, ingon man usab sa pagdawat sa mga update gikan sa server (dili sa pagtubag sa usa ka hangyo, apan kini mismo. nagpadala kanamo, sama sa PUSH, kung adunay mas klaro nga ingon niana).

Atensyon, karon adunay usa ra nga pananglitan sa Perl sa artikulo! (alang sa mga dili pamilyar sa syntax, ang una nga argumento sa panalangin mao ang istruktura sa datos sa butang, ang ikaduha mao ang klase niini):

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' )
};

Oo, dili usa ka spoiler sa katuyoan - kung wala pa nimo kini mabasa, padayon ug buhata kini!

Oh, wai~~... unsay hitsura niini? Usa ka butang nga pamilyar kaayo ... tingali kini ang istruktura sa datos sa usa ka tipikal nga Web API sa JSON, gawas nga ang mga klase gilakip usab sa mga butang?..

Mao ni ang resulta... Unsa man kini tanan, mga kauban?.. Daghan kaayong paningkamot - ug mihunong kami aron mopahulay diin ang mga Web programmer nagsugod pa lang?..Dili lang ba ang JSON sa HTTPS mas simple?! Unsa may among nakuha nga baylo? Takus ba ang paningkamot?

Atong susihon kung unsa ang gihatag sa TL+MTProto ug kung unsang mga alternatibo ang mahimo. Aw, ang HTTP, nga nagpunting sa modelo nga tubag sa hangyo, usa ka dili maayo nga angay, apan labing menos usa ka butang sa ibabaw sa TLS?

Compact nga serialization. Sa pagkakita niini nga istruktura sa datos, susama sa JSON, akong nahinumduman nga adunay binary nga mga bersyon niini. Atong markahan ang MsgPack nga dili igo nga mapadako, apan adunay, pananglitan, CBOR - sa paagi, usa ka sumbanan nga gihulagway sa RFC 7049. Kini mao ang talagsaon alang sa kamatuoran nga kini naghubit mga tag, isip mekanismo sa pagpalapad, ug taliwala sa standardized na nga anaa:

  • 25 + 256 - pag-ilis sa balik-balik nga mga linya sa usa ka pakisayran sa numero sa linya, ingon nga usa ka barato nga paagi sa kompresiyon
  • 26 - serialized Perl nga butang nga adunay ngalan sa klase ug mga argumento sa constructor
  • 27 - serialized language-independent nga butang nga adunay type name ug constructor arguments

Aw, gisulayan nako nga i-serialize ang parehas nga datos sa TL ug sa CBOR nga adunay gipalihok nga string ug object packing. Ang resulta nagsugod sa lain-laing pabor sa CBOR sa usa ka megabyte:

cborlen=1039673 tl_len=1095092

Ug busa, konklusyon: Adunay labi ka yano nga mga pormat nga dili ubos sa problema sa pagkapakyas sa pag-synchronize o wala mailhi nga identifier, nga adunay parehas nga kahusayan.

Pagtukod sa paspas nga koneksyon. Kini nagpasabot nga zero RTT human sa reconnection (sa diha nga ang yawe nahimo na sa makausa) - magamit gikan sa pinakaunang mensahe sa MTProto, apan sa pipila ka mga reserbasyon - naigo sa samang asin, ang sesyon dili dunot, ug uban pa. Unsa man ang gitanyag kanato sa TLS? Quote sa hilisgutan:

Kung gigamit ang PFS sa TLS, TLS session ticket (RFC 5077) aron ipadayon ang usa ka naka-encrypt nga sesyon nga wala’y pag-negosasyon pag-usab sa mga yawe ug wala’y pagtipig sa hinungdanon nga kasayuran sa server. Kung giablihan ang una nga koneksyon ug paghimo og mga yawe, gi-encrypt sa server ang estado sa koneksyon ug gipasa kini sa kliyente (sa porma sa tiket sa sesyon). Tungod niini, kung gipadayon ang koneksyon, ang kliyente nagpadala usa ka tiket sa sesyon, lakip ang yawe sa sesyon, balik sa server. Ang tiket mismo gi-encrypt gamit ang temporaryo nga yawe (session ticket key), nga gitipigan sa server ug kinahanglang iapod-apod sa tanang frontend server nga nagproseso sa SSL sa clustered solutions.[10]. Sa ingon, ang pagpaila sa usa ka tiket sa sesyon mahimong makalapas sa PFS kung ang temporaryo nga mga yawe sa server makompromiso, pananglitan, kung kini gitipigan sa dugay nga panahon (OpenSSL, nginx, Apache nagtipig niini pinaagi sa default sa tibuuk nga gidugayon sa programa; gigamit sa mga sikat nga site. ang yawe sulod sa daghang oras, hangtod sa mga adlaw).

Dinhi ang RTT dili zero, kinahanglan nimo nga ibaylo ang labing menos ClientHello ug ServerHello, pagkahuman mahimo’g ipadala sa kliyente ang datos kauban ang Tapos na. Apan dinhi kinahanglan natong hinumdoman nga wala kita sa Web, uban sa hugpong sa bag-ong giablihan nga mga koneksyon, apan usa ka mensahero, ang koneksyon nga kasagaran usa ug labaw pa o dili kaayo dugay, medyo mubo nga mga hangyo sa mga Web page - ang tanan multiplexed. sa sulod. Sa ato pa, madawat ra kung wala kami makit-an nga dili maayo nga seksyon sa subway.

Nakalimot ug lain? Isulat sa mga komento.

Ang pagpadayon!

Sa ikaduha nga bahin sa kini nga serye sa mga post atong tagdon dili teknikal, apan mga isyu sa organisasyon - mga pamaagi, ideolohiya, interface, kinaiya sa mga tiggamit, ug uban pa. Base, bisan pa, sa teknikal nga impormasyon nga gipresentar dinhi.

Ang ikatulo nga bahin magpadayon sa pag-analisar sa teknikal nga sangkap / kasinatian sa pag-uswag. Makakat-on ka, ilabina:

  • pagpadayon sa pandemonium nga adunay lainlaing klase sa TL
  • wala mailhi nga mga butang bahin sa mga channel ug supergroup
  • ngano nga ang mga diyalogo mas grabe kaysa roster
  • mahitungod sa absolute vs relative nga pag-address sa mensahe
  • unsa ang kalainan tali sa litrato ug imahe
  • kung giunsa ang pagsamok sa emoji sa italic nga teksto

ug uban pang crutches! Pagbantay!

Source: www.habr.com

Idugang sa usa ka comment