Kritika tal-protokoll u l-approċċi organizzattivi ta 'Telegram. Parti 1, teknika: esperjenza ta 'kitba ta' klijent mill-bidu - TL, MT

Riċentement, karigi dwar kemm Telegram huwa tajjeb, kemm huma brillanti u esperjenzati l-aħwa Durov fil-bini ta 'sistemi tan-netwerk, eċċ bdew jidhru aktar spiss fuq Habré. Fl-istess ħin, ftit nies verament mgħaddsa fl-apparat tekniku - l-iktar, jużaw API Bot pjuttost sempliċi (u pjuttost differenti minn MTProto) ibbażata fuq JSON, u ġeneralment jaċċettaw biss fuq il-fidi it-tifħir u l-PR kollha li jduru madwar il-messaġġier. Kważi sena u nofs ilu, il-kollega tiegħi fl-NGO Eshelon Vasily (sfortunatament, il-kont tiegħu fuq Habré tħassar flimkien mal-abbozz) beda jikteb il-klijent Telegram tiegħu stess mill-bidu f'Perl, u aktar tard ingħaqad l-awtur ta 'dawn il-linji. Għaliex Perl, xi wħud immedjatament jistaqsu? Minħabba li proġetti bħal dawn diġà jeżistu f’lingwi oħra.Fil-fatt, dan mhux il-punt, jista’ jkun hemm xi lingwa oħra fejn ma jkunx hemm librerija lesta, u għalhekk l-awtur għandu jmur it-triq kollha mill-bidu. Barra minn hekk, il-kriptografija hija kwistjoni ta 'fiduċja, iżda tivverifika. Bi prodott immirat lejn is-sigurtà, ma tistax sempliċement tistrieħ fuq librerija lesta mill-manifattur u tafdaha bl-addoċċ (madankollu, dan huwa suġġett għat-tieni parti). Bħalissa, il-librerija taħdem pjuttost tajjeb fil-livell "medja" (jippermettilek tagħmel kwalunkwe talba API).

Madankollu, mhux se jkun hemm ħafna kriptografija jew matematika f'din is-serje ta 'postijiet. Iżda se jkun hemm ħafna dettalji tekniċi oħra u krozzi arkitettoniċi (utili wkoll għal dawk li mhux se jiktbu mill-bidu, iżda se jużaw il-librerija fi kwalunkwe lingwa). Għalhekk, l-għan ewlieni kien li tipprova timplimenta l-klijent mill-bidu nett skond dokumentazzjoni uffiċjali. Jiġifieri, ejja nassumu li l-kodiċi tas-sors tal-klijenti uffiċjali huwa magħluq (għal darb'oħra, fit-tieni parti se nkopru f'aktar dettall is-suġġett tal-fatt li dan huwa minnu jiġri hekk), iżda, bħal fl-antik, pereżempju, hemm standard bħal RFC - huwa possibbli li tikteb klijent skont l-ispeċifikazzjoni biss, "mingħajr ma tħares" lejn il-kodiċi tas-sors, kemm jekk ikun uffiċjali (Telegram Desktop, mobbli), jew Telethon mhux uffiċjali?

Werrej:

Dokumentazzjoni... teżisti, hux? Veru?..

Is-sajf li għadda bdew jinġabru frammenti ta’ noti għal dan l-artiklu. Dan il-ħin kollu fuq il-websajt uffiċjali https://core.telegram.org Id-dokumentazzjoni kienet minn Saff 23, i.e. mwaħħla x'imkien fl-2014 (ftakar, lanqas kien hemm kanali dakinhar?). Naturalment, fit-teorija, dan kellu jippermettilna nimplimentaw klijent b'funzjonalità dak iż-żmien fl-2014. Iżda anke f'dan l-istat, id-dokumentazzjoni kienet, l-ewwelnett, mhux kompluta, u t-tieni, f'postijiet kienet tikkontradixxi lilha nnifisha. Ftit aktar minn xahar ilu, f’Settembru 2019, kien aċċidentalment Ġie skopert li kien hemm aġġornament kbir tad-dokumentazzjoni fuq is-sit, għas-Layer 105 kompletament riċenti, b’nota li issa kollox jeħtieġ li jerġa’ jinqara. Tabilħaqq, ħafna artikoli ġew riveduti, iżda ħafna baqgħu ma nbidlux. Għalhekk, meta taqra l-kritika hawn taħt dwar id-dokumentazzjoni, għandek iżżomm f'moħħok li xi wħud minn dawn l-affarijiet m'għadhomx rilevanti, iżda xi wħud għadhom pjuttost. Wara kollox, 5 snin fid-dinja moderna mhux biss żmien twil, iżda ħafna ħafna minn. Minn dawk iż-żminijiet (speċjalment jekk ma tqisx is-siti tal-ġeochat mormija u reġgħu minn dakinhar), in-numru ta 'metodi API fl-iskema kiber minn mija għal aktar minn mitejn u ħamsin!

Minn fejn tibda bħala awtur żagħżugħ?

Ma jimpurtax jekk tiktebx mill-bidu jew tużax, pereżempju, libreriji lesti bħal Telethon għal Python jew Madeline għall PHP, fi kwalunkwe każ, ser ikollok bżonn l-ewwel irreġistra l-applikazzjoni tiegħek - tikseb parametri api_id и api_hash (dawk li ħadmu mal-API VKontakte jifhmu immedjatament) li biha s-server jidentifika l-applikazzjoni. Dan għandi bzonn agħmel dan għal raġunijiet legali, imma nitkellmu aktar dwar għaliex l-awturi tal-libreriji ma jistgħux jippubblikawha fit-tieni parti. Tista 'tkun sodisfatt bil-valuri tat-test, għalkemm huma limitati ħafna - il-fatt hu li issa tista' tirreġistra wieħed biss app, sabiex ma għaġġla headlong fiha.

Issa, mil-lat tekniku, għandna nkunu interessati fil-fatt li wara r-reġistrazzjoni għandna nirċievu notifiki minn Telegram dwar aġġornamenti għad-dokumentazzjoni, protokoll, eċċ. Jiġifieri wieħed jista’ jassumi li s-sit bil-baċiri kien sempliċement abbandunat u baqa’ jaħdem speċifikament ma’ dawk li bdew jagħmlu l-klijenti, għax huwa aktar faċli. Imma le, xejn bħal dan ma ġie osservat, l-ebda informazzjoni ma waslet.

U jekk tikteb mill-bidu, allura l-użu tal-parametri miksuba fil-fatt għadu 'l bogħod. Għalkemm https://core.telegram.org/ u titkellem dwarhom fil Getting Started l-ewwelnett, fil-fatt, l-ewwel trid timplimenta MTProto protokoll - imma jekk inti emmen tqassim skond il-mudell OSI fl-aħħar tal-paġna għal deskrizzjoni ġenerali tal-protokoll, allura huwa kompletament għalxejn.

Fil-fatt, kemm qabel kif ukoll wara MTProto, fuq diversi livelli f'daqqa (kif jgħidu netwerkers barranin li jaħdmu fil-kernel tal-OS, ksur tas-saff), suġġett kbir, bl-uġigħ u terribbli se jfixkel...

Serializzazzjoni binarja: TL (Type Language) u l-iskema tagħha, u saffi, u ħafna kliem ieħor tal-biża

Dan is-suġġett, fil-fatt, huwa ċ-ċavetta għall-problemi ta 'Telegram. U se jkun hemm ħafna kliem terribbli jekk tipprova tidħol fih.

Allura, hawn id-dijagramma. Jekk tiġi f’moħħok din il-kelma, għid, Skema JSON, Inti ħsibt b'mod korrett. L-għan huwa l-istess: xi lingwa biex tiddeskrivi sett possibbli ta 'dejta trażmessa. Dan huwa fejn jispiċċaw ix-xebh. Jekk mill-paġna MTProto protokoll, jew mis-siġra tas-sors tal-klijent uffiċjali, aħna nippruvaw niftħu xi skema, naraw xi ħaġa bħal:

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;

Persuna li tara dan għall-ewwel darba b'mod intuwittiv tkun tista' tagħraf biss parti minn dak li hemm miktub - ukoll, dawn apparentement huma strutturi (għalkemm fejn hu l-isem, fuq ix-xellug jew fuq il-lemin?), hemm oqsma fihom, wara li tip isegwi wara kolon... probabbilment. Hawnhekk fil-parentesi angolari hemm probabilment mudelli bħal f'C++ (fil-fatt, mhux tassew). U xi jfissru s-simboli l-oħra kollha, marki ta’ mistoqsija, marki ta’ esklamazzjoni, perċentwali, marki tal-hash (u ovvjament li jfissru affarijiet differenti f’postijiet differenti), xi drabi preżenti u kultant le, numri eżadeċimali - u l-aktar importanti, kif tikseb minn dan regolari (li mhux se jiġi miċħud mis-server) byte stream? Int ser ikollok taqra d-dokumentazzjoni (iva, hemm links għall-iskema fil-verżjoni JSON fil-qrib - iżda dan ma jagħmilha aktar ċara).

Iftaħ il-paġna Serializzazzjoni tad-Dejta Binarja u adsa fid-dinja maġika tal-faqqiegħ u l-matematika diskreta, xi ħaġa simili għal matan fir-4 sena. Alfabett, tip, valur, combinator, combinator funzjonali, forma normali, tip kompost, tip polimorfiku... u dak kollu biss l-ewwel paġna! Li jmiss jistenniek Lingwa TL, li, għalkemm diġà fiha eżempju ta’ talba u tweġiba trivjali, ma tipprovdi xejn tweġiba għal każijiet aktar tipiċi, li jfisser li jkollok tgħaddi minn rakkont tal-matematika tradotta mir-Russu għall-Ingliż fuq tmienja oħra inkorporati. paġni!

Qarrejja familjari mal-lingwi funzjonali u l-inferenza tat-tip awtomatiku se, ovvjament, jaraw il-lingwa ta 'deskrizzjoni f'din il-lingwa, anke mill-eżempju, bħala ħafna aktar familjari, u jistgħu jgħidu li dan fil-fatt mhuwiex ħażin fil-prinċipju. L-oġġezzjonijiet għal dan huma:

  • Iva, l-għan ħsejjes tajba, imma sfortunatament, hi mhux miksub
  • L-edukazzjoni fl-universitajiet Russi tvarja anke fost l-ispeċjalitajiet tal-IT - mhux kulħadd ħa l-kors korrispondenti
  • Fl-aħħarnett, kif se naraw, fil-prattika huwa mhux meħtieġ, peress li jintuża biss subsett limitat anki tat-TL li kien deskritt

Kif intqal LeonNerd fuq il-kanal #perl fin-netwerk FreeNode IRC, li pprova jimplimenta gate minn Telegram għal Matrix (it-traduzzjoni tal-kwotazzjoni mhix preċiża mill-memorja):

Tħoss li xi ħadd ġie introdott għat-teorija tat-tip għall-ewwel darba, eċċitata, u beda jipprova jilgħab magħha, mhux verament jieħu ħsieb jekk kienx meħtieġ fil-prattika.

Ara għalik innifsek, jekk il-ħtieġa għal bare-types (int, long, eċċ.) bħala xi ħaġa elementari ma tqajjimx mistoqsijiet - fl-aħħar mill-aħħar għandhom jiġu implimentati manwalment - per eżempju, ejja nagħmel tentattiv biex nidħlu minnhom vettur. Jiġifieri, fil-fatt, firxa, jekk issejjaħ l-affarijiet li jirriżultaw bl-ismijiet proprji tagħhom.

Imma qabel

Deskrizzjoni qasira ta 'sottosett ta' sintassi TL għal dawk li ma jaqrawx id-dokumentazzjoni uffiċjali

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;

Id-definizzjoni dejjem tibda kostruttur, wara li b'mod fakultattiv (fil-prattika - dejjem) permezz tas-simbolu # għandu jkun CRC32 mis-sekwenza ta' deskrizzjoni normalizzata ta' dan it-tip. Wara tiġi deskrizzjoni tal-oqsma; jekk jeżistu, it-tip jista 'jkun vojt. Dan kollu jispiċċa b'sinjal ugwali, l-isem tat-tip li għalih jappartjeni dan il-kostruttur - jiġifieri, fil-fatt, is-sottotip -. Il-bniedem fuq il-lemin tas-sinjal ugwali huwa polimorfika - jiġifieri, diversi tipi speċifiċi jistgħu jikkorrispondu għaliha.

Jekk id-definizzjoni sseħħ wara l-linja ---functions---, allura s-sintassi tibqa 'l-istess, iżda t-tifsira tkun differenti: il-kostruttur se jsir l-isem tal-funzjoni RPC, l-oqsma se jsiru parametri (ukoll, jiġifieri, se tibqa' eżattament l-istess struttura mogħtija, kif deskritt hawn taħt , din tkun sempliċement it-tifsira assenjata), u t-"tip polimorfiku " - it-tip tar-riżultat ritornat. Veru, xorta se tibqa 'polimorfika - definita biss fit-taqsima ---types---, iżda dan il-kostruttur "mhux jitqies". Tagħbija żejda tat-tipi ta’ funzjonijiet imsejħa bl-argumenti tagħhom, i.e. Għal xi raġuni, diversi funzjonijiet bl-istess isem iżda firem differenti, bħal f'C++, mhumiex previsti fit-TL.

Għaliex "kostruttur" u "polimorfiku" jekk mhux OOP? Ukoll, fil-fatt, ikun aktar faċli għal xi ħadd li jaħseb dwar dan f'termini OOP - tip polimorfiku bħala klassi astratta, u l-kostrutturi huma l-klassijiet tad-dixxendenti diretti tiegħu, u final fit-terminoloġija ta’ numru ta’ lingwi. Fil-fatt, ovvjament, hawn biss xebh b'metodi reali ta' kostruttur mgħobbija żżejjed f'lingwi ta' programmar OO. Peress li hawn biss strutturi tad-dejta, m'hemm l-ebda metodi (għalkemm id-deskrizzjoni tal-funzjonijiet u l-metodi aktar hija pjuttost kapaċi toħloq konfużjoni fir-ras li jeżistu, iżda din hija kwistjoni differenti) - tista 'taħseb kostruttur bħala valur minn li qed jinbena tip meta taqra byte stream.

Kif jiġri dan? Id-deserializer, li dejjem jaqra 4 bytes, jara l-valur 0xcrc32 - u jifhem x'se jiġri wara field1 bit-tip int, i.e. jaqra eżattament 4 bytes, fuq dan il-qasam overlying mat-tip PolymorType aqra. Ara 0x2crc32 u jifhem li hemm żewġ oqsma oħra, l-ewwel long, li jfisser li naqraw 8 bytes. U mbagħad għal darb'oħra tip kumpless, li huwa deserialized bl-istess mod. Pereżempju, Type3 jistgħu jiġu ddikjarati fiċ-ċirkwit hekk kif żewġ kostrutturi, rispettivament, allura dawn għandhom jiltaqgħu jew 0x12abcd34, u wara trid taqra 4 bytes oħra intJew 0x6789cdef, wara li ma jkun hemm xejn. Xi ħaġa oħra - għandek bżonn tarmi eċċezzjoni. Xorta waħda, wara dan immorru lura għall-qari ta '4 bytes int marġini field_c в constructorTwo u b’hekk nispiċċaw naqraw tagħna PolymorType.

Fl-aħħarnett, jekk tinqabad 0xdeadcrc għall- constructorThree, allura kollox isir aktar ikkumplikat. L-ewwel qasam tagħna huwa bit_flags_of_what_really_present bit-tip # - fil-fatt, dan huwa biss alias għat-tip nat, li tfisser "numru naturali". Jiġifieri, fil-fatt, int mhux iffirmat huwa, mill-mod, l-uniku każ meta n-numri mhux iffirmati jseħħu f'ċirkwiti reali. Allura, li jmiss hija kostruzzjoni b'marka ta 'mistoqsija, li jfisser li dan il-qasam - se jkun preżenti fuq il-wajer biss jekk il-bit korrispondenti huwa ssettjat fil-qasam imsemmi (bejn wieħed u ieħor bħal operatur ternarju). Allura, ejja nassumu li dan il-bit ġie stabbilit, li jfisser li aktar għandna bżonn naqraw qasam bħal Type, li fl-eżempju tagħna għandu 2 kostrutturi. Wieħed huwa vojt (jikkonsisti biss mill-identifikatur), l-ieħor għandu field ids bit-tip ids:Vector<long>.

Tista 'taħseb li kemm il-mudelli kif ukoll il-ġeneriċi huma fil-vantaġġi jew Java. Imma le. Kważi. Dan l-uniku każ ta 'użu ta' parentesi angolari f'ċirkwiti reali, u jintuża BISS għal Vector. Fi fluss byte, dawn se jkunu 4 CRC32 bytes għat-tip Vector innifsu, dejjem l-istess, imbagħad 4 bytes - in-numru ta 'elementi ta' firxa, u mbagħad dawn l-elementi nfushom.

Żid ma 'dan il-fatt li s-serialization dejjem isseħħ fi kliem ta' 4 bytes, it-tipi kollha huma multipli tiegħu - it-tipi inkorporati huma deskritti wkoll bytes и string b'serialization manwali tat-tul u dan l-allinjament minn 4 - ukoll, jidher li ħoss normali u anke relattivament effettiv? Għalkemm TL huwa ddikjarat li huwa serialization binarju effettiv, għall-infern magħhom, bl-espansjoni ta 'kważi xi ħaġa, anke valuri Boolean u kordi ta' karattru wieħed għal 4 bytes, JSON xorta se jkun ħafna eħxen? Ara, anke oqsma mhux meħtieġa jistgħu jinqabżu b'bnadar bit, kollox huwa pjuttost tajjeb, u anke estensibbli għall-futur, allura għaliex ma żżidx oqsma fakultattivi ġodda mal-kostruttur aktar tard?...

Imma le, jekk taqra mhux id-deskrizzjoni qasira tiegħi, iżda d-dokumentazzjoni sħiħa, u taħseb dwar l-implimentazzjoni. L-ewwelnett, is-CRC32 tal-kostruttur huwa kkalkulat skont il-linja normalizzata tad-deskrizzjoni tat-test tal-iskema (neħħi spazju abjad żejjed, eċċ.) - Allura jekk jiżdied qasam ġdid, il-linja tad-deskrizzjoni tat-tip tinbidel, u għalhekk is-CRC32 tagħha u , konsegwentement, serialization. U x'jagħmel il-klijent l-antik jekk jirċievi qasam b'bnadar ġodda stabbiliti, u ma jkunx jaf x'għandu jagħmel magħhom wara?...

It-tieni nett, ejja niftakru CRC32, li huwa użat hawnhekk essenzjalment bħala funzjonijiet hash biex tiddetermina unikament liema tip qed jiġi (de)serialized. Hawnhekk qed niffaċċjaw il-problema tal-ħabtiet - u le, il-probabbiltà mhix waħda minn 232, iżda ħafna akbar. Min ftakar li CRC32 huwa ddisinjat biex jiskopri (u jikkoreġi) żbalji fil-kanal ta 'komunikazzjoni, u għaldaqstant itejjeb dawn il-proprjetajiet għad-detriment ta' ħaddieħor? Pereżempju, ma jimpurtahx mill-arranġament mill-ġdid tal-bytes: jekk tikkalkula CRC32 minn żewġ linji, fit-tieni tiskambja l-ewwel 4 bytes mal-4 bytes li jmiss - ikun l-istess. Meta l-input tagħna huwa kordi ta 'test mill-alfabett Latin (u punteġġjatura żgħira), u dawn l-ismijiet mhumiex partikolarment każwali, il-probabbiltà ta' tali riarranġament tiżdied ħafna.

Mill-mod, min iċċekkja dak li kien hemm? tassew CRC32? Wieħed mill-kodiċi tas-sors bikrija (anki qabel Waltman) kellu funzjoni hash li mmultiplika kull karattru bin-numru 239, tant maħbub minn dawn in-nies, ha ha!

Fl-aħħarnett, okay, indunajna li l-kostrutturi b'tip ta 'qasam Vector<int> и Vector<PolymorType> se jkollu CRC32 differenti. Xi ngħidu dwar il-prestazzjoni onlajn? U mil-lat teoretiku, dan isir parti mit-tip? Ejja ngħidu aħna ngħaddu firxa ta 'għaxart elef numri, ukoll ma Vector<int> kollox huwa ċar, it-tul u 40000 bytes oħra. X'jiġri jekk dan Vector<Type2>, li jikkonsisti f'qasam wieħed biss int u huwa waħdu fit-tip - għandna bżonn nirrepetu 10000xabcdef0 34 darba u mbagħad 4 bytes int, jew il-lingwa hija kapaċi INDEPENDIha għalina mill-kostruttur fixedVec u minflok 80000 bytes, ittrasferixxi mill-ġdid biss 40000?

Din mhix mistoqsija teoretika inattiva - immaġina li tirċievi lista ta 'utenti tal-grupp, li kull wieħed minnhom għandu id, isem, kunjom - id-differenza fl-ammont ta' dejta trasferita fuq konnessjoni mobbli tista 'tkun sinifikanti. Hija preċiżament l-effettività tas-serializzazzjoni tat-Telegram li tiġi reklamata lilna.

Allura ...

Vector, li qatt ma ġie rilaxxat

Jekk tipprova tgħaddi mill-paġni ta 'deskrizzjoni ta' kombinaturi u l-bqija, se tara li vettur (u anke matriċi) qed jipprova formalment joħroġ permezz ta 'tuples ta' diversi folji. Iżda fl-aħħar jinsew, il-pass finali jinqabeż, u definizzjoni ta 'vettur hija sempliċement mogħtija, li għadha mhix marbuta ma' tip. X'ġara? Fil-lingwi programmazzjoni, speċjalment dawk funzjonali, huwa pjuttost tipiku li tiddeskrivi l-istruttura b'mod rikursiv - il-kompilatur bl-evalwazzjoni għażżien tiegħu jifhem u jagħmel kollox hu stess. Fil-lingwa serialization tad-data dak li hemm bżonn huwa EFFIĊJENZA: huwa biżżejjed li sempliċiment tiddeskrivi lista, i.e. struttura ta 'żewġ elementi - l-ewwel huwa element tad-dejta, it-tieni huwa l-istess struttura nnifisha jew spazju vojt għad-denb (pakkett (cons) f'Lisp). Iżda dan ovvjament jeħtieġ ta 'kull wieħed element jonfoq 4 bytes addizzjonali (CRC32 fil-każ f'TL) biex jiddeskrivi t-tip tiegħu. Array jista' wkoll jiġi deskritt faċilment daqs fiss, iżda fil-każ ta 'firxa ta' tul mhux magħruf bil-quddiem, aħna nkissru.

Għalhekk, peress li TL ma jippermettix li joħroġ vettur, kellu jiżdied fuq il-ġenb. Fl-aħħar mill-aħħar id-dokumentazzjoni tgħid:

Is-serjelizzazzjoni dejjem tuża l-istess kostruttur "vettur" (const 0x1cb5c415 = crc32 ("vector t:Type # [ t ] = Vector t") li mhuwiex dipendenti fuq il-valur speċifiku tal-varjabbli tat-tip t.

Il-valur tal-parametru fakultattiv t mhuwiex involut fis-serialization peress li huwa derivat mit-tip tar-riżultat (dejjem magħruf qabel id-deserialization).

Agħti ħarsa aktar mill-qrib: vector {t:Type} # [ t ] = Vector t - imma imkien Din id-definizzjoni nnifisha ma tgħidx li l-ewwel numru għandu jkun ugwali għat-tul tal-vettur! U ma jiġi minn imkien. Din hija fatt li jeħtieġ li wieħed iżomm f'moħħu u jiġi implimentat b'idejk. X'imkien ieħor, id-dokumentazzjoni saħansitra ssemmi b'mod onest li t-tip mhuwiex reali:

Il-psewdotip polimorfiku Vector t huwa "tip" li l-valur tiegħu huwa sekwenza ta 'valuri ta' kwalunkwe tip t, jew f'kaxxa jew vojta.

... imma ma tiffokax fuqha. Meta int, għajjien li tgħaddi t-tiġbid tal-matematika (forsi anke magħrufa lilek minn kors universitarju), tiddeċiedi li taqta’ qalbek u fil-fatt tħares lejn kif taħdem magħha fil-prattika, l-impressjoni li tħalli f’rasek hija li dan huwa Serju Matematika fil-qalba, kienet ivvintata b'mod ċar minn Cool People (żewġ matematiċi - rebbieħ ACM), u mhux kulħadd. L-għan - li juri - intlaħaq.

Mill-mod, dwar in-numru. Ejjew infakkarkom li # huwa sinonimu nat, numru naturali:

Hemm espressjonijiet tat-tip (tip-espr) u espressjonijiet numeriċi (nat-expr). Madankollu, huma definiti bl-istess mod.

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

imma fil-grammatika huma deskritti bl-istess mod, i.e. Din id-differenza trid terġa' tiġi mfakkar u titqiegħed fl-implimentazzjoni bl-idejn.

Ukoll, iva, tipi ta 'mudelli (vector<int>, vector<User>) għandhom identifikatur komuni (#1cb5c415), i.e. jekk taf li s-sejħa titħabbar bħala

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

allura m'għadekx qed tistenna biss vettur, iżda vettur ta 'utenti. B'mod aktar preċiż, ghandu stenna - fil-kodiċi reali, kull element, jekk mhux tip vojt, se jkollu kostruttur, u b'mod tajjeb fl-implimentazzjoni jkun meħtieġ li tivverifika - iżda aħna ntbagħtu eżattament f'kull element ta 'dan il-vettur dak it-tip? X'jiġri kieku kien xi tip ta 'PHP, li fih firxa jista' jkun fiha tipi differenti f'elementi differenti?

F'dan il-punt tibda taħseb - TL bħal dan huwa meħtieġ? Forsi għall-karrettun ikun possibbli li tuża serializzatur uman, l-istess protobuf li diġà kien jeżisti dak iż-żmien? Dik kienet it-teorija, ejja nħarsu lejn il-prattika.

Implimentazzjonijiet TL eżistenti fil-kodiċi

TL twieled fil-fond ta 'VKontakte anke qabel l-avvenimenti famużi bil-bejgħ tas-sehem ta' Durov u (żgur), anki qabel ma beda l-iżvilupp tat-Telegram. U f'sors miftuħ kodiċi tas-sors tal-ewwel implimentazzjoni tista ssib ħafna krozzi umoristiċi. U l-lingwa nnifisha ġiet implimentata hemmhekk b'mod aktar sħiħ milli hi issa f'Telegram. Pereżempju, il-hashes ma jintużaw xejn fl-iskema (li jfisser pseudotip inkorporat (bħal vettur) b'imġieba devjanti). Or

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

imma ejja nikkunsidraw, għall-fini tal-kompletezza, biex intraċċaw, biex ngħidu hekk, l-evoluzzjoni tal-Ġgant tal-Ħsieb.

#define ZHUKOV_BYTES_HACK

#ifdef ZHUKOV_BYTES_HACK

/* dirty hack for Zhukov request */

Jew din sabiħa:

    static const char *reserved_words_polymorhic[] = {

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

      };

Dan il-framment huwa dwar mudelli bħal:

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

Din hija d-definizzjoni ta 'tip ta' mudell hashmap bħala vettur ta 'int - Tip pari. F'C++ tkun tidher xi ħaġa bħal din:

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

mela, alpha - keyword! Imma f'C++ biss tista 'tikteb T, imma għandek tikteb alpha, beta... Imma mhux aktar minn 8 parametri, dak huwa fejn tispiċċa l-fantasija. Jidher li darba f’San Pietruburgu saru xi djalogi bħal dawn:

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

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

Iżda dan kien dwar l-ewwel implimentazzjoni ppubblikata ta 'TL "b'mod ġenerali". Ejja ngħaddu biex nikkunsidraw l-implimentazzjonijiet fil-klijenti tat-Telegram infushom.

Kelma lil Vasily:

Vasily, [09.10.18 17:07] Fuq kollox, il-ħmar huwa jaħraq għax ħolqu mazz ta 'estrazzjonijiet, u mbagħad martellaw bolt fuqhom, u koprew il-ġeneratur tal-kodiċi bil-krozzi
Bħala riżultat, l-ewwel minn dock pilot.jpg
Imbagħad mill-kodiċi dzhekichan.webp

Naturalment, minn nies familjari mal-algoritmi u l-matematika, nistgħu nistennew li qraw Aho, Ullmann, u huma familjari mal-għodod li saru standard de facto fl-industrija matul l-għexieren ta’ snin għall-kitba tal-kompilaturi DSL tagħhom, hux?...

Permezz telegramma-cli huwa Vitaly Valtman, kif jista 'jinftiehem mill-okkorrenza tal-format TLO barra mill-konfini (cli) tiegħu, membru tat-tim - issa ġiet allokata librerija għall-parsing TL separatament, x'inhi l-impressjoni tagħha TL parser? ..

16.12 04:18 Vasily: Naħseb li xi ħadd ma ħakmux lex+yacc
16.12 04:18 Vasily: Ma nistax nispjegaha mod ieħor
16.12 04:18 Vasily: sew, jew tħallsu għan-numru ta 'linji f'VK
16.12 04:19 Vasily: 3k+ linji eċċ.<censored> minflok parser

Forsi eċċezzjoni? Ejja naraw kif ma Dan huwa l-klijent UFFIĊJALI - 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+ linja f'Python, koppja ta 'espressjonijiet regolari + każijiet speċjali bħal vettur, li, ovvjament, huwa ddikjarat fl-iskema kif għandu jkun skond is-sintassi TL, iżda qagħdu fuq din is-sintassi biex parseha... Tqum il-mistoqsija, għaliex kien kollu miraklu?иHuwa aktar f'saffi jekk ħadd mhu se janalizzah skont id-dokumentazzjoni xorta waħda?!

Mill-mod... Tiftakar li tkellimna dwar il-kontroll CRC32? Għalhekk, fil-ġeneratur tal-kodiċi Telegram Desktop hemm lista ta 'eċċezzjonijiet għal dawk it-tipi li fihom is-CRC32 ikkalkulat ma taqbilx ma’ dak indikat fid-dijagramma!

Vasily, [18.12/22 49:XNUMX] u hawn naħseb dwar jekk TL bħal dan huwiex meħtieġ
kieku ridt inħass bl-implimentazzjonijiet alternattivi, nibda ndaħħal line breaks, nofs il-parsers jinkisru fuq definizzjonijiet b'ħafna linji
tdesktop, madankollu, ukoll

Ftakar il-punt dwar one-liner, aħna se nerġgħu lura għaliha ftit aktar tard.

Tajjeb, telegram-cli mhux uffiċjali, Telegram Desktop huwa uffiċjali, imma xi ngħidu dwar l-oħrajn? Min jaf?.. Fil-kodiċi tal-klijent Android ma kien hemm l-ebda schema parser (li jqajjem mistoqsijiet dwar sors miftuħ, iżda dan huwa għat-tieni parti), iżda kien hemm diversi biċċiet oħra umoristiċi ta 'kodiċi, iżda aktar fuqhom fil- subtaqsima hawn taħt.

Liema mistoqsijiet oħra tqajjem is-serialization fil-prattika? Pereżempju, huma għamlu ħafna affarijiet, ovvjament, b'oqsma tal-bit u oqsma kondizzjonali:

Vasily: flags.0? true
ifisser li l-field huwa preżenti u huwa ugwali għal veru jekk il-bandiera tkun issettjata

Vasily: flags.1? int
ifisser li l-qasam huwa preżenti u jeħtieġ li jiġi deserialized

Vasily: Ħmar, tinkwetax x'qed tagħmel!
Vasily: Hemm ssemmi x'imkien fid-dokument li veru huwa tip ta' tul żero, iżda huwa impossibbli li tiġbor xi ħaġa mid-dokument tagħhom
Vasily: Fl-implimentazzjonijiet tas-sors miftuħ dan mhux il-każ lanqas, iżda hemm mazz ta 'krozzi u appoġġi

Xi ngħidu dwar Telethon? B'ħarsa 'l quddiem lejn is-suġġett ta' MTProto, eżempju - fid-dokumentazzjoni hemm biċċiet bħal dawn, iżda s-sinjal % hija deskritta biss bħala "li tikkorrispondi għal bare-tip partikolari", i.e. fl-eżempji hawn taħt hemm jew żball jew xi ħaġa mhux dokumentata:

Vasily, [22.06.18 18:38] F'post wieħed:

msg_container#73f1f8dc messages:vector message = MessageContainer;

B'mod differenti:

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

U dawn huma żewġ differenzi kbar, fil-ħajja reali jiġi xi tip ta 'vettur mikxuf

Ma rajtx definizzjoni ta' vettur vojta u ma ltqajtx ma' waħda

L-analiżi hija miktuba bl-idejn f'telethon

Fid-dijagramma tiegħu d-definizzjoni hija kkummentata msg_container

Għal darb'oħra, il-mistoqsija tibqa' madwar %. Mhuwiex deskritt.

Vadim Goncharov, [22.06.18 19:22] u fit-tdesktop?

Vasily, [22.06.18 19:23] Imma l-parser TL tagħhom fuq magni regolari x'aktarx mhux se jiekol dan lanqas

// parsed manually

TL hija astrazzjoni sabiħa, ħadd ma jimplimentaha kompletament

U % mhux fil-verżjoni tagħhom tal-iskema

Imma hawn id-dokumentazzjoni tikkontradixxi lilha nnifisha, allura idk

Instab fil-grammatika, setgħu sempliċement insew jiddeskrivu s-semantika

Rajt id-dokument fuq TL, ma tistax issibha mingħajr nofs litru

"Tajjeb, ejja ngħidu," se jgħid qarrej ieħor, "int tikkritika xi ħaġa, allura urini kif għandha ssir."

Vasily iwieġeb: “Fir-rigward tal-parser, inħobb affarijiet simili

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

b'xi mod bħalu aħjar minn

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

jew

        # 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)

dan huwa l-lexer KOLLHA:

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

dawk. aktar sempliċi huwa li tpoġġiha b’mod ħafif.”

B'mod ġenerali, bħala riżultat, l-parser u l-ġeneratur tal-kodiċi għas-subsett ta' TL attwalment użat jidħlu f'madwar 100 linja ta' grammatika u ~ 300 linja tal-ġeneratur (bl-għadd kollu print's ġenerat tal-kodiċi), inklużi l-informazzjoni tat-tip buns għall-introspezzjoni f'kull klassi. Kull tip polimorfiku jinbidel fi klassi bażi astratta vojta, u l-kostrutturi jirtu minnha u għandhom metodi għal serialization u deserialization.

Nuqqas ta' tipi fil-lingwa tat-tip

Ittajpjar qawwi huwa ħaġa tajba, hux? Le, dan mhuwiex holivar (għalkemm nippreferi lingwi dinamiċi), iżda postulat fil-qafas ta 'TL. Ibbażat fuqha, il-lingwa għandha tipprovdi kull xorta ta 'kontrolli għalina. Ukoll, okay, forsi mhux hu stess, iżda l-implimentazzjoni, iżda għandu mill-inqas jiddeskrivihom. U x’tip ta’ opportunitajiet irridu?

L-ewwelnett, restrizzjonijiet. Hawnhekk naraw fid-dokumentazzjoni għat-tlugħ tal-fajls:

Il-kontenut binarju tal-fajl imbagħad jinqasam f'partijiet. Il-partijiet kollha għandu jkollhom l-istess daqs ( daqs_parti ) u għandhom jiġu sodisfatti l-kundizzjonijiet li ġejjin:

  • part_size % 1024 = 0 (diviżibbli b'1KB)
  • 524288 % part_size = 0 (512KB iridu jkunu diviżibbli b'mod indaqs b'part_size)

L-aħħar parti m'għandhiex għalfejn tissodisfa dawn il-kundizzjonijiet, sakemm id-daqs tagħha jkun inqas minn part_size.

Kull parti għandu jkollha numru ta' sekwenza, file_part, b'valur li jvarja minn 0 sa 2,999.

Wara li l-fajl ikun ġie diviżjonat għandek bżonn tagħżel metodu biex issalvah fuq is-server. Użu upload.saveBigFilePart fil-każ li d-daqs sħiħ tal-fajl ikun aktar minn 10 MB u upload.saveFilePart għal fajls iżgħar.
[…] wieħed mill-iżbalji ta’ input tad-dejta li ġejjin jista’ jintbagħat lura:

  • FILE_PARTS_INVALID — Numru mhux validu ta' partijiet. Il-valur mhuwiex bejn 1..3000

Hemm xi ħaġa minn dan fid-dijagramma? Dan huwa b'xi mod espressibbli bl-użu ta 'TL? Nru. Imma skużani, anke Turbo Pascal tan-nannu kien kapaċi jiddeskrivi t-tipi speċifikati firxiet. U kien jaf ħaġa oħra, issa magħrufa aħjar bħala enum - tip li jikkonsisti f'enumerazzjoni ta' numru fiss (żgħir) ta' valuri. F'lingwi bħal C - numeriku, innota li s'issa tkellimna biss dwar it-tipi numri. Imma hemm ukoll arrays, kordi... per eżempju, ikun sabiħ li tiddeskrivi li din is-sekwenza jista 'jkun fiha biss numru tat-telefon, hux?

Xejn minn dan huwa fit-TL. Iżda hemm, pereżempju, fl-Iskema JSON. U jekk xi ħadd ieħor jista 'jargumenta dwar id-diviżibbiltà ta' 512 KB, li dan għad irid jiġi ċċekkjat fil-kodiċi, imbagħad kun żgur li l-klijent sempliċement ma setgħux ibgħat numru barra mill-firxa 1..3000 (u l-iżball korrispondenti ma setax jinqala') kien ikun possibbli, hux?...

Mill-mod, dwar żbalji u valuri ta 'ritorn. Anke dawk li ħadmu ma 'TL iċċajpar għajnejhom - ma immedjatament bidu fuqna li kull wieħed funzjoni f'TL fil-fatt tista' tirritorna mhux biss it-tip ta 'ritorn deskritt, iżda wkoll żball. Iżda dan ma jistax jiġi dedott bl-ebda mod bl-użu tat-TL innifsu. Naturalment, huwa diġà ċar u m'hemm l-ebda ħtieġa għal xejn fil-prattika (għalkemm fil-fatt, RPC jista 'jsir b'modi differenti, aħna ser nerġgħu lura għal dan aktar tard) - imma xi ngħidu dwar il-Purità tal-kunċetti tal-Matematika tat-Tipi Astratti mid-dinja tas-sema?.. qabadt l-irmonk - allura qabbilha.

U fl-aħħarnett, xi ngħidu dwar il-qari? Ukoll, hemm, b'mod ġenerali, nixtieq deskrizzjoni għandek id-dritt fl-iskema (fl-iskema JSON, għal darb'oħra, huwa), imma jekk int diġà tensjoni magħha, allura xi ngħidu dwar in-naħa prattika - għall-inqas b'mod trivjali tħares lejn diffs waqt l-aġġornamenti? Ara għalik innifsek fuq eżempji reali:

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

jew

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

Jiddependi fuq kulħadd, iżda GitHub, pereżempju, jirrifjuta li jenfasizza bidliet f'linji twal bħal dawn. Il-logħba "ssib 10 differenzi", u dak li l-moħħ jara immedjatament huwa li l-bidu u t-tmiem fiż-żewġ eżempji huma l-istess, għandek bżonn taqra tediously x'imkien fin-nofs... Fl-opinjoni tiegħi, dan mhux biss fit-teorija, iżda purament viżwalment maħmuġ u sloppy.

Mill-mod, dwar il-purità tat-teorija. Għaliex għandna bżonn oqsma bit? Ma jidhirx li huma riħa ħażina mil-lat tat-teorija tat-tip? L-ispjegazzjoni tista 'tidher f'verżjonijiet preċedenti tad-dijagramma. Għall-ewwel, iva, hekk kien, għal kull għatis inħoloq tip ġdid. Dawn ir-rudimenti għadhom jeżistu f'din il-forma, pereżempju:

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;

Imma issa immaġina, jekk għandek 5 oqsma fakultattivi fl-istruttura tiegħek, allura jkollok bżonn 32 tip għall-għażliet kollha possibbli. Splużjoni kombinatorja. Għalhekk, il-purità tal-kristall tat-teorija TL għal darb'oħra għebet kontra l-ħmar tal-ħadid fondut tar-realtà ħarxa tas-serialization.

Barra minn hekk, f'xi postijiet dawn il-guys infushom jiksru t-tipoloġija tagħhom stess. Pereżempju, f'MTProto (kapitolu li jmiss) ir-rispons jista 'jiġi kkompressat minn Gzip, kollox huwa tajjeb - ħlief li s-saffi u ċ-ċirkwit huma miksura. Għal darb'oħra, ma kienx RpcResult innifsu li nħasad, iżda l-kontenut tiegħu. Ukoll, għaliex nagħmel dan? .. Kelli nqatta 'f'krozza sabiex il-kompressjoni taħdem kullimkien.

Jew eżempju ieħor, darba skoprejna żball - intbagħat InputPeerUser minflok InputUser. Jew viċi versa. Imma ħadem! Jiġifieri, is-server ma jimpurtax mit-tip. Kif jista’ jkun dan? It-tweġiba tista 'tingħatalna minn frammenti ta' kodiċi minn 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);

Fi kliem ieħor, dan huwa fejn isir is-serialization MANUALMENT, mhux ġenerat kodiċi! Forsi s-server huwa implimentat b'mod simili?.. Fil-prinċipju, dan jaħdem jekk isir darba, imma kif jista 'jiġi appoġġjat aktar tard waqt l-aġġornamenti? Huwa għalhekk li l-iskema ġiet ivvintata? U hawn ngħaddu għall-mistoqsija li jmiss.

Verżjoni. Saffi

Għaliex il-verżjonijiet skematiċi jissejħu saffi jistgħu jiġu spekulati biss ibbażati fuq l-istorja ta 'skematiċi ppubblikati. Apparentement, għall-ewwel l-awturi ħasbu li l-affarijiet bażiċi jistgħu jsiru bl-użu tal-iskema mhux mibdula, u fejn meħtieġ biss, għal talbiet speċifiċi, jindikaw li kienu qed isiru bl-użu ta 'verżjoni differenti. Fil-prinċipju, anke idea tajba - u l-ġdida se tkun, bħallikieku, "imħallta", f'saffi fuq l-antik. Imma ejja naraw kif sar. Veru, ma kontx kapaċi nħares lejha mill-bidu nett - huwa umoristiku, iżda d-dijagramma tas-saff bażi sempliċement ma teżistix. Saffi bdew bi 2. Id-dokumentazzjoni tgħidilna dwar karatteristika speċjali TL:

Jekk klijent jappoġġja Saff 2, allura għandu jintuża l-kostruttur li ġej:

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

Fil-prattika, dan ifisser li qabel kull sejħa API, int bil-valur 0x289dd1f6 għandhom jiġu miżjuda qabel in-numru tal-metodu.

Ħsejjes normali. Imma x’ġara wara? Imbagħad deher

invokeWithLayer3#b7475268 query:!X = X;

Allura x'inhu jmiss? Kif tista' taħżen,

invokeWithLayer4#dea0d430 query:!X = X;

Umoristiċi? Le, għadu kmieni biex tidħaq, aħseb dwar il-fatt li kull waħda talba minn saff ieħor jeħtieġ li tkun imgeżwer f'tip speċjali bħal dan - jekk huma kollha differenti għalik, kif inkella tista 'tiddistingwihom? U żżid biss 4 bytes quddiem huwa metodu pjuttost effiċjenti. Allura,

invokeWithLayer5#417a57ae query:!X = X;

Iżda huwa ovvju li wara ftit dan se jsir xi tip ta 'baccanalia. U waslet is-soluzzjoni:

Aġġornament: Nibda bis-Saff 9, metodi helper invokeWithLayerN jistgħu jintużaw biss flimkien ma initConnection

Ħura! Wara 9 verżjonijiet, fl-aħħar wasalna għal dak li sar fil-protokolli tal-Internet lura fis-snin 80 - qbilna dwar il-verżjoni darba fil-bidu tal-konnessjoni!

Allura x'inhu jmiss? ..

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

Imma issa xorta tista tidħaq. Wara 9 saffi oħra biss, fl-aħħar ġie miżjud kostruttur universali b'numru tal-verżjoni, li jeħtieġ li jissejjaħ darba biss fil-bidu tal-konnessjoni, u t-tifsira tas-saffi dehret li sparixxa, issa hija biss verżjoni kondizzjonali, bħal kullimkien ieħor. Problema solvuta.

Eżattament?..

Vasily, [16.07.18 14:01] Anke nhar il-Ġimgħa ħsibt:
It-teleserver jibgħat avvenimenti mingħajr talba. It-talbiet għandhom ikunu mgeżwra f'InvokeWithLayer. Is-server ma jgħaqqadx l-aġġornamenti; m'hemm l-ebda struttura għat-tgeżwir tar-risponsi u l-aġġornamenti.

Dawk. il-klijent ma jistax jispeċifika s-saff li fih irid aġġornamenti

Vadim Goncharov, [16.07.18 14:02] mhux InvokeWithLayer crutch fil-prinċipju?

Vasily, [16.07.18 14:02] Dan huwa l-uniku mod

Vadim Goncharov, [16.07.18 14:02] li essenzjalment għandu jfisser qbil dwar is-saff fil-bidu tas-sessjoni

Mill-mod, isegwi li downgrade tal-klijent mhux ipprovdut

Aġġornamenti, i.e. tip Updates fl-iskema, dan huwa dak li s-server jibgħat lill-klijent mhux bi tweġiba għal talba API, iżda b'mod indipendenti meta jseħħ avveniment. Dan huwa suġġett kumpless li se jiġi diskuss f'post ieħor, iżda għalissa huwa importanti li tkun taf li s-server jiffranka l-Aġġornamenti anke meta l-klijent ikun offline.

Għalhekk, jekk inti tirrifjuta li wrap ta 'kull wieħed pakkett biex jindika l-verżjoni tiegħu, dan loġikament iwassal għall-problemi possibbli li ġejjin:

  • is-server jibgħat aġġornamenti lill-klijent anki qabel ma l-klijent ikun informa liema verżjoni jappoġġja
  • x'għandi nagħmel wara li ntejjeb il-klijent?
  • min garanzijili l-opinjoni tas-server dwar in-numru tas-saff mhux se tinbidel matul il-proċess?

Taħseb li din hija spekulazzjoni purament teoretika, u fil-prattika dan ma jistax iseħħ, minħabba li s-server huwa miktub b'mod korrett (għall-inqas, huwa ttestjat tajjeb)? Ha! Ma jimpurtax kif ikun!

Dan huwa eżattament dak li ltqajna miegħu f’Awwissu. Fl-14 ta’ Awwissu, kien hemm messaġġi li xi ħaġa kienet qed tiġi aġġornata fuq is-servers tat-Telegram... u mbagħad fil-logs:

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.

u mbagħad diversi megabytes ta 'traċċi ta' munzell (ukoll, fl-istess ħin il-qtugħ ġie ffissat). Wara kollox, jekk xi ħaġa mhix rikonoxxuta fit-TL tiegħek, hija binarja bil-firma, aktar 'l isfel fil-linja KOLLHA tmur, id-dekodifikazzjoni se ssir impossibbli. X'għandek tagħmel f'sitwazzjoni bħal din?

Ukoll, l-ewwel ħaġa li tiġi f'moħħu kulħadd hija li skonnettja u erġa' pprova. Ma għenitx. Aħna google CRC32 - dawn irriżultaw li huma oġġetti mill-iskema 73, għalkemm ħdimna fuq 82. Inħarsu bir-reqqa lejn il-logs - hemm identifikaturi minn żewġ skemi differenti!

Forsi l-problema hija purament fil-klijent mhux uffiċjali tagħna? Le, inniedu Telegram Desktop 1.2.17 (verżjoni pprovduta f'numru ta' distribuzzjonijiet tal-Linux), jikteb fil-log Eċċezzjoni: MTP Id-tip mhux mistenni #b5223b0f aqra f'MTPMessageMedia...

Kritika tal-protokoll u l-approċċi organizzattivi ta 'Telegram. Parti 1, teknika: esperjenza ta 'kitba ta' klijent mill-bidu - TL, MT

Google wera li problema simili kienet diġà ġrat lil wieħed mill-klijenti mhux uffiċjali, iżda mbagħad in-numri tal-verżjoni u, għaldaqstant, is-suppożizzjonijiet kienu differenti...

Allura x'għandna nagħmlu? Jien u Vasily infirdu: ipprova jaġġorna ċ-ċirkwit għal 91, iddeċidejt li nistenna ftit jiem u nipprova 73. Iż-żewġ metodi ħadmu, iżda peress li huma empiriċi, m'hemm l-ebda fehim ta 'kemm verżjonijiet 'il fuq jew 'l isfel għandek bżonn biex taqbeż, jew kemm għandek bżonn tistenna.

Aktar tard stajt nirriproduċi s-sitwazzjoni: inniedu l-klijent, itfih, nikkompilaw mill-ġdid iċ-ċirkwit għal saff ieħor, nibdew mill-ġdid, nerġgħu naqbdu l-problema, nerġgħu lura għal dik ta 'qabel - oops, l-ebda ammont ta' bidla taċ-ċirkwit u l-klijent jerġa 'jibda għal ftit minuti se jgħinu. Inti ser tirċievi taħlita ta 'strutturi tad-dejta minn saffi differenti.

Spjegazzjoni? Kif tistgħu taħsbu minn diversi sintomi indiretti, is-server jikkonsisti f'ħafna proċessi ta 'tipi differenti fuq magni differenti. Probabbilment, is-server li huwa responsabbli għall-"buffering" poġġa fil-kju dak li tah is-superjuri tiegħu, u tawh fl-iskema li kienet fis-seħħ fiż-żmien tal-ġenerazzjoni. U sakemm dan il-kju "immuffat", xejn ma seta' jsir dwarha.

Forsi... imma din hija crutch terribbli?!.. Le, qabel ma naħsbu dwar ideat tal-ġenn, ejja nħarsu lejn il-kodiċi tal-klijenti uffiċjali. Fil-verżjoni Android ma nsibu l-ebda parser TL, iżda nsibu fajl qawwi (GitHub jirrifjuta li jmissu) b'(de)serialization. Hawn huma s-snippets tal-kodiċi:

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;

jew

    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... jidher selvaġġ. Iżda, probabbilment, dan huwa kodiċi ġġenerat, allura okay? .. Imma ċertament jappoġġja l-verżjonijiet kollha! Veru, mhuwiex ċar għaliex kollox huwa mħallat flimkien, chats sigrieti, u kull xorta ta ' _old7 b'xi mod ma jidhrux qishom ġenerazzjoni tal-magni... Madankollu, fuq kollox jien kont minfuħa

TL_message_layer104
TL_message_layer104_2
TL_message_layer104_3

Guys, lanqas tista’ tiddeċiedi x’hemm ġewwa saff wieħed?! Ukoll, okay, ejja ngħidu li "tnejn" ġew rilaxxati bi żball, ukoll, jiġri, iżda TLIET? .. Minnufih, l-istess rake mill-ġdid? X'tip ta' pornografija hija din, skużani?...

Fil-kodiċi tas-sors ta 'Telegram Desktop, mill-mod, tiġri ħaġa simili - jekk iva, diversi impenji wara xulxin għall-iskema ma jbiddlux in-numru tas-saff tiegħu, iżda jiffissaw xi ħaġa. F'kundizzjonijiet fejn m'hemm l-ebda sors uffiċjali ta' data għall-iskema, minn fejn tista' tinkiseb, ħlief għall-kodiċi tas-sors tal-klijent uffiċjali? U jekk teħodha minn hemm, ma tistax tkun ċert li l-iskema hija kompletament korretta sakemm tittestja l-metodi kollha.

Kif jista 'anke dan jiġi ttestjat? Nittama li l-partitarji tat-testijiet unitarji, funzjonali u oħrajn se jaqsmu l-kummenti.

Tajjeb, ejja nħarsu lejn biċċa kodiċi oħra:

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;

Dan il-kumment "maħluq manwalment" jissuġġerixxi li parti biss minn dan il-fajl inkiteb manwalment (tista 'timmaġina l-ħmar il-lejl kollu tal-manutenzjoni?), U l-bqija kien iġġenerat mill-magni. Madankollu, imbagħad tqum mistoqsija oħra - li s-sorsi huma disponibbli mhux kompletament (a la GPL blobs fil-kernel Linux), iżda dan diġà huwa suġġett għat-tieni parti.

Imma biżżejjed. Ejja ngħaddu għall-protokoll li fuqu taħdem din is-serialization kollha.

MT Proto

Mela, ejja niftħu deskrizzjoni ġenerali и deskrizzjoni dettaljata tal-protokoll u l-ewwel ħaġa li nitfixklu hija t-terminoloġija. U b’abbundanza ta’ kollox. B'mod ġenerali, din tidher li hija karatteristika proprjetarja ta' Telegram - issejjaħ affarijiet differenti f'postijiet differenti, jew affarijiet differenti b'kelma waħda, jew viċi versa (per eżempju, f'API ta 'livell għoli, jekk tara pakkett ta' stikers, mhuwiex dak li ħsibt).

Per eżempju, "messaġġ" u "sessjoni" tfisser xi ħaġa differenti hawnhekk milli fl-interface tal-klijent tas-soltu Telegram. Ukoll, kollox huwa ċar bil-messaġġ, jista 'jiġi interpretat f'termini OOP, jew sempliċement imsejjaħ il-kelma "pakkett" - dan huwa livell baxx ta' trasport, m'hemmx l-istess messaġġi bħal fl-interface, hemm ħafna messaġġi ta 'servizz . Imma s-sessjoni... imma l-ewwelnett.

saff tat-trasport

L-ewwel ħaġa hija t-trasport. Huma jgħidulna dwar 5 għażliet:

  • TCP
  • Websocket
  • Websocket fuq HTTPS
  • HTTP
  • HTTPS

Vasily, [15.06.18 15:04] Hemm ukoll trasport UDP, iżda mhux dokumentat

U TCP fi tliet varjanti

L-ewwel wieħed huwa simili għal UDP fuq TCP, kull pakkett jinkludi numru ta 'sekwenza u crc
Għaliex il-qari ta’ dokumenti fuq karrettun huwa daqshekk bl-uġigħ?

Ukoll, hemm issa TCP diġà f'4 varjanti:

  • Imbiegħed
  • Intermedju
  • Intermedju kkuttunat
  • Sħiħ

Ukoll, ok, Padded intermedju għal MTProxy, dan ġie miżjud aktar tard minħabba avvenimenti magħrufa. Imma għaliex żewġ verżjonijiet oħra (tlieta b’kollox) meta tista’ tgħaddi b’waħda? L-erbgħa essenzjalment huma differenti biss fil-mod kif jiġu stabbiliti t-tul u t-tagħbija tal-MTProto prinċipali, li se jiġu diskussi aktar:

  • fi Imqassar huwa 1 jew 4 bytes, iżda mhux 0xef, allura l-korp
  • f'Intermedju dan huwa 4 bytes ta 'tul u qasam, u l-ewwel darba li l-klijent irid jibgħat 0xeeeeeeee biex jindika li huwa Intermedju
  • B'mod sħiħ l-aktar vizzju, mil-lat ta 'networker: tul, numru ta' sekwenza, u MHUX DAK li huwa prinċipalment MTProto, korp, CRC32. Iva, dan kollu huwa fuq TCP. Li jipprovdilna trasport affidabbli fil-forma ta 'fluss ta' byte sekwenzjali; m'hemmx bżonn ta 'sekwenzi, speċjalment checksums. Tajjeb, issa xi ħadd se joġġezzjona għalija li TCP għandu checksum ta' 16-il bit, għalhekk isseħħ korruzzjoni tad-dejta. Kbir, iżda fil-fatt għandna protokoll kriptografiku b'hashes itwal minn 16 bytes, dawn l-iżbalji kollha - u saħansitra aktar - se jinqabdu minn nuqqas ta 'qbil SHA f'livell ogħla. M'hemm l-EBDA punt f'CRC32 fuq dan.

Ejja nqabblu Imqassar, li fih byte wieħed ta 'tul huwa possibbli, ma' Intermedju, li jiġġustifika "Fil-każ li jkun meħtieġ allinjament tad-dejta ta '4 byte," li huwa pjuttost nonsense. X'inhuma, huwa maħsub li l-programmaturi Telegram huma tant inkompetenti li ma jistgħux jaqraw data minn socket f'buffer allinjat? Xorta trid tagħmel dan, għax il-qari jista' jirritornalek kull numru ta' bytes (u hemm ukoll proxy servers, pereżempju...). Jew min-naħa l-oħra, għaliex jimblokka Imqassar jekk għad ikollna padding qawwi fuq 16-il byte - ħlief 3 bytes kultant ?

Wieħed jieħu l-impressjoni li Nikolai Durov verament iħobb jivvinta r-roti, inklużi protokolli tan-netwerk, mingħajr ebda ħtieġa prattika reali.

Għażliet oħra tat-trasport, inkl. Web u MTProxy, mhux se nikkunsidraw issa, forsi f'post ieħor, jekk ikun hemm talba. Dwar dan l-istess MTProxy, ejjew niftakru biss issa li ftit wara li ħareġ fl-2018, il-fornituri malajr tgħallmu jimblukkawha, maħsuba għal imblukkar tal-bypassskond daqs tal-pakkett! U wkoll il-fatt li s-server MTProxy miktub (għal darb'oħra minn Waltman) f'C kien marbut iżżejjed mal-ispeċifiċitajiet tal-Linux, għalkemm dan ma kienx meħtieġ xejn (Phil Kulin se jikkonferma), u li server simili jew f'Go jew Node.js kien se tajbin f'inqas minn mitt linja.

Imma se nieħdu konklużjonijiet dwar il-litteriżmu tekniku ta’ dawn in-nies fl-aħħar tat-taqsima, wara li nikkunsidraw kwistjonijiet oħra. Għalissa, ejja ngħaddu għal saff OSI 5, sessjoni - li fuqha poġġew is-sessjoni MTProto.

Ċwievet, messaġġi, sessjonijiet, Diffie-Hellman

Poġġewh hemm mhux kompletament korrett... Sessjoni mhix l-istess sessjoni li tidher fl-interface taħt Sessjonijiet Attivi. Imma fl-ordni.

Kritika tal-protokoll u l-approċċi organizzattivi ta 'Telegram. Parti 1, teknika: esperjenza ta 'kitba ta' klijent mill-bidu - TL, MT

Allura rċevejna string byte ta 'tul magħruf mis-saff tat-trasport. Dan huwa jew messaġġ kriptat jew sempliċi - jekk għadna fl-istadju tal-ftehim ewlieni u fil-fatt qed nagħmluh. Liema mill-mazz ta 'kunċetti msejħa "ċavetta" qed nitkellmu? Ejja niċċaraw din il-kwistjoni għat-tim tat-Telegram innifsu (niskuża ruħi li ttradujt id-dokumentazzjoni tiegħi mill-Ingliż b'moħħ għajjien fl-4 am, kien aktar faċli li nħalli xi frażijiet kif inhuma):

Hemm żewġ entitajiet imsejħa sessjoni - wieħed fl-IU tal-klijenti uffiċjali taħt "sessjonijiet kurrenti", fejn kull sessjoni tikkorrispondi għal apparat / OS kollu.
It-tieni huwa Sessjoni MTProto, li fiha n-numru tas-sekwenza tal-messaġġ (f'sens ta' livell baxx), u liema jista' jdum bejn konnessjonijiet TCP differenti. Jistgħu jiġu installati diversi sessjonijiet MTProto fl-istess ħin, pereżempju, biex jitħaffef it-tniżżil tal-fajls.

Bejn dawn it-tnejn sessjonijiet hemm kunċett awtorizzazzjoni. Fil-każ deġenerat, nistgħu ngħidu li Sessjoni UI huwa l-istess bħal awtorizzazzjoni, imma sfortunatament, kollox huwa kkumplikat. Ejja nħarsu:

  • L-utent fuq l-apparat il-ġdid l-ewwel jiġġenera aw_key u jorbotha biex tagħti kont, pereżempju permezz ta’ SMS - hu għalhekk li awtorizzazzjoni
  • Ġara ġewwa l-ewwel Sessjoni MTProto, li għandha session_id ġewwa lilek innifsek.
  • F'dan il-pass, il-kombinazzjoni awtorizzazzjoni и session_id jista' jissejjaħ eżempju - din il-kelma tidher fid-dokumentazzjoni u l-kodiċi ta’ xi klijenti
  • Imbagħad, il-klijent jista 'jinfetaħ xi Sessjonijiet MTProto taħt l-istess aw_key - lill-istess DC.
  • Imbagħad, jum wieħed il-klijent ikollu jitlob il-fajl minn DC ieħor - u għal din id-DC se tiġi ġġenerata waħda ġdida aw_key !
  • Biex tinforma lis-sistema li mhux utent ġdid li qed jirreġistra, iżda l-istess awtorizzazzjoni (Sessjoni UI), il-klijent juża sejħiet API auth.exportAuthorization fid-dar DC auth.importAuthorization fid-DC il-ġdid.
  • Kollox huwa l-istess, bosta jistgħu jkunu miftuħa Sessjonijiet MTProto (kull wieħed tiegħu session_id) lil din id-DC ġdida, taħt tiegħu aw_key.
  • Fl-aħħarnett, il-klijent jista 'jixtieq Perfect Forward Segrecy. Kull aw_key kien permanenti ċavetta - għal kull DC - u l-klijent jista 'jsejjaħ auth.bindTempAuthKey għall-użu temporanju aw_key - u għal darb'oħra, wieħed biss temp_auth_key għal kull DC, komuni għal kulħadd Sessjonijiet MTProto lil dan DC.

Innota li melħ (u melħ futur) huwa wkoll wieħed fuq aw_key dawk. maqsuma bejn kulħadd Sessjonijiet MTProto lill-istess DC.

Xi jfisser "bejn konnessjonijiet TCP differenti"? Allura dan ifisser xi ħaġa simili cookie ta 'awtorizzazzjoni fuq websajt - tippersisti (jgħix) ħafna konnessjonijiet TCP ma' server partikolari, iżda xi darba tmur ħażin. B'differenza mill-HTTP biss, f'MTProto messaġġi f'sessjoni huma nnumerati u kkonfermati b'mod sekwenzjali; jekk daħlu fil-mina, il-konnessjoni kienet miksura - wara li stabbiliet konnessjoni ġdida, is-server ġentilment jibgħat dak kollu f'din is-sessjoni li ma wassalx fis-sessjoni preċedenti. Konnessjoni TCP.

Madankollu, l-informazzjoni t'hawn fuq hija miġbura fil-qosor wara ħafna xhur ta 'investigazzjoni. Sadanittant, qed nimplimentaw il-klijent tagħna mill-bidu? - ejja mmorru lura għall-bidu.

Mela ejja niġġeneraw auth_key fuq Verżjonijiet Diffie-Hellman minn Telegram. Ejja nippruvaw nifhmu d-dokumentazzjoni...

Vasily, [19.06.18 20:05] data_with_hash := SHA1(data) + data + (kwalunkwe bytes każwali); tali li t-tul ikun ugwali għal 255 bytes;
encrypted_data := RSA(data_with_hash, server_public_key); numru twil ta '255 byte (big endian) jittella' għall-qawwa meħtieġa fuq il-modulus meħtieġ, u r-riżultat jinħażen bħala numru ta' 256 byte.

Għandhom xi dope DH

Ma tidhirx DH ta' persuna b'saħħitha
M'hemm l-ebda żewġ ċwievet pubbliċi f'dx

Ukoll, fl-aħħar dan ġie riżolt, iżda baqa 'fdal - prova ta' xogħol issir mill-klijent li kien kapaċi jiffattura n-numru. Tip ta' protezzjoni kontra attakki DoS. U ċ-ċavetta RSA tintuża darba biss f'direzzjoni waħda, essenzjalment għall-kriptaġġ new_nonce. Iżda filwaqt li din l-operazzjoni li tidher sempliċi se tirnexxi, x'ser ikollok tiffaċċja?

Vasily, [20.06.18/00/26 XNUMX:XNUMX] Għadni ma wasaltx għat-talba appid

Bgħatt din it-talba lil DH

U, fil-baċir tat-trasport jgħid li jista 'jirrispondi b'4 bytes ta' kodiċi ta 'żball. Dak kollox

Ukoll, qalli -404, allura xiex?

Allura għedtlu: "Aqbad il-bullshit tiegħek encrypted b'ċavetta tas-server b'marki tas-swaba' bħal din, irrid DH," u wieġbet b'404 stupidu.

X'taħseb dwar din ir-rispons tas-server? X'tagħmel? M'hemm ħadd min jistaqsi (iżda aktar dwar dan fit-tieni parti).

Hawnhekk l-interess kollu jsir fuq il-baċir

M'għandi xejn x'nagħmel, biss ħlomt li nikkonverti n-numri 'l quddiem u lura

Żewġ numri 32 bit. Ippakkjathom bħal kulħadd

Imma le, dawn it-tnejn jeħtieġ li jiżdiedu mal-linja l-ewwel bħala BE

Vadim Goncharov, [20.06.18 15:49] u minħabba dan 404?

Vasily, [20.06.18 15:49] IVA!

Vadim Goncharov, [20.06.18 15:50] allura ma nifhimx x'jista '"ma sabx"

Vasily, [20.06.18 15:50] approssimattivament

Ma stajtx insib tali dekompożizzjoni f'fatturi ewlenin%)

Lanqas mmexxija r-rappurtar tal-iżbalji

Vasily, [20.06.18 20:18] Oh, hemm ukoll MD5. Diġà tliet hashes differenti

Il-marki tas-swaba' ewlenin hija kkalkulata kif ġej:

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

SHA1 u sha2

Mela ejja npoġġuha auth_key irċevejna 2048 bit fid-daqs bl-użu Diffie-Hellman. X'inhu jmiss? Sussegwentement niskopru li l-1024 bits aktar baxxi ta 'din iċ-ċavetta ma jintużaw bl-ebda mod... iżda ejja naħsbu dwar dan għalissa. F'dan il-pass, għandna sigriet kondiviż mas-server. Ġie stabbilit analogu tas-sessjoni TLS, li hija proċedura għalja ħafna. Imma s-server għadu ma jaf xejn dwar min aħna! Għadha mhux, fil-fatt. awtorizzazzjoni. Dawk. jekk ħsibt f'termini ta '"login-password", kif darba għamilt f'ICQ, jew għall-inqas "login-key", bħal f'SSH (per eżempju, fuq xi gitlab/github). Irċevejna waħda anonima. X'jiġri jekk is-server jgħidilna "dawn in-numri tat-telefon jingħataw servizz minn DC ieħor"? Jew saħansitra "in-numru tat-telefon tiegħek huwa pprojbit"? L-aħjar li nistgħu nagħmlu hu li nżommu ċ-ċavetta bit-tama li tkun utli u sa dak iż-żmien ma titħassarx.

Mill-mod, aħna "rċevejna" b'riżervi. Per eżempju, aħna nafdaw is-server? X'jiġri jekk huwa falz? Ikunu meħtieġa kontrolli kriptografiċi:

Vasily, [21.06.18 17:53] Huma joffru lill-klijenti mobbli biex jiċċekkjaw numru 2kbit għall-primalità%)

Imma mhu ċar xejn, nafeijoa

Vasily, [21.06.18 18:02] Id-dokument ma jgħidx x'għandek tagħmel jekk jirriżulta li mhux sempliċi

Mhux qal. Ejja naraw x'jagħmel il-klijent Android uffiċjali f'dan il-każ? A dak hu (u iva, il-fajl kollu huwa interessanti) - kif jgħidu, jien ser inħalli dan hawn:

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

Le, ovvjament għadu hemm xi wħud Hemm testijiet għall-primalità ta 'numru, imma personalment m'għadx għandi biżżejjed għarfien tal-matematika.

Okay, aħna ltqajna ċ-ċavetta prinċipali. Biex tidħol, i.e. tibgħat talbiet, għandek bżonn twettaq aktar encryption, billi tuża AES.

Iċ-ċavetta tal-messaġġ hija definita bħala l-128 bit tan-nofs tas-SHA256 tal-korp tal-messaġġ (inkluża sessjoni, ID tal-messaġġ, eċċ.), inklużi l-bytes tal-ikkuttunar, imqabbda minn 32 bytes meħuda mill-muftieħ tal-awtorizzazzjoni.

Vasily, [22.06.18 14:08] Medja, kelba, bits

Riċevuti auth_key. Kollha. Lil hinn minnhom... mhux ċar mid-dokument. Ħossok liberu li tistudja l-kodiċi open source.

Innota li MTProto 2.0 jeħtieġ minn 12 sa 1024 bytes ta 'ikkuttunar, xorta suġġett għall-kundizzjoni li t-tul tal-messaġġ li jirriżulta jkun diviżibbli b'16-il byte.

Allura kemm ikkuttunar għandek iżżid?

U iva, hemm ukoll 404 f'każ ta 'żball

Jekk xi ħadd studja bir-reqqa d-dijagramma u t-test tad-dokumentazzjoni, innutaw li hemm l-ebda MAC. U dak l-AES jintuża f'ċertu mod IGE li ma jintuża imkien ieħor. Huma, ovvjament, jiktbu dwar dan fil-FAQ tagħhom... Hawnhekk, bħal, iċ-ċavetta tal-messaġġ nnifisha hija wkoll il-hash SHA tad-dejta decrypted, użata biex tiċċekkja l-integrità - u f'każ ta 'nuqqas ta' qbil, id-dokumentazzjoni għal xi raġuni jirrakkomanda li tinjorahom fis-skiet (imma xi ngħidu dwar is-sigurtà, x'jiġri jekk ikissruna?).

Jien mhux kriptografu, forsi m'hemm xejn ħażin f'dan il-mod f'dan il-każ mil-lat teoretiku. Imma nista' nsemmi b'mod ċar problema prattika, billi nuża Telegram Desktop bħala eżempju. Jikkodifika l-cache lokali (dawn kollha D877F783D5D3EF8C) bl-istess mod bħall-messaġġi f'MTProto (biss f'dan il-każ verżjoni 1.0), i.e. l-ewwel iċ-ċavetta tal-messaġġ, imbagħad id-dejta nnifisha (u x'imkien imwarrba l-kbar prinċipali auth_key 256 bytes, li mingħajrhom msg_key inutli). Għalhekk, il-problema ssir notevoli fuq fajls kbar. Jiġifieri, għandek bżonn iżżomm żewġ kopji tad-data - encrypted u decrypted. U jekk hemm megabytes, jew streaming video, pereżempju?.. Skemi klassiċi b'MAC wara l-ciphertext jippermettulek taqraha stream, immedjatament tittrażmettiha. Imma b'MTProto ikollok għall-ewwel encrypt jew decrypt il-messaġġ kollu, biss imbagħad ittrasferih għan-netwerk jew fuq disk. Għalhekk, fl-aħħar verżjonijiet ta 'Telegram Desktop fil-cache in user_data Jintuża wkoll format ieħor - b'AES fil-mod CTR.

Vasily, [21.06.18 01:27] Oh, sibt x'inhu IGE: IGE kien l-ewwel tentattiv ta '"modalità ta' encryption ta 'awtentikazzjoni", oriġinarjament għal Kerberos. Kien tentattiv fallut (ma jipprovdix protezzjoni tal-integrità), u kellu jitneħħa. Dak kien il-bidu ta 'tfittxija ta' 20 sena għal mod ta 'kriptaġġ ta' awtentikazzjoni li jaħdem, li reċentement laħaq il-qofol tiegħu f'modi bħal OCB u GCM.

U issa l-argumenti min-naħa tal-karrettun:

It-tim wara Telegram, immexxi minn Nikolai Durov, jikkonsisti minn sitt champions ACM, nofshom Ph.Ds fil-matematika. Ħaduhom madwar sentejn biex joħorġu l-verżjoni attwali ta 'MTProto.

That's umoristiċi. Sentejn fil-livell aktar baxx

Jew tista 'sempliċement tieħu tls

Tajjeb, ejja ngħidu li għamilna l-encryption u sfumaturi oħra. Huwa fl-aħħar possibbli li jintbagħtu talbiet serialized f'TL u deserialize-tweġibiet? Allura dak u kif għandek tibgħat? Hawnhekk, ejja ngħidu, il-metodu initConnection, forsi dan hu?

Vasily, [25.06.18 18:46] Inizjalizza l-konnessjoni u tissejvja l-informazzjoni fuq it-tagħmir u l-applikazzjoni tal-utent.

Jaċċetta app_id, device_model, system_version, app_version u lang_code.

U xi mistoqsija

Dokumentazzjoni bħal dejjem. Ħossok liberu li tistudja s-sors miftuħ

Jekk kollox kien bejn wieħed u ieħor ċar b'invokeWithLayer, allura x'hemm ħażin hawn? Jirriżulta, ejja ngħidu li għandna - il-klijent diġà kellu xi ħaġa dwar xiex jistaqsi lis-server - hemm talba li ridna nibagħtu:

Vasily, [25.06.18 19:13] Ġġudikati mill-kodiċi, l-ewwel sejħa hija mgeżwra f'dan il-ħażin, u l-ħażin innifsu huwa mgeżwer f'invokewithlayer

Għaliex initConnection ma setgħetx tkun sejħa separata, iżda trid tkun tgeżwir? Iva, kif irriżulta, għandu jsir kull darba fil-bidu ta 'kull sessjoni, u mhux darba, bħal ma ċ-ċavetta prinċipali. Imma! Ma jistax jissejjaħ minn utent mhux awtorizzat! Issa wasalna fl-istadju fejn huwa applikabbli Dan wieħed paġna tad-dokumentazzjoni - u tgħidilna li...

Porzjon żgħir biss tal-metodi API huma disponibbli għal utenti mhux awtorizzati:

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

L-ewwel wieħed minnhom, auth.sendCode, u hemm dik l-ewwel talba għażiża li fiha nibagħtu api_id u api_hash, u wara nirċievu SMS b'kodiċi. U jekk inkunu f'DC ħażin (in-numri tat-telefon f'dan il-pajjiż huma moqdija minn ieħor, pereżempju), allura nirċievu żball bin-numru tad-DC mixtieq. Biex issir taf liema indirizz IP b'numru DC għandek bżonn tikkonnettja miegħu, għinna help.getConfig. F'ħin wieħed kien hemm biss 5 entrati, iżda wara l-avvenimenti famużi tal-2018, in-numru żdied b'mod sinifikanti.

Issa ejja niftakru li wasalna għal dan l-istadju fuq is-server b'mod anonimu. Mhux għali wisq biex tikseb biss indirizz IP? Għaliex ma tagħmilx dan, u operazzjonijiet oħra, fil-parti mhux kriptata ta 'MTProto? Nisma l-oġġezzjoni: "kif nistgħu niżguraw li mhux RKN li se jwieġeb b'indirizzi foloz?" Għal dan niftakru li, b'mod ġenerali, klijenti uffiċjali Iċ-ċwievet RSA huma inkorporati, i.e. tista 'biss sinjal din l-informazzjoni. Fil-fatt, dan diġà qed isir għal informazzjoni dwar l-imblukkar ta' bypass li l-klijenti jirċievu permezz ta 'kanali oħra (loġikament, dan ma jistax isir f'MTProto innifsu; trid tkun taf ukoll fejn tikkonnettja).

KOLLOX SEW. F'dan l-istadju tal-awtorizzazzjoni tal-klijent, għadna m'aħniex awtorizzati u ma rreġistrajniex l-applikazzjoni tagħna. Irridu biss naraw għalissa x'jirrispondi s-server għal metodi disponibbli għal utent mhux awtorizzat. U hawn...

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;

Fl-iskema, l-ewwel jiġi t-tieni

Fl-iskema tdesktop it-tielet valur huwa

Iva, minn dakinhar, ovvjament, id-dokumentazzjoni ġiet aġġornata. Għalkemm dalwaqt jista’ jerġa’ jsir irrilevanti. Kif għandu jkun jaf żviluppatur novizzi? Forsi jekk tirreġistra l-applikazzjoni tiegħek, jinfurmak? Vasily għamel dan, iżda sfortunatament, ma bagħtulu xejn (għal darb'oħra, nitkellmu dwar dan fit-tieni parti).

...Innutajt li diġà mxejna b'xi mod għall-API, i.e. għal-livell li jmiss, u qbiżt xi ħaġa fis-suġġett MTProto? Ebda sorpriża:

Vasily, [28.06.18 02:04] Mm, qed jaħarqu xi wħud mill-algoritmi fuq e2e

Mtproto jiddefinixxi l-algoritmi tal-kriptaġġ u ċ-ċwievet għaż-żewġ oqsma, kif ukoll daqsxejn ta 'struttura ta' tgeżwir

Iżda kontinwament iħalltu livelli differenti tal-munzell, għalhekk mhux dejjem ikun ċar fejn spiċċa mtproto u beda l-livell li jmiss

Kif jitħalltu? Ukoll, hawn l-istess ċavetta temporanja għal PFS, pereżempju (mill-mod, Telegram Desktop ma jistax jagħmel dan). Huwa esegwit minn talba API auth.bindTempAuthKey, i.e. mill-ogħla livell. Iżda fl-istess ħin tinterferixxi mal-kriptaġġ fil-livell aktar baxx - wara, pereżempju, trid terġa 'tagħmel initConnection eċċ, dan mhux biss talba normali. X'inhu wkoll speċjali huwa li jista 'jkollok biss ċavetta temporanja WAĦDA għal kull DC, għalkemm il-qasam auth_key_id f'kull messaġġ jippermettilek li tibdel iċ-ċavetta mill-inqas kull messaġġ, u li s-server għandu d-dritt li "jinsa" iċ-ċavetta temporanja fi kwalunkwe ħin - id-dokumentazzjoni ma tgħidx x'għandek tagħmel f'dan il-każ... ukoll, għaliex setgħet m'għandekx diversi ċwievet, bħal ma' sett ta' mluħa futuri, u?...

Hemm ftit affarijiet oħra ta 'min jinnota dwar it-tema MTProto.

Messaġġi tal-messaġġi, msg_id, msg_seqno, konfermi, pings fid-direzzjoni żbaljata u idjosinkrażi oħra

Għaliex għandek bżonn tkun taf dwarhom? Minħabba li "jnixxu" għal livell ogħla, u trid tkun konxju tagħhom meta taħdem ma 'l-API. Ejja nassumu li m'aħniex interessati f'msg_key; il-livell aktar baxx iddeċifra kollox għalina. Iżda ġewwa d-dejta decrypted għandna l-oqsma li ġejjin (ukoll it-tul tad-dejta, sabiex inkunu nafu fejn hu l-ikkuttunar, iżda dan mhux importanti):

  • melħ - int64
  • session_id - int64
  • message_id — int64
  • seq_no - int32

Ejjew infakkarkom li hemm melħ wieħed biss għad-DC kollu. Għaliex tkun taf dwarha? Mhux biss għax hemm talba get_future_salts, li jgħidlek liema intervalli se jkunu validi, iżda wkoll għaliex jekk il-melħ tiegħek ikun "immuffat", allura l-messaġġ (talba) sempliċiment jintilef. Is-server, ovvjament, jirrapporta l-melħ il-ġdid billi joħroġ new_session_created - imma bil-qadima jkollok terġa' tibgħatha b'xi mod, pereżempju. U din il-kwistjoni taffettwa l-arkitettura tal-applikazzjoni.

Is-server huwa permess li jwaqqa sessjonijiet għal kollox u jirrispondi b'dan il-mod għal ħafna raġunijiet. Fil-fatt, x'inhi sessjoni MTProto min-naħa tal-klijent? Dawn huma żewġ numri session_id и seq_no messaġġi fi ħdan din is-sessjoni. Ukoll, u l-konnessjoni TCP sottostanti, ovvjament. Ejja ngħidu li l-klijent tagħna għadu ma jafx kif jagħmel ħafna affarijiet, skonnettja u reġa' qabad. Jekk dan ġara malajr - is-sessjoni l-antika kompliet fil-konnessjoni TCP il-ġdida, żid seq_no aktar. Jekk jieħu żmien twil, is-server jista’ jħassarha, għax min-naħa tiegħu hija wkoll kju, kif sirna nafu.

X'għandu jkun seq_no? Oh, dik hija mistoqsija delikata. Ipprova tifhem onestament dak li kien ifisser:

Messaġġ relatat mal-kontenut

Messaġġ li jeħtieġ rikonoxximent espliċitu. Dawn jinkludu l-utent u ħafna messaġġi tas-servizz, prattikament kollha bl-eċċezzjoni tal-kontenituri u rikonoxximenti.

Numru tas-Sekwenza tal-Messaġġ (msg_seqno)

Numru ta’ 32 bit ugwali għad-doppju tan-numru ta’ messaġġi “relatati mal-kontenut” (dawk li jeħtieġu rikonoxximent, u b’mod partikolari dawk li mhumiex kontenituri) maħluqa mill-mittent qabel dan il-messaġġ u sussegwentement inkrementat b’wieħed jekk il-messaġġ kurrenti huwa messaġġ relatat mal-kontenut. Kontenitur huwa dejjem iġġenerat wara l-kontenut kollu tiegħu; għalhekk, in-numru tas-sekwenza tiegħu huwa akbar minn jew ugwali għan-numri tas-sekwenza tal-messaġġi li jinsabu fih.

X'tip ta 'ċirku huwa dan b'inkrement b'1, u mbagħad ieħor b'2?... Nissuspetta li inizjalment kienu jfissru "l-inqas daqsxejn sinifikanti għal ACK, il-bqija huwa numru", iżda r-riżultat mhuwiex l-istess - b'mod partikolari, toħroġ, jistgħu jintbagħtu xi konfermi li jkollhom l-istess seq_no! Kif? Ukoll, pereżempju, is-server jibgħatilna xi ħaġa, jibgħatha, u aħna nfusna nibqgħu siekta, nirrispondu biss b'messaġġi ta 'servizz li jikkonfermaw l-irċevuta tal-messaġġi tiegħu. F'dan il-każ, il-konfermi ħerġin tagħna se jkollhom l-istess numru ħerġin. Jekk int familjari mat-TCP u ħsibt li dan jinstema' b'xi mod selvaġġ, iżda jidher mhux selvaġġ ħafna, għax f'TCP seq_no ma jinbidilx, iżda l-konferma tmur għal seq_no fuq in-naħa l-oħra, se nħaffef biex inħarbtek. Il-konfermi huma pprovduti f'MTProto MHUX fuq seq_no, bħal fil-TCP, iżda minn msg_id !

X'inhu dan msg_id, l-aktar importanti minn dawn l-oqsma? Identifikatur uniku tal-messaġġ, kif jissuġġerixxi l-isem. Huwa definit bħala numru ta '64 bit, li l-aktar bits baxxi tagħhom għal darb'oħra għandhom il-maġija "server-mhux server", u l-bqija huwa timestamp Unix, inkluża l-parti frazzjonali, imċaqlaq 32 bit lejn ix-xellug. Dawk. timestamp per se (u messaġġi b'ħinijiet li jvarjaw wisq se jiġu rrifjutati mis-server). Minn dan jirriżulta li b'mod ġenerali dan huwa identifikatur li huwa globali għall-klijent. Minħabba li - ejja niftakru session_id - aħna garantiti: Taħt l-ebda ċirkostanza ma jista' messaġġ maħsub għal sessjoni waħda jintbagħat f'sessjoni differenti. Jiġifieri jirriżulta li diġà hemm 3 livell - sessjoni, numru tas-sessjoni, id-messaġġ. Għaliex komplikazzjoni żejda bħal din, dan il-misteru huwa kbir ħafna.

Allura, msg_id meħtieġa għal...

RPC: talbiet, tweġibiet, żbalji. Konfermazzjonijiet.

Kif forsi innotajt, m'hemm l-ebda tip jew funzjoni speċjali ta '"agħmel talba RPC" kullimkien fid-dijagramma, għalkemm hemm tweġibiet. Wara kollox, għandna messaġġi relatati mal-kontenut! Jiġifieri kwalunkwe il-messaġġ jista' jkun talba! Jew ma tkunx. Wara kollox, ta 'kull wieħed hemm msg_id. Iżda hemm tweġibiet:

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

Dan huwa fejn huwa indikat għal liema messaġġ dan huwa tweġiba. Għalhekk, fl-ogħla livell tal-API, ikollok tiftakar x'kien in-numru tat-talba tiegħek - naħseb li m'hemmx għalfejn tispjega li x-xogħol huwa asinkroniku, u jista 'jkun hemm diversi talbiet għaddejjin fl-istess ħin, it-tweġibiet li għalihom jistgħu jintbagħtu lura fi kwalunkwe ordni? Fil-prinċipju, minn dan u messaġġi ta 'żball bħall-ebda ħaddiema, l-arkitettura wara dan tista' tiġi rintraċċata: is-server li jżomm konnessjoni TCP miegħek huwa front-end balancer, jgħaddi talbiet lill-backends u jiġborhom lura permezz message_id. Jidher li kollox hawn huwa ċar, loġiku u tajjeb.

Iva?.. U jekk taħseb dwarha? Wara kollox, ir-rispons RPC innifsu għandu wkoll qasam msg_id! Għandna bżonn ngħajtu fuq is-server "m'intix qed twieġeb it-tweġiba tiegħi!"? U iva, x’kien hemm dwar il-konfermi? Dwar il-paġna messaġġi dwar messaġġi jgħidilna x'inhu

msgs_ack#62d6b459 msg_ids:Vector long = MsgsAck;

u għandu jsir minn kull naħa. Imma mhux dejjem! Jekk irċevejt RpcResult, huwa stess iservi bħala konferma. Jiġifieri, is-server jista 'jirrispondi għat-talba tiegħek b'MsgsAck - bħal, "Irċevejtha." RpcResult jista 'jirrispondi immedjatament. Jista 'jkun it-tnejn.

U iva, għad trid twieġeb it-tweġiba! Konferma. Inkella, is-server jikkunsidra li ma jistax jitwassal u jerġa 'jibgħatha lura lilek. Anke wara konnessjoni mill-ġdid. Iżda hawnhekk, ovvjament, tqum il-kwistjoni tal-timeouts. Ejja nħarsu lejhom ftit aktar tard.

Sadanittant, ejja nħarsu lejn żbalji possibbli fl-eżekuzzjoni tal-mistoqsijiet.

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

Oh, xi ħadd se exclaim, hawnhekk huwa format aktar uman - hemm linja! Ħu l-ħin tiegħek. Hawn lista ta’ żbalji, iżda ovvjament mhux komplut. Minnha nitgħallmu li l-kodiċi huwa xi ħaġa simili Żbalji HTTP (tajjeb, ovvjament, is-semantika tat-tweġibiet mhumiex rispettati, f'xi postijiet huma mqassma b'mod każwali fost il-kodiċi), u l-linja tidher qisha KAPITAL_LETTERS_AND_NUMBERS. Per eżempju, PHONE_NUMBER_OCCUPIED jew FILE_PART_Х_MISSING. Ukoll, jiġifieri, xorta jkollok bżonn din il-linja parse. Pereżempju FLOOD_WAIT_3600 se jfisser li inti għandek tistenna siegħa, u PHONE_MIGRATE_5, li numru tat-telefon b'dan il-prefiss irid ikun reġistrat fil-5 DC. Għandna lingwa tat-tip, hux? M'għandniex bżonn argument minn spag, dawk regolari se jagħmlu, okay.

Għal darb'oħra, dan mhux fuq il-paġna tal-messaġġi tas-servizz, iżda, kif diġà s-soltu ma 'dan il-proġett, l-informazzjoni tista' tinstab fuq paġna oħra tad-dokumentazzjoni. Jew jitfa’ suspett. L-ewwelnett, ara, ittajpjar/ksur tas-saff - RpcError jista 'jitbejta fih RpcResult. Għaliex mhux barra? X’ma qisniex?.. Għaldaqstant, fejn hi l-garanzija li RpcError ma jistgħux jiġu inkorporati fi RpcResult, imma tkun direttament jew imnaqqsa f'tip ieħor?.. U jekk ma tistax, għaliex mhix fl-ogħla livell, i.e. hija nieqsa req_msg_id ? ..

Imma ejja nkomplu dwar il-messaġġi tas-servizz. Il-klijent jista 'jaħseb li s-server qed jaħseb għal żmien twil u jagħmel din it-talba mill-isbaħ:

rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;

Hemm tliet tweġibiet possibbli għal din il-mistoqsija, għal darb'oħra jaqsmu mal-mekkaniżmu ta' konferma; li tipprova tifhem x'għandhom ikunu (u x'inhuma l-lista ġenerali ta' tipi li ma jeħtiġux konferma) titħalla f'idejn il-qarrej bħala xogħol tad-dar (nota: l-informazzjoni f' il-kodiċi tas-sors tat-Telegram Desktop mhux komplut).

Vizzju tad-droga: status tal-messaġġ

B'mod ġenerali, ħafna postijiet f'TL, MTProto u Telegram b'mod ġenerali jħallu sens ta' stubbornness, iżda minn edukat, tattika u oħrajn ħiliet artab B’mod edukat żammejna siekta dwarha, u ċensurajna l-oxxenitajiet fid-djalogi. Madankollu, dan il-postОil-biċċa l-kbira tal-paġna hija dwar messaġġi dwar messaġġi Huwa xokkanti anke għalija, li ilni naħdem bi protokolli tan-netwerk għal żmien twil u rajt roti ta 'gradi differenti ta' mgħawġa.

Jibda innokwament, b'konfermi. Imbagħad jgħidulna dwar

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;

Ukoll, kull min jibda jaħdem ma 'MTProto se jkollu jindirizzahom; fiċ-ċiklu "ikkoreġut - rikompilat - imniedi", li jkollok żbalji tan-numri jew melħ li rnexxielu jmur ħażin waqt l-editjar hija ħaġa komuni. Madankollu, hawn żewġ punti:

  1. Dan ifisser li l-messaġġ oriġinali jintilef. Għandna bżonn noħolqu xi kjuwijiet, aħna ser inħarsu lejn dan aktar tard.
  2. X'inhuma dawn in-numri strambi ta' żball? 16, 17, 18, 19, 20, 32, 33, 34, 35, 48, 64... fejn huma n-numri l-oħra, Tommy?

Id-dokumentazzjoni tgħid:

L-intenzjoni hija li l-valuri ta 'error_code huma raggruppati (error_code >> 4): pereżempju, il-kodiċijiet 0x40 — 0x4f jikkorrispondu għal żbalji fid-dekompożizzjoni tal-kontenitur.

iżda, l-ewwelnett, bidla fid-direzzjoni l-oħra, u t-tieni, ma jimpurtax, fejn huma l-kodiċijiet l-oħra? F'ras l-awtur?.. Madankollu, dawn huma trifles.

Il-vizzju jibda f'messaġġi dwar l-istatus tal-messaġġi u l-kopji tal-messaġġi:

  • Talba għal Informazzjoni dwar l-Istatus tal-Messaġġ
    Jekk xi parti ma tkunx irċeviet informazzjoni dwar l-istatus tal-messaġġi ħerġin tagħha għal xi żmien, tista' titlobha b'mod espliċitu mingħand il-parti l-oħra:
    msgs_state_req#da69fb52 msg_ids:Vector long = MsgsStateReq;
  • Messaġġ Informattiv dwar l-Istatus tal-Messaġġi
    msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
    Hawnhekk, info hija string li fiha eżattament byte wieħed ta' status ta' messaġġ għal kull messaġġ mil-lista msg_ids deħlin:

    • 1 = xejn mhu magħruf dwar il-messaġġ (msg_id baxx wisq, il-parti l-oħra tista’ tkun insiet)
    • 2 = messaġġ mhux riċevut (msg_id jaqa' fil-firxa ta' identifikaturi maħżuna; madankollu, il-parti l-oħra ċertament ma rċevietx messaġġ bħal dak)
    • 3 = messaġġ mhux riċevut (msg_id għoli wisq; madankollu, il-parti l-oħra ċertament għadha ma rċevietux)
    • 4 = messaġġ riċevut (innota li din ir-risposta hija wkoll fl-istess ħin konferma tal-irċevuta)
    • +8 = messaġġ diġà rikonoxxut
    • +16 = messaġġ li ma jeħtieġx rikonoxximent
    • +32 = mistoqsija RPC li tinsab fil-messaġġ li qed jiġi pproċessat jew l-ipproċessar diġà lest
    • +64 = rispons relatat mal-kontenut għal messaġġ diġà ġġenerat
    • +128 = parti l-oħra taf fil-fatt li l-messaġġ diġà wasal
      Din it-tweġiba ma teħtieġx rikonoxximent. Huwa rikonoxximent tal-msgs_state_req rilevanti, fih innifsu.
      Innota li jekk jirriżulta f'daqqa waħda li l-parti l-oħra m'għandhiex messaġġ li jidher li ntbagħat lilha, il-messaġġ jista 'sempliċement jerġa' jintbagħat. Anke jekk il-parti l-oħra għandha tirċievi żewġ kopji tal-messaġġ fl-istess ħin, id-duplikat jiġi injorat. (Jekk ikun għadda wisq ħin, u l-msg_id oriġinali m'għadux validu, il-messaġġ għandu jkun imgeżwer f'msg_copy).
  • Komunikazzjoni Volontarja tal-Istatus tal-Messaġġi
    Kull parti tista' volontarjament tinforma lill-parti l-oħra dwar l-istatus tal-messaġġi trażmessi mill-parti l-oħra.
    msgs_all_info#8cc0d131 msg_ids:Vector long info:string = MsgsAllInfo
  • Komunikazzjoni Volontarja Estiża ta 'Status ta' Messaġġ Wieħed
    ...
    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;
  • Talba Espliċita biex Tibgħat Messaġġi mill-ġdid
    msg_resend_req#7d861a08 msg_ids:Vector long = MsgResendReq;
    Il-parti remota twieġeb immedjatament billi terġa’ tibgħat il-messaġġi mitluba […]
  • Talba Espliċita biex Tibgħat Tweġibiet mill-ġdid
    msg_resend_ans_req#8610baeb msg_ids:Vector long = MsgResendReq;
    Il-parti remota tirrispondi immedjatament billi terġa 'tibgħat tweġibiet għall-messaġġi mitluba […]
  • Kopji tal-Messaġġ
    F'xi sitwazzjonijiet, messaġġ antik b'msg_id li m'għadux validu jeħtieġ li jerġa' jintbagħat. Imbagħad, ikun imgeżwer f'kontenitur tal-kopja:
    msg_copy#e06046b2 orig_message:Message = MessageCopy;
    Ladarba riċevut, il-messaġġ jiġi pproċessat bħallikieku l-ippakkjar ma kienx hemm. Madankollu, jekk ikun magħruf b'ċertezza li l-messaġġ orig_message.msg_id ġie riċevut, allura l-messaġġ il-ġdid ma jiġix ipproċessat (filwaqt li fl-istess ħin, huwa u orig_message.msg_id huma rikonoxxuti). Il-valur ta' orig_message.msg_id għandu jkun aktar baxx mill-msg_id tal-kontenitur.

Ejja saħansitra nżommu siekta dwar xiex msgs_state_info għal darb'oħra l-widnejn tat-TL mhux mitmuma qed joħorġu (neħtieġu vector ta 'bytes, u fiż-żewġ bits t'isfel kien hemm enum, u fiż-żewġ bits ogħla kien hemm bnadar). Il-punt huwa differenti. Xi ħadd jifhem għaliex dan kollu huwa fil-prattika? f'klijent reali meħtieġ?.. B'diffikultà, iżda wieħed jista 'jimmaġina xi benefiċċju jekk persuna tkun involuta fid-debugging, u f'mod interattiv - staqsi lis-server x'u kif. Iżda hawn it-talbiet huma deskritti vjaġġ bir-ritorn.

Minn dan isegwi li kull parti għandha mhux biss tikkriptaġġ u tibgħat messaġġi, iżda wkoll taħżen data dwarhom infushom, dwar it-tweġibiet għalihom, għal ammont ta 'żmien mhux magħruf. Id-dokumentazzjoni ma tiddeskrivix la l-ħinijiet u lanqas l-applikabbiltà prattika ta' dawn il-karatteristiċi. bl-ebda mod. X'hemm l-aktar aqwa huwa li huma attwalment użati fil-kodiċi tal-klijenti uffiċjali! Jidher li qalulhom xi ħaġa li ma kinitx inkluża fid-dokumentazzjoni pubblika. Ifhem mill-kodiċi għaliex, m'għadux sempliċi bħal fil-każ ta 'TL - mhix parti (relattivament) loġikament iżolata, iżda biċċa marbuta mal-arkitettura tal-applikazzjoni, i.e. se teħtieġ ħafna aktar ħin biex tifhem il-kodiċi tal-applikazzjoni.

Pings u ħinijiet. Kjuwijiet.

Minn kollox, jekk niftakru l-suppożizzjonijiet dwar l-arkitettura tas-server (distribuzzjoni tat-talbiet fuq backends), ġejja ħaġa pjuttost imdejjaq - minkejja l-garanziji kollha tal-kunsinna fit-TCP (jew id-dejta titwassal, jew tkun infurmat dwar id-distakk, iżda id-data se titwassal qabel ma sseħħ il-problema), li l-konfermi f'MTProto innifsu - ebda garanziji. Is-server jista 'faċilment jitlef jew jarmi l-messaġġ tiegħek, u xejn ma jista' jsir dwaru, sempliċement uża tipi differenti ta 'krozzi.

U l-ewwel nett - kjuwijiet tal-messaġġi. Ukoll, b'ħaġa waħda kollox kien ovvju mill-bidu nett - messaġġ mhux ikkonfermat irid jinħażen u jerġa' jintbagħat. Kemm se jdum? U l-jester jaf lilu. Forsi dawk il-messaġġi tas-servizz dipendenti b'xi mod isolvu din il-problema bil-krozzi, ngħidu aħna, f'Telegram Desktop hemm madwar 4 kjuwijiet li jikkorrispondu magħhom (forsi aktar, kif diġà ssemma, għal dan għandek bżonn tidħol fil-kodiċi u l-arkitettura tagħha b'mod aktar serju; fl-istess ħin żmien, aħna Nafu li ma jistax jittieħed bħala kampjun; ċertu numru ta 'tipi mill-iskema MTProto mhumiex użati fiha).

Għaliex qed jiġri dan? Probabbilment, il-programmaturi tas-server ma setgħux jiżguraw affidabbiltà fi ħdan il-cluster, jew saħansitra buffering fuq il-front balancer, u ttrasferixxew din il-problema lill-klijent. B'disprament, Vasily ipprova jimplimenta għażla alternattiva, b'żewġ kjuwijiet biss, bl-użu ta 'algoritmi minn TCP - kejl tal-RTT għas-server u aġġustament tad-daqs tat-"tieqa" (f'messaġġi) skont in-numru ta' talbiet mhux ikkonfermati. Jiġifieri, euristiku daqshekk approssimattiv għall-valutazzjoni tat-tagħbija tas-server huwa kemm mit-talbiet tagħna jista 'jomgħod fl-istess ħin u ma jitlifx.

Ukoll, jiġifieri, tifhem, hux? Jekk trid timplimenta TCP mill-ġdid fuq protokoll li jaħdem fuq TCP, dan jindika protokoll iddisinjat ħażin ħafna.

Oh yeah, għaliex għandek bżonn aktar minn kju wieħed, u xi jfisser dan għal persuna li taħdem b'API ta 'livell għoli xorta waħda? Ara, inti tagħmel talba, serializeha, imma ħafna drabi ma tistax tibgħatha immedjatament. Għaliex? Għax it-tweġiba se tkun msg_id, li hija temporanjaаJiena tikketta, li l-assenjazzjoni tagħha tiġi posposta l-aħjar sa tard kemm jista’ jkun - f’każ li s-server jirrifjutaha minħabba nuqqas ta’ qbil fil-ħin bejnna u bejnu (naturalment, nistgħu nagħmlu crutch li ċċaqlaq il-ħin tagħna mill-preżent lis-server billi żżid delta kkalkulata mit-tweġibiet tas-server - il-klijenti uffiċjali jagħmlu dan, iżda huwa mhux raffinat u mhux preċiż minħabba l-buffering). Għalhekk, meta tagħmel talba b'sejħa ta' funzjoni lokali mil-librerija, il-messaġġ jgħaddi mill-istadji li ġejjin:

  1. Hija tinsab f'kju wieħed u tistenna l-encryption.
  2. Maħtur msg_id u l-messaġġ mar għal kju ieħor - trażmissjoni possibbli; ibgħat lill-sokit.
  3. a) Is-server wieġeb MsgsAck - il-messaġġ ġie kkunsinnat, aħna nħassruh mill-"kju ieħor".
    b) Jew viċeversa, ma għoġbitx xi ħaġa, wieġeb badmsg - ibgħat mill-ġdid minn "kju ieħor"
    c) Xejn mhu magħruf, il-messaġġ jeħtieġ li jintbagħat mill-ġdid minn kju ieħor - iżda mhux magħruf eżattament meta.
  4. Is-server fl-aħħar wieġeb RpcResult - ir-rispons attwali (jew żball) - mhux biss mogħtija, iżda wkoll ipproċessati.

Forsi, l-użu ta 'kontenituri jista' jsolvi parzjalment il-problema. Dan huwa meta mazz ta 'messaġġi huma ppakkjati f'wieħed, u s-server wieġeb b'konferma lilhom kollha f'daqqa, f'wieħed msg_id. Imma se jirrifjuta wkoll dan il-pakkett, jekk xi ħaġa marret ħażin, fl-intier tiegħu.

U f'dan il-punt jidħlu fis-seħħ kunsiderazzjonijiet mhux tekniċi. Mill-esperjenza, rajna ħafna krozzi, u barra minn hekk, issa se naraw aktar eżempji ta’ pariri ħżiena u arkitettura – f’kundizzjonijiet bħal dawn, ta’ min nafdaw u nieħdu deċiżjonijiet bħal dawn? Il-mistoqsija hija retorika (naturalment le).

Fuq xiex qed nitkellmu? Jekk fuq is-suġġett ta '"messaġġi dwar messaġġi tad-droga" xorta tista' tispekula b'oġġezzjonijiet bħal "int stupid, ma fhimtx il-pjan brillanti tagħna!" (Għalhekk ikteb id-dokumentazzjoni l-ewwel, kif għandhom in-nies normali, b'raġunament u eżempji ta 'skambju ta' pakketti, imbagħad nitkellmu), imbagħad timings/timeouts huma mistoqsija purament prattika u speċifika, kollox hawn ilu magħruf għal żmien twil. X'tgħidilna d-dokumentazzjoni dwar timeouts?

Server normalment jirrikonoxxi l-irċevuta ta 'messaġġ minn klijent (normalment, mistoqsija RPC) billi juża rispons RPC. Jekk tweġiba hija twila li ġejja, server jista 'l-ewwel jibgħat konferma tal-irċevuta, u kemmxejn aktar tard, ir-rispons RPC innifsu.

Klijent normalment jirrikonoxxi l-irċevuta ta’ messaġġ minn server (ġeneralment, rispons RPC) billi jżid rikonoxximent mal-mistoqsija RPC li jmiss jekk ma tiġix trażmessa tard wisq (jekk jiġi ġġenerat, ngħidu aħna, 60-120 sekonda wara l-irċevuta ta’ messaġġ mis-server). Madankollu, jekk għal perjodu twil ta 'żmien ma jkunx hemm raġuni biex jintbagħtu messaġġi lis-server jew jekk ikun hemm numru kbir ta' messaġġi mhux rikonoxxuti mis-server (jiġifieri, aktar minn 16), il-klijent jittrasmetti rikonoxximent waħdu.

... nittraduċi: aħna stess ma nafux kemm u kif għandna bżonnu, allura ejja nassumu li ħalliha tkun hekk.

U dwar il-pings:

Messaġġi Ping (PING/PONG)

ping#7abe77ec ping_id:long = Pong;

Risposta normalment tiġi rritornata lill-istess konnessjoni:

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

Dawn il-messaġġi ma jeħtiġux rikonoxximenti. Pong jiġi trasmess biss bi tweġiba għal ping filwaqt li ping jista' jinbeda minn kull naħa.

Għeluq tal-Konnessjoni Differita + PING

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

Jaħdem bħal ping. Barra minn hekk, wara li dan jiġi riċevut, is-server jibda tajmer li jagħlaq il-konnessjoni attwali disconnect_delay sekondi aktar tard sakemm ma jirċievix messaġġ ġdid tal-istess tip li awtomatikament jerġa’ jissettja t-tajmers preċedenti kollha. Jekk il-klijent jibgħat dawn il-pings darba kull 60 sekonda, pereżempju, jista' jistabbilixxi disconnect_delay ugwali għal 75 sekonda.

Int miġnun?! F'60 sekonda, il-ferrovija se tidħol fl-istazzjon, tinżel u tiġbor passiġġieri, u għal darb'oħra titlef il-kuntatt fil-mina. F'120 sekonda, waqt li tismagħha, tasal għal ieħor, u l-konnessjoni x'aktarx tinkiser. Ukoll, huwa ċar minn fejn ġejjin is-saqajn - "Smajt tisfir, imma ma nafx fejn hi", hemm l-algoritmu ta 'Nagl u l-għażla TCP_NODELAY, maħsuba għal xogħol interattiv. Iżda, skużani, żomm il-valur default tagħha - 200 Millisekondi Jekk verament trid turi xi ħaġa simili u tiffranka fuq koppja possibbli ta 'pakketti, imbagħad poġġiha off għal 5 sekondi, jew tkun xi tkun il-ħin ta' skadenza tal-messaġġ "L-utent qed ittajpja..." issa. Imma mhux aktar.

U finalment, pings. Jiġifieri, tiċċekkja l-ħajja tal-konnessjoni TCP. Huwa umoristiku, iżda madwar 10 snin ilu ktibt test kritiku dwar il-messaġġier tad-dorm tal-fakultà tagħna - l-awturi hemmhekk ukoll pingaw is-server mill-klijent, u mhux viċi versa. Imma l-istudenti tat-3 sena huma ħaġa waħda, u uffiċċju internazzjonali ieħor, hux?...

L-ewwel, ftit programm edukattiv. Konnessjoni TCP, fin-nuqqas ta 'skambju ta' pakketti, tista 'tgħix għal ġimgħat. Dan huwa kemm tajjeb kif ukoll ħażin, skont l-iskop. Tajjeb jekk kellek konnessjoni SSH miftuħa għas-server, qomt mill-kompjuter, rebootajt ir-router, erġajt lura f'postek - is-sessjoni permezz ta' dan is-server ma kinitx imqatta' (ma tajt xejn, ma kien hemm l-ebda pakkett) , huwa konvenjenti. Huwa ħażin jekk ikun hemm eluf ta 'klijenti fuq is-server, kull wieħed jieħu riżorsi (hello, Postgres!), U l-host tal-klijent jista' jkun rebooteja żmien twil ilu - iżda mhux se nkunu nafu biha.

Is-sistemi ta' chat/IM jaqgħu fit-tieni każ għal raġuni addizzjonali waħda - statuses online. Jekk l-utent "waqa'", għandek bżonn tinforma lill-interlokuturi tiegħu dwar dan. Inkella, inti tispiċċa bi żball li l-ħallieqa ta 'Jabber għamlu (u kkoreġuti għal 20 sena) - l-utent skonnettja, iżda jkomplu jiktbu messaġġi lilu, jemmen li huwa online (li wkoll kienu kompletament mitlufa f'dawn ftit minuti qabel ma ġiet skoperta l-iskonnettjar). Le, l-għażla TCP_KEEPALIVE, li ħafna nies li ma jifhmux kif jaħdmu t-tajmers TCP jarmu bl-addoċċ (billi jistabbilixxu valuri selvaġġi bħal għexieren ta’ sekondi), mhux se tgħin hawn - trid tiżgura li mhux biss il-qalba tal-OS. tal-magna tal-utent hija ħaj, iżda taħdem ukoll b'mod normali, kapaċi tirrispondi, u l-applikazzjoni nnifisha (taħseb li ma tistax tiffriża? Telegram Desktop fuq Ubuntu 18.04 ffriżat għalija aktar minn darba).

Huwa għalhekk li għandek tagħmel ping server klijent, u mhux viċi versa - jekk il-klijent jagħmel dan, jekk il-konnessjoni tinkiser, il-ping mhux se jitwassal, l-għan mhux se jintlaħaq.

X'naraw fuq Telegram? Huwa eżattament l-oppost! Ukoll, jiġifieri. Formalment, ovvjament, iż-żewġ naħat jistgħu jagħmlu ping lil xulxin. Fil-prattika, il-klijenti jużaw crutch ping_delay_disconnect, li jistabbilixxi t-tajmer fuq is-server. Ukoll, skużani, mhuwiex f'idejn il-klijent li jiddeċiedi kemm irid jgħix hemm mingħajr ping. Is-server, ibbażat fuq it-tagħbija tiegħu, jaf aħjar. Imma, ovvjament, jekk ma tfixkilx ir-riżorsi, allura tkun Pinocchio ħażin tiegħek stess, u crutch se tagħmel ...

Kif kellha tkun iddisinjata?

Nemmen li l-fatti ta 'hawn fuq jindikaw b'mod ċar li t-tim ta' Telegram/VKontakte mhuwiex kompetenti ħafna fil-qasam tat-trasport (u livell aktar baxx) tan-netwerks tal-kompjuter u l-kwalifiki baxxi tagħhom f'materji rilevanti.

Għaliex irriżulta li kien daqshekk ikkumplikat, u l-periti Telegram kif jistgħu jippruvaw joġġezzjonaw? Il-fatt li ppruvaw jagħmlu sessjoni li tgħix konnessjoni TCP waqfiet, jiġifieri, dak li ma kienx ikkunsinnat issa, aħna se nwasslu aktar tard. Probabbilment ippruvaw jagħmlu wkoll trasport UDP, iżda ltaqgħu ma’ diffikultajiet u abbandunawh (għalhekk id-dokumentazzjoni hija vojta - ma kien hemm xejn x’tiftaħar). Iżda minħabba nuqqas ta 'fehim ta' kif in-netwerks b'mod ġenerali u t-TCP b'mod partikolari jaħdmu, fejn tista 'tistrieħ fuqha, u fejn għandek bżonn tagħmel it yourself (u kif), u tentattiv biex tgħaqqad dan mal-kriptografija "żewġ għasafar b' ġebla waħda”, dan huwa r-riżultat.

Kif kien meħtieġ? Ibbażat fuq il-fatt li msg_id huwa timestamp meħtieġ mil-lat kriptografiku biex jipprevjeni attakki ta 'replay, huwa żball li tehmeż funzjoni ta' identifikatur uniku miegħu. Għalhekk, mingħajr ma tinbidel b'mod fundamentali l-arkitettura attwali (meta l-fluss tal-Aġġornamenti jiġi ġġenerat, dak huwa suġġett API ta 'livell għoli għal parti oħra ta' din is-serje ta 'postijiet), wieħed ikollu bżonn:

  1. Is-server li jżomm il-konnessjoni TCP mal-klijent jieħu r-responsabbiltà - jekk ikun qara mis-socket, jekk jogħġbok irrikonoxxi, jipproċessa jew jirritorna żball, l-ebda telf. Imbagħad il-konferma mhix vettur ta 'ids, iżda sempliċement "l-aħħar seq_no riċevut" - numru biss, bħal f'TCP (żewġ numri - seq tiegħek u dak ikkonfermat). Aħna dejjem fi ħdan is-sessjoni, hux?
  2. Il-timestamp biex jipprevjenu attakki replay isir qasam separat, a la nonce. Huwa ċċekkjat, iżda ma jaffettwa xejn ieħor. Biżżejjed u uint32 - jekk il-melħ tagħna jinbidel mill-inqas kull nofs ġurnata, nistgħu nallokaw 16-il bit għall-bits ta 'ordni baxx ta' parti sħiħa tal-ħin kurrenti, il-bqija - għal parti frazzjonali ta 'sekonda (bħal issa).
  3. Imneħħija msg_id fil-livelli kollha - mill-perspettiva tad-distinzjoni tat-talbiet fuq il-backends, hemm, l-ewwelnett, l-id tal-klijent, u t-tieni, l-id tas-sessjoni, tikkonkatenhom. Għaldaqstant, ħaġa waħda biss hija biżżejjed bħala identifikatur tar-rikjesta seq_no.

Din mhix l-iktar għażla ta’ suċċess; każwali kompluta tista’ sservi bħala identifikatur – dan diġà jsir fl-API ta’ livell għoli meta jintbagħat messaġġ, bil-mod. Ikun aħjar li terġa 'tinkiseb kompletament l-arkitettura minn relattiv għal assolut, iżda dan huwa suġġett għal parti oħra, mhux din il-kariga.

API?

Ta-daam! Għalhekk, wara li tħabtu minn triq mimlija uġigħ u krozzi, fl-aħħar stajna nibagħtu kwalunkwe talba lis-server u nirċievu kwalunkwe tweġiba għalihom, kif ukoll nirċievu aġġornamenti mis-server (mhux bi tweġiba għal talba, iżda hija stess jibgħatilna, bħal PUSH, jekk xi ħadd ikun aktar ċar hekk).

Attenzjoni, issa se jkun hemm l-uniku eżempju fil-Perl fl-artiklu! (għal dawk li mhumiex familjari mas-sintassi, l-ewwel argument tal-bless huwa l-istruttura tad-dejta tal-oġġett, it-tieni hija l-klassi tiegħu):

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

Iva, mhux spoiler apposta - jekk għadek ma qrajtux, kompli u agħmel dan!

Oh, wai~~... kif tidher din? Xi ħaġa familjari ħafna... forsi din hija l-istruttura tad-dejta ta 'Web API tipika f'JSON, ħlief li l-klassijiet huma wkoll mehmuża ma' oġġetti?..

Allura dan huwa kif jirriżulta... X'inhu dan kollu, sħabi?.. Tant sforz - u aħna waqfu biex jistrieħu fejn il-programmaturi tal-Web għadu qed jibda?..JSON mhux biss fuq HTTPS ikun aktar sempliċi?! X’ksibna bi skambju? L-isforz kien jiswa?

Ejja nevalwaw dak li tana TL+MTProto u liema alternattivi huma possibbli. Ukoll, HTTP, li jiffoka fuq il-mudell ta 'talba-rispons, huwa tajjeb ħażin, iżda għall-inqas xi ħaġa fuq quċċata ta' TLS?

Serialization kompatt. Meta nara din l-istruttura tad-dejta, simili għal JSON, niftakar li hemm verżjonijiet binarji tagħha. Ejja nimmarkaw MsgPack bħala mhux estensibbli biżżejjed, iżda hemm, pereżempju, CBOR - mill-mod, standard deskritt f' RFC 7049. Huwa notevoli għall-fatt li jiddefinixxi tikketti, bħala mekkaniżmu ta 'espansjoni, u fost diġà standardizzat disponibbli:

  • 25 + 256 - tissostitwixxi linji ripetuti b'referenza għan-numru tal-linja, tali metodu ta 'kompressjoni irħis
  • 26 - oġġett Perl serialized bl-isem tal-klassi u argumenti tal-kostruttur
  • 27 - oġġett serializzat indipendenti mill-lingwa b'isem tat-tip u argumenti tal-kostruttur

Ukoll, ippruvajt serialize l-istess dejta f'TL u f'CBOR bl-ippakkjar ta 'sekwenza u oġġett attivat. Ir-riżultat beda jvarja favur CBOR x'imkien minn megabyte:

cborlen=1039673 tl_len=1095092

Allura, konklużjoni: Hemm formati sostanzjalment aktar sempliċi li mhumiex suġġetti għall-problema ta 'nuqqas ta' sinkronizzazzjoni jew identifikatur mhux magħruf, b'effiċjenza komparabbli.

Stabbiliment ta 'konnessjoni mgħaġġla. Dan ifisser żero RTT wara konnessjoni mill-ġdid (meta ċ-ċavetta tkun diġà ġiet ġġenerata darba) - applikabbli mill-ewwel messaġġ MTProto, iżda b'xi riżervi - tolqot l-istess melħ, is-sessjoni mhix immuffata, eċċ. X'joffrilna TLS minflok? Kwotazzjoni fuq is-suġġett:

Meta tuża PFS f'TLS, biljetti tas-sessjoni TLS (RFC 5077) biex terġa 'tibda sessjoni kriptata mingħajr ma terġa' tinnegozja ċ-ċwievet u mingħajr ma taħżen informazzjoni ewlenija fuq is-server. Meta tiftaħ l-ewwel konnessjoni u toħloq ċwievet, is-server jikkripta l-istat tal-konnessjoni u jittrasmettih lill-klijent (fil-forma ta 'biljett ta' sessjoni). Għaldaqstant, meta l-konnessjoni terġa 'tibda, il-klijent jibgħat biljett tas-sessjoni, inkluża ċ-ċavetta tas-sessjoni, lura lis-server. Il-biljett innifsu huwa kkodifikat b'ċavetta temporanja (ċavetta tal-biljett tas-sessjoni), li hija maħżuna fuq is-server u għandha titqassam fost is-servers kollha ta' frontend li jipproċessaw SSL f'soluzzjonijiet raggruppati.[10]. Għalhekk, l-introduzzjoni ta 'biljett ta' sessjoni tista 'tikser PFS jekk iċ-ċwievet tas-server temporanji jiġu kompromessi, pereżempju, meta jinħażnu għal żmien twil (OpenSSL, nginx, Apache jaħżnuhom awtomatikament għat-tul kollu tal-programm; siti popolari jużaw iċ-ċavetta għal diversi sigħat, sa jiem).

Hawnhekk l-RTT mhuwiex żero, għandek bżonn tiskambja mill-inqas ClientHello u ServerHello, wara li l-klijent jista 'jibgħat data flimkien ma' Finished. Iżda hawnhekk għandna niftakru li m'għandniex il-Web, bil-mazz tagħha ta 'konnessjonijiet ġodda miftuħa, iżda messaġġier, li l-konnessjoni tiegħu ħafna drabi hija waħda u aktar jew inqas talbiet għal ħajja twila, relattivament qosra għal paġni tal-Web - kollox huwa multiplexed internament. Jiġifieri, huwa pjuttost aċċettabbli jekk ma ltqajna ma 'sezzjoni tas-subway tassew ħażina.

Insejt xi ħaġa oħra? Ikteb fil-kummenti.

Ser jitkompla aktar il-quddiem!

Fit-tieni parti ta 'din is-sensiela ta' postijiet se nikkunsidraw kwistjonijiet mhux tekniċi, iżda organizzattivi - approċċi, ideoloġija, interface, attitudni lejn l-utenti, eċċ. Ibbażat, madankollu, fuq l-informazzjoni teknika li ġiet ippreżentata hawn.

It-tielet parti se tkompli tanalizza l-komponent tekniku / esperjenza ta 'żvilupp. Inti ser titgħallem, b'mod partikolari:

  • kontinwazzjoni tal-pandemonju mal-varjetà ta 'tipi TL
  • affarijiet mhux magħrufa dwar kanali u supergruppi
  • għaliex id-djalogu huma agħar minn roster
  • dwar l-indirizzar tal-messaġġ assolut vs relattiv
  • x'inhi d-differenza bejn ritratt u immaġni
  • kif l-emoji jinterferixxu mat-test korsiv

u krozzi oħra! Ibqa' sintonizzat!

Sors: www.habr.com

Żid kumment