Cáineadh prótacal agus cur chuige eagraíochtúil Telegram. Cuid 1, teicniúil: taithí ar chliant a scríobh ón tús - TL, MT

Le déanaí, tá poist faoi cé chomh maith agus atá Telegram, cé chomh iontach agus a bhfuil taithí acu ar na deartháireacha Durov agus iad ag tógáil córais líonra, etc., tar éis tosú le feiceáil níos minice ar Habré. Ag an am céanna, is beag duine atá tumtha i ndáiríre sa gléas teicniúil - ar a mhéad, úsáideann siad API Bot sách simplí (agus an-difriúil ó MTProto) bunaithe ar JSON, agus de ghnáth ní ghlacann siad ach. ar chreideamh gach moladh agus PR a revolve around an teachtaire. Beagnach bliain go leith ó shin, thosaigh mo chomhghleacaí ag Eshelon NGO Vasily (ar an drochuair, scriosadh a chuntas ar Habré mar aon leis an dréacht) a chliant Telegram féin a scríobh ón tús i Perl, agus ina dhiaidh sin chuaigh údar na línte seo isteach. Cén fáth Perl, beidh roinnt a iarraidh láithreach? Toisc go bhfuil a leithéid de thionscadail ann cheana féin i dteangacha eile Go deimhin, ní hé seo an pointe, d'fhéadfadh go mbeadh teanga ar bith eile ann leabharlann réidh, agus dá réir sin ní foláir don ughdar dul an bealach ar fad ón dtús. Thairis sin, is ábhar muiníne é cripteagrafaíocht, ach a fhíorú. Le táirge atá dírithe ar shlándáil, ní féidir leat brath go simplí ar leabharlann réamhdhéanta ón monaróir agus muinín a bheith agat as (mar sin féin, is ábhar é seo don dara cuid). Faoi láthair, oibríonn an leabharlann go measartha maith ag an “meánleibhéal” (a ligeann duit aon iarratais API a dhéanamh).

Mar sin féin, ní bheidh mórán cripteagrafaíochta ná matamaitice sa tsraith post seo. Ach beidh go leor sonraí teicniúla eile agus crutches ailtireachta (úsáideach freisin dóibh siúd nach mbeidh ag scríobh ón tús, ach a úsáidfidh an leabharlann i dteanga ar bith). Mar sin, ba é an príomhsprioc ná iarracht a dhéanamh an cliant a chur i bhfeidhm ón tús de réir doiciméad oifigiúil. Is é sin, déanaimis glacadh leis go bhfuil cód foinse na gcliant oifigiúil dúnta (arís, sa dara cuid clúdóimid níos mionsonraithe an t-ábhar ar an bhfíric go bhfuil sé seo fíor tharlaíonn mar sin), ach, mar a bhí sna seanlaethanta, mar shampla, tá caighdeán cosúil le RFC - an féidir cliant a scríobh de réir na sonraíochta amháin, “gan breathnú” ar an gcód foinseach, bíodh sé oifigiúil (Telegram Desktop, soghluaiste), nó Telethon neamhoifigiúil?

Suil:

Doiciméadú ... tá sé ann, ceart? An bhfuil sé fíor?..

Thosaigh blúirí nótaí don airteagal seo a bhailiú an samhradh seo caite. Gach an am seo ar an láithreán gréasáin oifigiúil https://core.telegram.org Bhí an doiciméadú mar atá i Sraith 23, i.e. bhfostú áit éigin i 2014 (cuimhnigh, nach raibh fiú bealaí ar ais ansin?). Ar ndóigh, go teoiriciúil, ba cheart go gceadódh sé seo dúinn cliant le feidhmiúlacht a chur i bhfeidhm ag an am sin in 2014. Ach fiú sa stát seo, bhí an doiciméadú, ar an gcéad dul síos, neamhiomlán, agus sa dara háit, bhí sé ag teacht salach ar a chéile in áiteanna. Beagán níos mó ná mí ó shin, i Meán Fómhair 2019, bhí de sheans Fuarthas amach go raibh nuashonrú mór ar an gcáipéisíocht ar an suíomh, don Chiseal 105 a bhí go hiomlán le déanaí, le nóta gur gá gach rud a léamh arís anois. Go deimhin, rinneadh athbhreithniú ar go leor alt, ach níor tháinig aon athrú ar go leor. Dá bhrí sin, nuair a bhíonn an cáineadh thíos á léamh faoin doiciméadú, ba cheart duit a choinneáil i gcuimhne nach bhfuil cuid de na rudaí seo ábhartha a thuilleadh, ach tá cuid acu fós go leor. Tar éis an tsaoil, ní hamháin go bhfuil 5 bliana sa domhan nua-aimseartha ar feadh i bhfad, ach an- a lán. Ó na hamanna sin (go háirithe mura gcuireann tú san áireamh na suíomhanna geochat a caitheadh ​​agus a athbheochan ó shin i leith), tá méadú tagtha ar líon na modhanna API sa scéim ó céad go dtí níos mó ná dhá chéad caoga!

Cá háit le tosú mar údar óg?

Is cuma cé acu an scríobhann tú ón tús nó an úsáideann tú, mar shampla, leabharlanna réamhdhéanta mar Telethon le haghaidh PythonMadeline le haghaidh php, in aon chás, beidh ort ar dtús cláraigh d’iarratas - paraiméadair a fháil api_id и api_hash (Tuigeann iad siúd a d'oibrigh leis an VKontakte API láithreach) trína n-aithneoidh an freastalaí an t-iarratas. seo caithfidh Déan é ar chúiseanna dlí, ach labhróimid níos mó faoin bhfáth nach féidir le húdair leabharlainne é a fhoilsiú sa dara cuid. Féadfaidh tú a bheith sásta leis na luachanna tástála, cé go bhfuil siad an-teoranta - is é fírinne an scéil gur féidir leat clárú anois ach amhain app, mar sin ná Rush headlong isteach é.

Anois, ó thaobh teicniúil de, ba cheart go mbeadh suim againn sa mhéid is gur chóir dúinn tar éis clárúcháin a fháil fógraí ó Telegram faoi nuashonruithe ar dhoiciméadú, prótacal, etc. Is é sin, d'fhéadfadh duine glacadh leis go raibh an suíomh leis na duganna tréigthe go simplí agus lean sé ag obair go sonrach leo siúd a thosaigh ag déanamh cliaint, mar gheall ar tá sé níos éasca. Ach ní hea, níor breathnaíodh aon rud mar sin, níor tháinig aon fhaisnéis.

Agus má scríobhann tú ón tús, ansin tá baint úsáide as na paraiméadair a fhaightear i ndáiríre fós i bhfad amach. Cé go https://core.telegram.org/ agus labhraíonn sé fúthu in Getting Started ar an gcéad dul síos, go deimhin, beidh ort a chur i bhfeidhm ar dtús Prótacal MTProto - ach má chreid tú leagan amach de réir mhúnla OSI ag deireadh an leathanaigh le haghaidh cur síos ginearálta ar an bprótacal, ansin tá sé go hiomlán in vain.

Go deimhin, roimh agus tar éis MTProto, ar leibhéil éagsúla ag an am céanna (mar a deir líonraithe eachtracha atá ag obair san eithne OS, sárú ciseal), cuirfear ábhar mór, pianmhar agus uafásach ar an mbealach ...

Srathú dénártha: TL (Cineál Teanga) agus a scéim, agus sraitheanna, agus go leor focail scanrúla eile

Is é an topaic seo, i ndáiríre, an eochair do fhadhbanna Telegram. Agus beidh go leor focail uafásacha ann má dhéanann tú iarracht dul i ngleic leis.

Mar sin, seo an léaráid. Má thagann an focal seo i d’intinn, abair, Scéimre JSON, Shíl tú i gceart. Is é an sprioc mar an gcéanna: roinnt teanga chun cur síos a dhéanamh ar shraith féideartha de shonraí tarchurtha. Seo an áit a dtagann deireadh leis na cosúlachtaí. Más rud é ón leathanach Prótacal MTProto, nó ó chrann foinse an chliaint oifigiúil, déanfaimid iarracht roinnt scéimre a oscailt, feicfimid rud éigin mar:

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;

Ní bheidh duine a fheiceann seo den chéad uair in ann ach cuid den méid atá scríofa a aithint go hintuigthe - bhuel, is struchtúir iad seo de réir dealraimh (cé go bhfuil an t-ainm, ar chlé nó ar dheis?), go bhfuil réimsí iontu, ina dhiaidh sin leanann cineál tar éis idirstad... is dócha. Anseo idir lúibíní uillinn is dócha go bhfuil teimpléid cosúil le C++ (go deimhin, Níl i ndáiríre). Agus cad a chiallaíonn na siombailí eile go léir, marcanna ceist, exclamation marcanna, céatadáin, marcanna hash (agus ar ndóigh ciallaíonn siad rudaí éagsúla in áiteanna éagsúla), uaireanta i láthair agus uaireanta nach bhfuil, uimhreacha heicsidheachúla - agus is tábhachtaí, conas a fháil ó seo go rialta (nach ndiúltóidh an freastalaí) sruth beart? Beidh ort na doiciméid a léamh (tá, tá naisc leis an scéimre sa leagan JSON in aice láimhe - ach ní dhéanann sé sin níos soiléire).

Oscail an leathanach Srathú Sonraí Dénártha agus tumadh isteach i ndomhan draíochta na muisiriún agus na matamaitice scoite, rud éigin cosúil le Matan sa 4ú bliain. Aibítir, cineál, luach, cumascóir, cumascóir feidhmiúil, gnáthfhoirm, cineál ilchodach, cineál ilmhorfach ... agus níl ann ach an chéad leathanach! Ar Aghaidh ag fanacht leat TL Teanga, nach dtugann freagra ar bith ar chásanna níos tipiciúla, cé go bhfuil sampla ann cheana féin d’iarratas agus d’fhreagairt fánach, rud a chiallaíonn go mbeidh ort dul trí athinsint matamaitice aistrithe ó Rúisis go Béarla ar ocht gcinn eile leabaithe. leathanaigh!

Ar ndóigh, feicfidh léitheoirí a bhfuil eolas acu ar theangacha feidhmiúla agus ar thátal cineál uathoibríoch an teanga tuairiscithe sa teanga seo, fiú ón sampla, i bhfad níos eolach, agus is féidir leo a rá nach bhfuil sé seo go dona i bprionsabal. Is iad na hagóidí ina choinne seo:

  • Sea, sprioc fuaimeanna go maith, ach faraor, sí nach bhfuil bainte amach
  • Athraíonn oideachas in ollscoileanna na Rúise fiú i measc speisialtachtaí TF - níor ghlac gach duine an cúrsa comhfhreagrach
  • Ar deireadh, mar a fheicfimid, go praiticiúil tá sé ní gá, toisc nach n-úsáidtear ach fo-thacar teoranta fiú amháin den TL ar a ndearnadh cur síos

Mar a dúradh LeonNáird ar an gcainéal #perl sa líonra FreeNode IRC, a rinne iarracht geata a chur i bhfeidhm ó Telegram go Maitrís (tá aistriú an athfhriotail míchruinn ón gcuimhne):

Mothaíonn sé mar a tugadh isteach duine éigin le cineál teoiric den chéad uair, bhí sceitimíní, agus thosaigh ag iarraidh a imirt timpeall leis, gan a bheith ag tabhairt aire i ndáiríre cibé an raibh sé ag teastáil go praiticiúil.

Féach duit féin, mura n-ardaíonn an gá atá le cineálacha lom (int, fada, etc.) mar rud bunúsach ceisteanna - ar deireadh thiar ní mór iad a chur i bhfeidhm de láimh - mar shampla, déanaimis iarracht díorthú astu. veicteoir. Is é sin, i ndáiríre, eagar, má ghlaonn tú ar na rudaí a thagann dá bharr faoina n-ainmneacha cearta.

Ach ar dtús

Cur síos gairid ar fhothacar de chomhréir TL dóibh siúd nach léann an doiciméadú oifigiúil

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;

Tosaíonn sainmhíniú i gcónaí dearthóir, ina dhiaidh sin go roghnach (i gcleachtas - i gcónaí) tríd an tsiombail # Ní mór a bheith CRC32 ón teaghrán tuairiscithe normalaithe den chineál seo. Ansin déantar cur síos ar na réimsí; má tá siad ann, féadfaidh an cineál a bheith folamh. Críochnaíonn sé seo go léir le comhartha comhionann, ainm an chineáil lena mbaineann an cruthaitheoir seo - is é sin, i ndáiríre, an fochineál -. Is é an fear ar dheis an comhartha comhionann polymorphic - is é sin, is féidir roinnt cineálacha sonracha a fhreagraíonn dó.

Má tharlaíonn an sainmhíniú tar éis na líne ---functions---, ansin fanfaidh an chomhréir mar an gcéanna, ach beidh an bhrí difriúil: beidh an cruthaitheoir mar ainm na feidhme RPC, beidh na réimsí ina paraiméadair (go maith, is é sin, fanfaidh sé díreach mar an gcéanna struchtúr tugtha, mar a thuairiscítear thíos , ní bheidh anseo ach an bhrí a shanntar), agus an "cineál polymorphic" - cineál an toraidh a tugadh ar ais. True, fanfaidh sé fós polymorphic - díreach sainithe san alt ---types---, ach ní dhéanfar an cruthaitheoir seo a mheas. Na cineálacha feidhmeanna ar a dtugtar a ró-ualú ag a n-argóintí, i.e. Ar chúis éigin, ní dhéantar foráil san TL do roinnt feidhmeanna a bhfuil an t-ainm céanna orthu ach sínithe éagsúla, mar atá i C++.

Cén fáth "tógálaí" agus "polymorphic" más rud é nach bhfuil sé OOP? Bhuel, i ndáiríre, beidh sé níos éasca do dhuine smaoineamh ar seo i dtéarmaí OOP - cineál polymorphic mar aicme teibí, agus is iad na tógálaithe a ranganna sliocht díreacha, agus final i dtéarmaí roinnt teangacha. Go deimhin, ar ndóigh, anseo amháin cosúlacht le fíor-mhodhanna cruthaitheoir ró-ualaithe i dteangacha ríomhchlárúcháin OO. Ós rud é nach bhfuil anseo ach struchtúir sonraí, níl aon mhodhanna ann (cé go bhfuil an cur síos ar fheidhmeanna agus modhanna níos faide in ann mearbhall a chruthú sa cheann go bhfuil siad ann, ach is ábhar difriúil é sin) - is féidir leat smaoineamh ar chruthaitheoir mar luach ó a á thógáil clóscríobh agus tú ag léamh sruth beart.

Conas a tharlaíonn sé seo? Feiceann an díserialtóir, a léann 4 bytes i gcónaí, an luach 0xcrc32 - agus tuigeann sé cad a tharlóidh ina dhiaidh sin field1 le cineál int, i.e. léann go díreach 4 bytes, ar an réimse forshuite leis an gcineál PolymorType léigh. Feiceann 0x2crc32 agus tuigeann sé go bhfuil dhá réimse eile, ar dtús long, rud a chiallaíonn go léann muid 8 bytes. Agus ansin arís cineál casta, atá deserialized ar an mbealach céanna. Mar shampla, Type3 D'fhéadfaí a dhearbhú sa chiorcad chomh luath agus is dhá tógálaí, faoi seach, ansin ní mór dóibh freastal ar an oiread 0x12abcd34, ina dhiaidh sin ní mór duit 4 beart eile a léamh int0x6789cdef, ina dhiaidh sin ní bheidh aon rud ann. Rud ar bith eile - ní mór duit eisceacht a chaitheamh. Ar aon nós, tar éis é seo a théann muid ar ais chuig léamh 4 bytes int corrlaigh field_c в constructorTwo agus leis sin críochnaímid ag léamh ár PolymorType.

Ar deireadh, má fhaigheann tú gafa 0xdeadcrc le haghaidh constructorThree, ansin éiríonn gach rud níos casta. Is é ár gcéad réimse bit_flags_of_what_really_present le cineál # - go deimhin, níl anseo ach ailias don chineál nat, rud a chiallaíonn "uimhir nádúrtha". Is é sin, i ndáiríre, slánuimhir neamhshínithe, dála an scéil, an t-aon chás nuair a tharlaíonn uimhreacha gan síniú i gciorcaid réadacha. Mar sin, is é seo chugainn tógáil le comhartha ceiste, rud a chiallaíonn go bhfuil an réimse seo - ní bheidh sé i láthair ar an sreang ach amháin má tá an giotán comhfhreagrach socraithe sa réimse dá dtagraítear (thart ar nós oibreoir trínártha). Mar sin, déanaimis glacadh leis gur socraíodh an giotán seo, rud a chiallaíonn go gcaithfimid réimse cosúil le léamh a thuilleadh Type, a bhfuil inár sampla 2 tógálaithe. Tá ceann amháin folamh (nach bhfuil ann ach an t-aitheantóir), tá réimse ag an gceann eile ids le cineál ids:Vector<long>.

D'fhéadfá smaoineamh go bhfuil an dá teimpléid agus generics sna buntáistí nó Java. Ach níl. Beagnach. seo an t-aon cheann gcás úsáid a bhaint as lúibíní uillinn i gciorcaid fhíor, agus úsáidtear é AMHÁIN le haghaidh Veicteoir. I sruth beart, beidh siad seo 4 CRC32 beart don chineál Veicteoir féin, i gcónaí mar an gcéanna, ansin 4 bytes - líon na n-eilimintí eagar, agus ansin na heilimintí sin iad féin.

Cuir leis seo go dtarlaíonn sraithiú i gcónaí i bhfocail 4 beart, is iolraí de gach cineál - déantar cur síos freisin ar na cineálacha ionsuite bytes и string le sraithiú láimhe den fhad agus an ailíniú seo faoi 4 - go maith, is cosúil go bhfuil sé gnáth agus fiú sách éifeachtach? Cé go n-éilítear TL a bheith ina serialization dénártha éifeachtach, go hifreann leo, leis an leathnú díreach faoi rud ar bith, fiú luachanna Boole agus teaghráin aon-charachtar go 4 bytes, beidh JSON fós i bhfad thicker? Féach, is féidir fiú réimsí neamhriachtanacha a scipeáil le bratacha giotán, tá gach rud sách maith, agus fiú insínte don todhchaí, mar sin cén fáth nach gcuirfidh tú réimsí roghnacha nua leis an tógálaí níos déanaí?..

Ach ní hea, mura léann tú mo chur síos gairid, ach an doiciméadú iomlán, agus smaoineamh ar an gcur i bhfeidhm. Ar an gcéad dul síos, ríomhtar CRC32 an tógálaí de réir líne normalaithe tuairisc téacs na scéime (bain spás bán breise, etc.) - mar sin má chuirtear réimse nua leis, athrófar an líne tuairisc chineáil, agus mar sin a CRC32 agus , dá bharr sin, sraithiú. Agus cad a dhéanfadh an seanchliant dá bhfaigheadh ​​sé réimse le bratacha nua socraithe, agus nach bhfuil a fhios aige cad atá le déanamh leo ina dhiaidh sin?..

Ar an dara dul síos, déanaimis cuimhneamh CRC32, a úsáidtear anseo go bunúsach mar feidhmeanna hash a chinneadh go huathúil cén cineál atá á (dí)shraithiú. Anseo táimid ag tabhairt aghaidhe ar fhadhb na n-imbhuailtí - agus ní hea, níl an dóchúlacht i gceann 232, ach i bhfad níos mó. Cé a mheabhraigh go bhfuil CRC32 deartha chun earráidí sa chainéal cumarsáide a bhrath (agus a cheartú), agus dá réir sin feabhsaítear na hairíonna seo chun dochair do dhaoine eile? Mar shampla, is cuma leis faoi bhearta a atheagrú: má ríomhann tú CRC32 ó dhá líne, sa dara háit mhalartóidh tú na chéad 4 bhearta leis na 4 bhearta eile - beidh sé mar an gcéanna. Nuair is teaghráin téacs ón aibítir Laidineach é ár n-ionchur (agus beagán poncaíochta), agus nach bhfuil na hainmneacha seo randamach go háirithe, méadaíonn an dóchúlacht go ndéanfaí athchóiriú dá leithéid go mór.

Dála an scéil, cé a sheiceáil cad a bhí ann? i ndáiríre CRC32? Bhí feidhm hash ag ceann de na cóid foinse luatha (fiú roimh Waltman) a d'iolraigh gach carachtar faoin uimhir 239, a raibh grá ag na daoine seo uirthi, ha ha!

Ar deireadh, ceart go leor, thuig muid go tógálaithe le cineál réimse Vector<int> и Vector<PolymorType> beidh CRC32 difriúil aige. Cad mar gheall ar fheidhmíocht ar líne? Agus ó thaobh teoiriciúil de, an éiríonn sé seo mar chuid den chineál? Ligean le rá go n-éiríonn linn raon de dheich míle uimhreacha, chomh maith Vector<int> tá gach rud soiléir, an fad agus ceann eile 40000 bytes. Agus más rud é seo Vector<Type2>, nach bhfuil ann ach réimse amháin int agus tá sé ina n-aonar sa chineál - an gá dúinn a dhéanamh arís 10000xabcdef0 34 uair agus ansin 4 bytes int, nó tá an teanga in ann é a INDEPEND dúinn ón cruthaitheoir fixedVec agus in ionad 80000 beart, aistrigh arís ach 40000?

Ní ceist theoiriciúil dhíomhaoin í seo ar chor ar bith - samhlaigh go bhfaighidh tú liosta úsáideoirí grúpa, a bhfuil aitheantas, céadainm, sloinne ag gach duine acu - is féidir go mbeadh difríocht shuntasach idir an méid sonraí a aistrítear thar nasc soghluaiste. Is é éifeachtacht sraitheachú Telegram go beacht a fhógraítear dúinn.

Mar sin ...

Veicteoir, nár scaoileadh riamh

Má dhéanann tú iarracht wade trí na leathanaigh cur síos ar chomhcheangail agus mar sin de, feicfidh tú go bhfuil veicteoir (agus fiú maitrís) ag iarraidh go foirmiúil a bheith aschur trí tuples de roinnt bileoga. Ach sa deireadh déanann siad dearmad, déantar an chéim dheireanach a scipeáil, agus tugtar sainmhíniú simplí ar veicteoir, nach bhfuil ceangailte fós le cineál. Céard atá ort? I dteangacha cláir, go háirithe cinn feidhmiúla, tá sé tipiciúil go leor cur síos a dhéanamh ar an struchtúr go hathchúrsach - tuigfidh an tiomsaitheoir lena mheastóireacht leisciúil agus déanfaidh sé gach rud é féin. I dteanga sraithiú sonraí is é an rud atá ag teastáil ná ÉIFEACHTÚLACHT: is leor cur síos simplí a dhéanamh liosta, i.e. struchtúr dhá eilimint - is eilimint sonraí é an chéad cheann, is é an dara ceann an struchtúr céanna féin nó spás folamh don eireaball (pacáiste (cons) i Lisp). Ach beidh sé seo ag teastáil ar ndóigh gach Caitheann eilimint 4 beart breise (CRC32 i gcás TL) chun cur síos a dhéanamh ar a chineál. Is féidir cur síos a dhéanamh go héasca ar eagar freisin méid seasta, ach i gcás sraith d'fhad anaithnid roimh ré, briseann muid amach.

Mar sin, ós rud é nach gceadaíonn TL veicteoir a aschur, b'éigean é a chur leis ar an taobh. Sa deireadh deir an doiciméadú:

Úsáideann sraithiú i gcónaí an “veicteoir” cruthaitheoir céanna (const 0x1cb5c415 = crc32("veicteoir t:Cineál # [ t ] = Veicteoir t") nach bhfuil ag brath ar luach sonrach na hathróige de chineál t.

Níl baint ag luach an pharaiméadar roghnach t leis an sraithiú toisc go bhfuil sé díorthaithe ón gcineál toraidh (a bhí ar eolas i gcónaí roimh an díscriosú).

Féach níos dlúithe: vector {t:Type} # [ t ] = Vector t - ach áit ar bith Ní deir an sainmhíniú seo féin go gcaithfidh an chéad uimhir a bheith comhionann le fad an veicteora! Agus ní thagann sé ó áit ar bith. Is ábhar é seo nach mór a choinneáil i gcuimhne agus a chur i bhfeidhm le do lámha. In áiteanna eile, luann an doiciméadú go hionraic fiú nach bhfuil an cineál fíor:

Is “cineál” é an pseudotype polymorphic Veicteoir t arb é a luach seicheamh luachanna d’aon chineál t, bíodh sé i mboscaí nó lom.

... ach ní dhíríonn sé air. Nuair a shocraíonn tú, tuirseach ag siúl trí shíneadh na matamaitice (b’fhéidir fiú ó chúrsa ollscoile) éirí as agus féachaint ar conas oibriú leis go praiticiúil, is é an tuiscint atá fágtha i do cheann ná go bhfuil sé seo tromchúiseach. Matamaitic ag croílár, bhí sé invented go soiléir ag Daoine Cool (beirt matamaiticeoirí - buaiteoir ACM), agus ní hamháin duine ar bith. Tá an sprioc - a thaispeáint as - bainte amach.

Dála an scéil, mar gheall ar an uimhir. Cuirfimid é sin i gcuimhne duit # is comhchiall é nat, uimhir nádúrtha:

Tá nathanna cineáil (cineál-expr) agus nathanna uimhriúla (nat-expr). Mar sin féin, sainítear iad ar an mbealach céanna.

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

ach sa ghramadach cuirtear síos orthu ar an mbealach céanna, i.e. Ní mór an difríocht seo a mheabhrú arís agus a chur i bhfeidhm de láimh.

Bhuel, tá, cineálacha teimpléid (vector<int>, vector<User>) a bhfuil comh-aitheantóir acu (#1cb5c415), i.e. má tá a fhios agat go bhfógraítear an glao mar

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

ansin níl tú ag fanacht ach le veicteoir amháin, ach le veicteoir úsáideoirí. Níos cruinne, Ba chóir fan - i bhfíorchód, beidh cruthaitheoir ag gach eilimint, más rud é nach cineál lom é, agus ar bhealach maith i gcur i bhfeidhm bheadh ​​​​sé riachtanach a sheiceáil - ach cuireadh go díreach sinn i ngach eilimint den veicteoir seo. cineál sin? Cad a tharlaíonn má bhí sé de chineál éigin PHP, inar féidir le sraith go bhfuil cineálacha éagsúla in eilimintí éagsúla?

Ag an bpointe seo tosaíonn tú ag smaoineamh - an bhfuil a leithéid de TL riachtanach? B'fhéidir go bhféadfaí srathachtóir daonna a úsáid don tralaí, an protobuf céanna a bhí ann cheana féin? Ba é sin an teoiric, a ligean ar breathnú ar chleachtas.

Feidhmithe TL atá sa chód faoi láthair

Rugadh TL i ndoimhneacht VKontakte fiú roimh na himeachtaí cáiliúla le díol sciar Durov agus (B'fhéidir), fiú sular thosaigh forbairt Telegram. Agus i bhfoinse oscailte cód foinse an chéad chur chun feidhme Is féidir leat teacht ar a lán de na crutches greannmhar. Agus cuireadh an teanga féin i bhfeidhm ansin níos iomláine ná mar atá sí anois i dTeileagram. Mar shampla, ní úsáidtear hashes ar chor ar bith sa scéim (a chiallaíonn pseudotype ionsuite (cosúil le veicteoir) le hiompar claonta). Nó

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

ach déanaimis machnamh, ar mhaithe le hiomláine, ar éabhlóid Ghorm na Smaointe a rianú, mar a déarfá.

#define ZHUKOV_BYTES_HACK

#ifdef ZHUKOV_BYTES_HACK

/* dirty hack for Zhukov request */

Nó an ceann álainn seo:

    static const char *reserved_words_polymorhic[] = {

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

      };

Baineann an blúire seo le teimpléid mar:

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

Is é seo an sainmhíniú ar chineál teimpléad hashmap mar veicteoir de int - péirí Cineál. I C++ bheadh ​​cuma mar seo air:

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

mar sin, alpha - eochairfhocal! Ach amháin i C++ is féidir leat T a scríobh, ach ba cheart duit alfa, béite a scríobh... Ach gan níos mó ná 8 paraiméadair, sin an áit a chríochnaíonn an fantaisíocht. Dealraíonn sé gur tharla roinnt comhráite mar seo uair amháin i St Petersburg:

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

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

Ach bhain sé seo leis an gcéad chur i bhfeidhm foilsithe de TL “go ginearálta”. Gabhaimis ar aghaidh go dtí breithniú a dhéanamh ar fheidhmiúcháin sna cliaint Telegram iad féin.

Focal a Vasily:

Vasily, [09.10.18 17:07] An chuid is mó ar fad, tá an t-asal te mar chruthaigh siad a bunch de astarraingtí, agus ansin hammered bolt orthu, agus clúdaithe an gineadóir cód le crutches.
Mar thoradh air sin, ar dtús ó duga pilot.jpg
Ansin ón gcód dzhekichan.webp

Ar ndóigh, ó dhaoine atá eolach ar halgartaim agus matamaitic, is féidir linn a bheith ag súil go bhfuil Aho, Ullmann léite acu, agus go bhfuil siad eolach ar na huirlisí atá ina gcaighdeán de facto sa tionscal le blianta fada anuas chun a dtiomsaitheoirí DSL a scríobh, ceart?..

Le teileagram-cli is Vitaly Valtman, mar is féidir a thuiscint ó tharla an fhormáid TLO lasmuigh dá teorainneacha (cli), ball den fhoireann - anois tá leabharlann le haghaidh parsáil TL leithdháilte ar leithligh, cad é an tuiscint atá uirthi Parsálaí TL?..

16.12 04:18 Vasily: Sílim nár mháistir duine éigin lex+yacc
16.12 04:18 Vasily: Ní féidir liom a mhíniú a mhalairt
16.12 04:18 Vasily: bhuel, nó íocadh iad as líon na línte i VK
16.12 04:19 Vasily: 3k+ línte srl<censored> in ionad parsálaí

B'fhéidir eisceacht? A ligean ar a fheiceáil conas dhéanann Seo é an cliant OIFIGIÚIL - 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+ líne i Python, cúpla nathanna rialta + cásanna speisialta cosúil le veicteoir, atá, ar ndóigh, dearbhaithe sa scéim mar ba chóir de réir chomhréir TL, ach bhí siad ag brath ar an chomhréir seo chun é a pharsáil... Éiríonn an cheist, cén fáth go raibh sé ar fad miracle?иTá sé níos sraitheanna mura bhfuil aon duine chun é a pharsáil de réir na gcáipéisí ar aon nós?!

Dála an scéil... Cuimhnigh gur labhair muid faoi sheiceáil CRC32? Mar sin, i gineadóir cód Deisce Telegram tá liosta eisceachtaí do na cineálacha sin ina bhfuil an CRC32 ríofa nach ionann leis an gceann a léirítear sa léaráid!

Vasily, [18.12/22 49:XNUMX] agus anseo ba mhaith liom smaoineamh an bhfuil a leithéid de TL ag teastáil
dá mba mhian liom praiseach a dhéanamh le feidhmiúcháin mhalartacha, chuirfinn tús le briseadh líne a chur isteach, brisfidh leath de na parsálaithe ar shainmhínithe illíne
tdesktop, áfach, freisin

Cuimhnigh an pointe faoi aon-línéar, cuirfimid ar ais chuige beagán níos déanaí.

Ceart go leor, tá teileagram-cli neamhoifigiúil, tá Telegram Desktop oifigiúil, ach cad faoi na cinn eile? Cé a fhios?.. Sa chód cliant Android ní raibh aon parsálaí scéimre ar chor ar bith (a ardaíonn ceisteanna faoi foinse oscailte, ach tá sé seo le haghaidh an dara cuid), ach bhí roinnt píosaí greannmhar eile de chód, ach níos mó orthu sa fo-alt thíos.

Cad iad na ceisteanna eile a ardaíonn sraithiú go praiticiúil? Mar shampla, rinne siad a lán rudaí, ar ndóigh, le réimsí giotán agus réimsí coinníollach:

Vasily: flags.0? true
Ciallaíonn sé seo go bhfuil an réimse i láthair agus cothrom fíor má tá an bhratach socraithe

Vasily: flags.1? int
ciallaíonn sé sin go bhfuil an réimse i láthair agus gur gá é a dhíshrianú

Vasily: Asal, ná bíodh imní ort faoi cad atá ar siúl agat!
Vasily: Tá tagairt áit éigin sa doiciméad gur cineál lom nialasach é fíor, ach nach féidir aon rud a chur le chéile óna ndoiciméad
Vasily: Sna feidhmeanna foinse oscailte ní hé seo an cás ach an oiread, ach tá a lán crutches agus tacaíochtaí

Cad faoi Telethon? Ag breathnú ar aghaidh chuig an ábhar MTProto, sampla - sa doiciméadú tá píosaí den sórt sin, ach an comhartha % ní dhéantar cur síos air ach mar “a fhreagraíonn do chineál lom ar leith”, i.e. sna samplaí thíos tá earráid nó rud éigin gan doiciméadú:

Vasily, [22.06.18 18:38] In aon áit amháin:

msg_container#73f1f8dc messages:vector message = MessageContainer;

I gcás eile:

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

Agus is dhá dhifríocht mhór iad seo, sa saol fíor tagann veicteoir de chineál éigin naked

Ní fhaca mé sainmhíniú veicteora lom agus níor tháinig mé trasna ar cheann amháin

Scríobhtar an anailís de láimh sa teileathón

Ina léaráid déantar trácht ar an sainmhíniú msg_container

Arís, tá an cheist fós faoi %. Ní chuirtear síos air.

Vadim Goncharov, [22.06.18 19:22] agus i tdesktop?

Vasily, [22.06.18 19:23] Ach is dócha nach n-íosfaidh a gcuid parsálaí TL ar innill rialta é seo ach an oiread

// parsed manually

Astarraingt álainn is ea TL, ní chuireann éinne i bhfeidhm go hiomlán é

Agus níl % ina leagan den scéim

Ach anseo tá an doiciméadú salach ar a chéile, mar sin idk

Bhí sé le fáil sa ghramadach, d'fhéadfadh siad dearmad go simplí chun cur síos ar an séimeantaice

Chonaic tú an doiciméad ar TL, ní féidir leat a dhéanamh amach gan leath lítear

“Bhuel, déarfainn,” déarfaidh léitheoir eile, “cáineann tú rud éigin, mar sin taispeáin dom conas ba cheart é a dhéanamh.”

Freagraíonn Vasily: “Maidir leis an parsálaí, is maith liom rudaí mar

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

ar bhealach níos fearr ná

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

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

            (?:s              # After that, we want to match its arguments (name:type)
                {?             # For handling the start of the '{X:Type}' case
                w+            # The argument name will always be an alpha-only name
                :              # Then comes the separator between name:type
                [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)

seo an lexer UILE:

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

siúd. is simplí é a chur go réidh.”

Go ginearálta, mar thoradh air sin, luíonn an parsálaí agus an gineadóir cóid don fho-thacar de TL a úsáidtear go hiarbhír isteach i thart ar 100 líne gramadaí agus ~300 líne den ghineadóir (gach rud a chomhaireamh print's cód ginte), lena n-áirítear bunnies faisnéise cineáil le haghaidh inbhreathnaithe i ngach rang. Athraíonn gach cineál polymorphic isteach i mbunrang teibí folamh, agus faigheann tógálaithe oidhreacht uaidh agus tá modhanna acu chun sraithiú agus díshraithiú.

Easpa cineálacha sa teanga cineáil

Is rud maith é clóscríobh láidir, ceart? Ní hea, ní holivar é seo (cé gur fearr liom teangacha dinimiciúla), ach postulate laistigh de chreat TL. Bunaithe air, ba cheart don teanga gach cineál seiceála a sholáthar dúinn. Bhuel, ceart go leor, b'fhéidir nach bhfuil sé féin, ach a chur i bhfeidhm, ach ba chóir dó cur síos a dhéanamh orthu ar a laghad. Agus cén cineál deiseanna atá uainn?

Gcéad dul síos, srianta. Anseo feicimid sa doiciméadú le haghaidh uaslódáil comhaid:

Roinntear ábhar dénártha an chomhaid ina chodanna ansin. Caithfidh an méid céanna a bheith ag gach cuid ( páirt_mhéid ) agus ní mór na coinníollacha seo a leanas a chomhlíonadh:

  • part_size % 1024 = 0 (roinnte ar 1KB)
  • 524288 % part_size = 0 (Caithfidh 512KB a bheith inroinnte go cothrom de réir méid_pháirt)

Ní chaithfidh an chuid dheireanach na coinníollacha seo a shásamh, ar choinníoll go bhfuil a méid níos lú ná part_size.

Ba chóir go mbeadh uimhir sheicheamh ag gach cuid, comhad_cuid, le luach idir 0 agus 2,999.

Tar éis duit an comhad a dheighilt ní mór duit modh a roghnú chun é a shábháil ar an bhfreastalaí. Úsáid upload.saveBigFilePart i gcás go bhfuil méid iomlán an chomhaid níos mó ná 10 MB agus upload.saveFilePart le haghaidh comhaid níos lú.
[…] féadfar ceann de na hearráidí ionchuir sonraí seo a leanas a thabhairt ar ais:

  • FILE_PARTS_INVALID — Líon neamhbhailí páirteanna. Níl an luach idir 1..3000

An bhfuil aon chuid de seo sa léaráid? An bhfuil sé seo in iúl ar bhealach éigin ag baint úsáide as TL? Níl. Ach gabh mo leithscéal, bhí fiú Turbo Pascal de chuid an seanathair in ann cur síos a dhéanamh ar na cineálacha sonraithe raonta. Agus bhí a fhios aige rud amháin eile, ar a dtugtar anois níos fearr enum - cineál arb é atá ann líon seasta (beag) luachanna. I dteangacha cosúil le C - uimhriúil, tabhair faoi deara go dtí seo níor labhair muid ach faoi chineálacha uimhreacha. Ach tá eagair, teaghráin ann freisin ... mar shampla, bheadh ​​sé deas cur síos a dhéanamh nach féidir leis an teaghrán seo ach uimhir theileafóin a bheith ann, ceart?

Níl aon cheann de seo sa TL. Ach tá, mar shampla, i Scéimre JSON. Agus má d'fhéadfadh duine éigin eile a mhaíomh faoi inroinnteacht 512 KB, gur gá é seo a sheiceáil go fóill i gcód, ansin déan cinnte go bhfuil an cliant go simplí Ní féidir seol uimhir as raon 1..3000 (agus ní fhéadfadh an earráid chomhfhreagrach a bheith tagtha chun cinn) bheadh ​​​​sé indéanta, ceart?..

Dála an scéil, faoi earráidí agus luachanna tuairisceáin. Fiú iad siúd a d’oibrigh le TL doiléir a gcuid súl - ní raibh sé sin breacadh an lae orainne láithreach gach éinne is féidir le feidhm in TL, ní hamháin an cineál tuairiscithe tuairiscithe a thabhairt ar ais, ach earráid freisin. Ach ní féidir é seo a bhaint as an TL féin ar bhealach ar bith. Ar ndóigh, tá sé soiléir cheana féin agus níl aon ghá le rud ar bith go praiticiúil (cé go deimhin, is féidir RPC a dhéanamh ar bhealaí éagsúla, cuirfimid ar ais chuig seo níos déanaí) - ach cad mar gheall ar íonacht na gcoincheap Matamaitice de Chineálacha Teibí ón domhan neamhaí?.. Thóg mé suas an tug - mar sin mheaitseáil é.

Agus ar deireadh, cad faoi inléiteacht? Bhuel, ann, go ginearálta, ba mhaith liom tuairisc bíodh sé ceart sa scéimre (i scéimre JSON, arís, tá), ach má tá brú ort cheana féin, ansin cad mar gheall ar an taobh praiticiúil - ar a laghad ag féachaint go fánach ar dhifríochtaí le linn nuashonruithe? Féach duit féin ag samplaí fíor:

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

-message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;
+message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;

Braitheann sé ar gach duine, ach diúltaíonn GitHub, mar shampla, aird a tharraingt ar athruithe taobh istigh de línte fada den sórt sin. Is é an cluiche “aimsigh 10 ndifríochtaí”, agus is é an rud a fheiceann an inchinn láithreach ná go bhfuil an tús agus na foircinn sa dá shampla mar an gcéanna, ní mór duit a léamh go tedious áit éigin sa lár... I mo thuairim, nach bhfuil sé seo ach go teoiriciúil, ach amháin ó thaobh amhairc salach agus sloppy.

Dála an scéil, faoi íonacht an teoiric. Cén fáth a bhfuil gá againn le réimsí giotán? Ní cosúil go bhfuil siad pahnut olc ó thaobh teoiric cineáil? Tá an míniú le feiceáil i leaganacha níos luaithe den léaráid. Ar dtús, sea, sin mar a bhí, cruthaíodh cineál nua do gach sraothartach. Tá na bunghnéithe seo fós san fhoirm seo, mar shampla:

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;

Ach samhlaigh anois, má tá 5 réimse roghnacha agat i do struchtúr, ansin beidh 32 cineál ag teastáil uait le haghaidh gach rogha féideartha. Pléascadh comhcheangailte. Mar sin, bhris íonacht chriostail na teoirice TL arís i gcoinne an asail iarainn theilgthe ar réaltacht chrua an tsrathaithe.

Ina theannta sin, i roinnt áiteanna sáraíonn na guys seo a gcuid tíopeolaíocht féin. Mar shampla, i MTProto (an chéad chaibidil eile) is féidir an freagra a chomhbhrú le Gzip, tá gach rud go breá - ach amháin go sáraítear na sraitheanna agus an ciorcad. Arís eile, ní RpcResult é féin a baineadh amach, ach a raibh ann. Bhuel, cén fáth é seo a dhéanamh?.. Bhí orm gearradh isteach i magairlín ionas go n-oibreodh an comhbhrú áit ar bith.

Nó sampla eile, fuair muid amach earráid uair amháin - cuireadh é InputPeerUser in ionad InputUser. Nó vice versa. Ach d'oibrigh sé! Is é sin, ní raibh an freastalaí buartha faoin gcineál. Conas is féidir é seo a bheith? Is féidir an freagra a thabhairt dúinn le blúirí cód ó 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);

I bhfocail eile, is é seo an áit a ndéantar sraithiú Láimh, ní cód ginte! B'fhéidir go gcuirtear an freastalaí i bhfeidhm ar an mbealach céanna?.. I bprionsabal, oibreoidh sé seo má dhéantar é uair amháin, ach conas is féidir tacú leis níos déanaí le linn nuashonruithe? An é seo an fáth ar ceapadh an scéim? Agus anseo bogaimid ar aghaidh go dtí an chéad cheist eile.

Leagan. Sraitheanna

Ní féidir ach tuairimíocht a dhéanamh ar an bhfáth ar a dtugtar sraitheanna ar na leaganacha scéimre bunaithe ar stair na schematics foilsithe. De réir dealraimh, cheap na húdair ar dtús go bhféadfaí rudaí bunúsacha a dhéanamh trí leas a bhaint as an scéim gan athrú, agus go dtí gur ghá, le haghaidh iarratais ar leith, léirigh siad go raibh siad á ndéanamh ag baint úsáide as leagan eile. I bprionsabal, fiú smaoineamh maith - agus beidh an nua, mar a bhí, "measctha", cisealta ar bharr na sean. Ach a ligean ar a fheiceáil conas a rinneadh é. Fíor, ní raibh mé in ann breathnú air ón tús - tá sé greannmhar, ach níl an léaráid den bhunchiseal ann. Cuireadh tús leis na sraitheanna le 2. Insíonn an doiciméadú dúinn faoi ghné speisialta TL:

Má thacaíonn cliant le Sraith 2, ní mór an cruthaitheoir seo a leanas a úsáid:

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

Go praiticiúil, ciallaíonn sé seo go roimh gach glao API, slánuimhir leis an luach 0x289dd1f6 ní mór é a chur leis roimh uimhir an mhodha.

Fuaimeanna gnáth. Ach cad a tharla ina dhiaidh sin? Ansin chuma

invokeWithLayer3#b7475268 query:!X = X;

Mar sin, cad é seo chugainn? Mar a d’fhéadfá buille faoi thuairim,

invokeWithLayer4#dea0d430 query:!X = X;

Greannmhar? Níl, tá sé ró-luath le gáire, smaoineamh ar an bhfíric go gach ceann acu ní mór iarratas ó chiseal eile a bheith fillte i gcineál speisialta den sórt sin - má tá siad uile difriúil duitse, conas eile is féidir leat iad a idirdhealú? Agus is modh éifeachtach go leor é 4 beart a chur isteach chun tosaigh. Mar sin,

invokeWithLayer5#417a57ae query:!X = X;

Ach is léir go dtiocfaidh bacchanalia de shaghas éigin air seo tar éis tamaill. Agus tháinig an réiteach:

Nuashonrú: Ag tosú le Sraith 9, modhanna cúntóra invokeWithLayerN is féidir a úsáid ach amháin in éineacht le initConnection

Hooray! Tar éis 9 leagan, tháinig muid ar deireadh leis an méid a rinneadh i bprótacail Idirlín ar ais sna 80í - aontú ar an leagan uair amháin ag tús an nasc!

Mar sin, cad atá le teacht? ..

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

Ach anois is féidir leat gáire fós. Ach amháin tar éis 9 sraithe eile, cuireadh cruthaitheoir uilíoch le uimhir leagain leis ar deireadh, rud nach mór a ghlaoch ach uair amháin ag tús an cheangail, agus ba chosúil go raibh brí na sraitheanna imithe, anois níl sé ach leagan coinníollach, cosúil le i ngach áit eile. Fadhb réitithe.

Díreach?..

Vasily, [16.07.18 14:01] Fiú amháin ar an Aoine shíl mé:
Seolann an freastalaí teilifíse imeachtaí gan iarratas. Ní mór iarratais a bheith fillte in InvokeWithLayer. Ní fhillteann an freastalaí nuashonruithe; níl aon struchtúr ann chun freagraí agus nuashonruithe a fhilleadh.

Iad siúd. ní féidir leis an gcliant an ciseal ina dteastaíonn nuashonruithe a shonrú

Vadim Goncharov, [16.07.18 14:02] nach rud é InvokeWithLayer i bprionsabal?

Vasily, [16.07.18 14:02] Is é seo an t-aon bhealach

Vadim Goncharov, [16.07.18 14:02] ba chóir a chiallaíonn go bunúsach aontú ar an ciseal ag tús an tseisiúin

Dála an scéil, leanann sé nach gcuirtear íosghrádú cliant ar fáil

Nuashonruithe, i.e. cineál Updates sa scéim, is é seo a sheolann an freastalaí chuig an gcliant ní mar fhreagra ar iarratas API, ach go neamhspleách nuair a tharlaíonn teagmhas. Is ábhar casta é seo a phléifear i bpost eile, ach faoi láthair tá sé tábhachtach go mbeadh a fhios go sábhálann an freastalaí Nuashonruithe fiú nuair a bhíonn an cliant as líne.

Dá bhrí sin, má dhiúltaíonn tú a wrap gach pacáiste chun a leagan a chur in iúl, eascraíonn na fadhbanna féideartha seo a leanas go loighciúil:

  • seolann an freastalaí nuashonruithe chuig an gcliant fiú sula gcuireann an cliant in iúl cén leagan a dtacaíonn sé leis
  • cad ba cheart dom a dhéanamh tar éis an cliant a uasghrádú?
  • ráthaíochtaínach n-athróidh tuairim an fhreastalaí faoin uimhir ciseal le linn an phróisis?

An gceapann tú gur tuairimíocht teoiriciúil amháin é seo, agus go praiticiúil ní féidir leis seo tarlú, toisc go bhfuil an freastalaí scríofa i gceart (ar a laghad, déantar tástáil mhaith air)? Ha! Is cuma conas atá sé!

Is é seo go díreach a bhí ar siúl againn i mí Lúnasa. Ar an 14 Lúnasa, bhí teachtaireachtaí ann go raibh rud éigin á nuashonrú ar na freastalaithe Telegram ... agus ansin sna logaí:

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.

agus ansin roinnt meigibheart de rianta cruachta (go maith, socraíodh an logáil ag an am céanna). Tar éis an tsaoil, mura n-aithnítear rud éigin i do TL, tá sé dénártha trí shíniú, níos faide síos an líne GACH Téann, beidh díchódaithe dodhéanta. Cad ba cheart duit a dhéanamh i gcás den sórt sin?

Bhuel, is é an chéad rud a thagann chun cuimhne aon duine ná dícheangal agus triail a bhaint as arís. Níor chabhraigh. Táimid ag google CRC32 - d'éirigh leo seo a bheith ina rudaí ó scéim 73, cé gur oibrigh muid ar 82. Breathnaímid go cúramach ar na logaí - tá aitheantóirí ó dhá scéim éagsúla!

B'fhéidir go bhfuil an fhadhb amháin inár gcliant neamhoifigiúil? Ní hea, seolann muid Telegram Desktop 1.2.17 (leagan a soláthraíodh i roinnt dáiltí Linux), scríobhann sé chuig an logáil Eisceacht: MTP Cineál id gan choinne #b5223b0f léite i MTPMessageMedia…

Cáineadh prótacal agus cur chuige eagraíochtúil Telegram. Cuid 1, teicniúil: taithí ar chliant a scríobh ón tús - TL, MT

Léirigh Google gur tharla fadhb den chineál céanna cheana féin do cheann de na cliaint neamhoifigiúla, ach ansin bhí na huimhreacha leagan agus, dá réir sin, na boinn tuisceana difriúil ...

Mar sin, cad ba cheart dúinn a dhéanamh? Scoilt Vasily agus mé suas: rinne sé iarracht an ciorcad a nuashonrú go 91, chinn mé fanacht cúpla lá agus iarracht a dhéanamh ar 73. D'oibrigh an dá mhodh, ach ós rud é go bhfuil siad eimpíreach, níl aon tuiscint ar cé mhéad leagan suas nó síos a theastaíonn uait. chun léim , nó cé chomh fada is gá duit fanacht .

Níos déanaí bhí mé in ann an cás a atáirgeadh: seolann muid an cliant, é a mhúchadh, an ciorcad a ath-thiomsú go ciseal eile, atosú, an fhadhb a ghabháil arís, filleadh ar an gceann roimhe seo - oops, gan aon athrú ciorcad agus atosaíonn an cliant ar feadh a. cabhróidh cúpla nóiméad. Gheobhaidh tú meascán de struchtúir sonraí ó shraitheanna éagsúla.

Míniú? Mar is féidir leat buille faoi thuairim ó na hairíonna indíreacha éagsúla, is éard atá sa fhreastalaí go leor próisis de chineálacha éagsúla ar mheaisíní éagsúla. Is dóichí gur chuir an freastalaí atá freagrach as “buffering” isteach sa scuaine an méid a thug a chuid ceannairí é, agus thug siad é sa scéim a bhí i bhfeidhm tráth na giniúna. Agus go dtí go raibh an scuaine seo “lofa”, ní fhéadfaí aon rud a dhéanamh faoi.

B'fhéidir... ach is crutch uafásach é seo?!... Ní hea, roimh smaoineamh ar smaointe craiceáilte, déanaimis féachaint ar chód na gcliant oifigiúil. Sa leagan Android ní aimsímid aon pharsálaí TL, ach aimsímid comhad mór (diúltaíonn GitHub teagmháil a dhéanamh leis) le (de)srathú. Seo iad na gearrthóga cód:

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

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

Hmm... tá cuma fhiáin air. Ach, is dócha, tá an cód a ghintear, ansin ceart go leor?.. Ach tacaíonn sé cinnte gach leagan! Fíor, níl sé soiléir cén fáth go bhfuil gach rud measctha le chéile, comhráite rúnda, agus gach cineál _old7 ar bhealach nach bhfuil cuma giniúna meaisín... Ar an mórgóir, áfach, bhí mé gafa

TL_message_layer104
TL_message_layer104_2
TL_message_layer104_3

Guys, nach féidir leat a chinneadh fiú cad atá taobh istigh de shraith amháin?! Bhuel, ceart go leor, déanaimis a rá gur scaoileadh “beirt” le hearráid, bhuel, a tharlaíonn sé, ach TRÍ?.. Ar an bpointe boise, an raic chéanna arís? Cén cineál pornagrafaíochta é seo, faraor?..

I gcód foinse Telegram Desktop, dála an scéil, tarlaíonn rud den chineál céanna - más amhlaidh, ní athraíonn roinnt geallúintí i ndiaidh a chéile leis an scéim a líon ciseal, ach rud éigin a shocrú. I gcoinníollacha nach bhfuil foinse oifigiúil sonraí ann don scéim, cén áit ar féidir é a fháil, seachas cód foinse an chliaint oifigiúil? Agus má thógann tú as sin é, ní féidir leat a bheith cinnte go bhfuil an scéim iomlán ceart go dtí go ndéanann tú na modhanna go léir a thástáil.

Conas is féidir é seo a thástáil fiú? Tá súil agam go roinnfidh lucht leanúna na dtástálacha aonaid, feidhmiúla agus eile sna tuairimí.

Ceart go leor, déanaimis féachaint ar phíosa cód eile:

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;

Tugann an trácht seo “de láimh” le fios nár scríobhadh ach cuid den chomhad seo de láimh (an féidir leat an tromluí cothabhála ar fad a shamhlú?), agus gur meaisín-ghinte an chuid eile. Mar sin féin, tagann ceist eile chun cinn - go bhfuil na foinsí ar fáil ní go hiomlán (a la GPL blobaí san eithne Linux), ach is ábhar é seo don dara cuid cheana féin.

Ach go leor. A ligean ar bogadh ar aghaidh go dtí an prótacal ar a bharr a ritheann an sraithiú seo go léir.

MT Proto

Mar sin, a ligean ar oscailt cur síos ginearálta и cur síos mionsonraithe ar an bprótacal agus is é an chéad rud a thagann trasna orainn ná an téarmaíocht. Agus le raidhse de gach rud. Go ginearálta, is cosúil gur gné dílseánaigh é seo de Telegram - ag glaoch ar rudaí go difriúil in áiteanna éagsúla, nó rudaí éagsúla le focal amháin, nó vice versa (mar shampla, i API ardleibhéil, má fheiceann tú pacáiste greamáin, níl sé cad a cheap tú).

Mar shampla, ciallaíonn “teachtaireacht” agus “seisiún” rud éigin difriúil anseo ná mar atá i ngnáthchomhéadan cliant Telegram. Bhuel, tá gach rud soiléir leis an teachtaireacht, d'fhéadfaí é a léirmhíniú i dtéarmaí OOP, nó go simplí ar a dtugtar an focal "paicéad" - tá sé seo leibhéal íseal, iompair, níl na teachtaireachtaí céanna agus sa chomhéadan, tá go leor teachtaireachtaí seirbhíse . Ach an seisiún... ach rudaí ar dtús ar dtús.

ciseal iompair

Is é an chéad rud iompar. Inseoidh siad dúinn faoi 5 rogha:

  • TCP
  • Soicéad Gréasáin
  • Soicéad Gréasáin thar HTTPS
  • HTTP
  • HTTPS

Vasily, [15.06.18 15:04] Tá iompar UDP ann freisin, ach níl sé doiciméadaithe

Agus TCP i dtrí leagan

Tá an chéad cheann cosúil le UDP thar TCP, cuimsíonn gach paicéad uimhir seicheamh agus crc
Cén fáth a bhfuil sé chomh pianmhar doiciméid a léamh ar thralaí?

Bhuel, tá sé anois TCP i 4 leagan cheana féin:

  • Ardaithe
  • Idirmheánach
  • Padded idirmheánach
  • Iomlán

Bhuel, ceart go leor, Padded idirmheánach do MTProxy, cuireadh é seo níos déanaí mar gheall ar imeachtaí aitheanta. Ach cén fáth ar dhá leagan eile (trí cinn san iomlán) nuair a d'fhéadfá a fháil le ceann amháin? Ní hionann na ceithre cinn go bunúsach ach amháin maidir le conas fad agus pálasta an phríomh-MTProto a shocrú, a phléifear tuilleadh:

  • i Giorraithe tá sé 1 nó 4 bytes, ach ní 0xef, ansin an comhlacht
  • i Meánrang is é seo 4 bytes ar fhad agus réimse, agus an chéad uair a chaithfidh an cliant a sheoladh 0xeeeeeeee a chur in iúl go bhfuil sé Meánrang
  • ina n-iomláine an ceann is andúile, ó thaobh líonraitheora de: fad, uimhir an tseichimh, agus NÍ AN CHEANN is mó atá MTProto, comhlacht, CRC32. Sea, tá sé seo go léir ar bharr TCP. A sholáthraíonn iompar iontaofa dúinn i bhfoirm sruth beart seicheamhach nach bhfuil gá le seichimh, go háirithe seiceálacha. Ceart go leor, anois beidh duine ag cur i gcoinne dom go bhfuil seiceálacha 16-giotán ag TCP, mar sin tarlaíonn éilliú sonraí. Go hiontach, ach i ndáiríre tá prótacal cripteagrafach againn le hashes níos faide ná 16 bytes, beidh na hearráidí seo go léir - agus fiú níos mó - gafa ag neamhréir SHA ag leibhéal níos airde. Níl aon phointe ag CRC32 anuas air seo.

Déanaimis comparáid idir Giorraithe, ina bhfuil beart amháin d’fhad indéanta, le Meánleibhéal, a thugann údar “I gcás go bhfuil gá le ailíniú sonraí 4-bheart,” rud nach bhfuil ciall leis. Cad é, creidtear go bhfuil ríomhchláraitheoirí Telegram chomh neamhinniúil sin nach féidir leo sonraí ó soicéad a léamh isteach i maolán ailínithe? Ní mór duit é seo a dhéanamh fós, mar is féidir leis an léitheoir aon líon beart a thabhairt ar ais duit (agus tá seachfhreastalaí ann freisin, mar shampla...). Nó ar an láimh eile, cén fáth a bloc Giorraithe má beidh stuáil hefty fós againn ar bharr 16 beart - shábháil 3 bytes uaireanta ?

Faigheann duine an tuiscint gur maith le Nikolai Durov rothaí a athchruthú, lena n-áirítear prótacail líonra, gan aon ghá praiticiúil.

Roghanna eile iompair, lena n-áirítear. Gréasáin agus MTProxy, ní mheasfaimid anois, b'fhéidir i bpost eile, má tá iarratas ann. Maidir leis an MTProxy céanna seo, ná déanaimis cuimhneamh ach anois go luath tar éis é a scaoileadh i 2018, d'fhoghlaim soláthraithe go tapa é a bhlocáil, a bhí beartaithe le haghaidh seachbhóthar blocáilDe réir méid pacáiste! Agus freisin ar an bhfíric go raibh an freastalaí MTProxy scríofa (arís ag Waltman) in C ró-cheangailte le sonraíochtaí Linux, cé nach raibh sé seo ag teastáil ar chor ar bith (deimhneoidh Phil Kulin), agus go ndéanfadh freastalaí den chineál céanna in Go nó Node.js oiriúnach i níos lú ná céad líne.

Ach bainfimid conclúidí faoi litearthacht theicniúil na ndaoine seo ag deireadh an ailt, tar éis saincheisteanna eile a bhreithniú. Chun anois, a ligean ar bogadh ar aghaidh go dtí OSI ciseal 5, seisiún - ar a chuir siad seisiún MTProto.

Eochracha, teachtaireachtaí, seisiúin, Diffie-Hellman

Chuir siad ann nach bhfuil sé go hiomlán i gceart... Ní seisiún an seisiún céanna atá le feiceáil sa chomhéadan faoi seisiúin Ghníomhach. Ach in ord.

Cáineadh prótacal agus cur chuige eagraíochtúil Telegram. Cuid 1, teicniúil: taithí ar chliant a scríobh ón tús - TL, MT

Mar sin fuaireamar teaghrán beart d'fhad aitheanta ón gciseal iompair. Is teachtaireacht criptithe nó gnáththéacs é seo - má táimid fós ag an bpríomhchéim comhaontaithe agus go bhfuil sé á dhéanamh i ndáiríre. Cé acu de na coincheapa ar a dtugtar “eochair” ar a bhfuil muid ag caint? Déanaimis an tsaincheist seo a shoiléiriú don fhoireann Telegram féin (Gabh mo leithscéal as mo dhoiciméadú féin a aistriú ó Bhéarla le hinchinn tuirseach ag 4 am, bhí sé níos éasca roinnt frásaí a fhágáil mar atá siad):

Tá dhá aonán ar a dtugtar Seisiún - ceann amháin in Chomhéadain na gcliant oifigiúil faoi “seisiúin reatha”, ina gcomhfhreagraíonn gach seisiún do ghléas iomlán / OS.
An dara - Seisiún MTProto, a bhfuil uimhir sheicheamh na teachtaireachta (i gciall ísealleibhéil) inti, agus a bhfuil féadfaidh sé maireachtáil idir naisc TCP éagsúla. Is féidir roinnt seisiún MTProto a shuiteáil ag an am céanna, mar shampla, chun íoslódáil comhad a bhrostú.

Idir an bheirt seo seisiúin tá coincheap ann údarú. Sa chás degenerate, is féidir linn a rá go Seisiún Chomhéadain mar an gcéanna le údarú, ach faraor, tá gach rud casta. Breathnaímid:

  • Gineann an t-úsáideoir ar an ngléas nua ar dtús údar_eochair agus cuireann sé chun cuntais é, mar shampla trí SMS - sin an fáth údarú
  • Tharla sé taobh istigh den chéad uair Seisiún MTProto, a bhfuil session_id istigh duit féin.
  • Ag an gcéim seo, an meascán údarú и session_id d'fhéadfaí a ghlaoch mar shampla - tá an focal seo le feiceáil i ndoiciméadú agus i gcód roinnt cliant
  • Ansin, is féidir leis an gcliant a oscailt roinnt seisiúin MTProto faoin gcéanna údar_eochair - chuig an DC céanna.
  • Ansin, lá amháin beidh ar an gcliant an comhad a iarraidh ó DC eile - agus don DC seo ginfear ceann nua údar_eochair !
  • A chur in iúl don chóras nach úsáideoir nua é atá ag clárú, ach mar an gcéanna údarú (Seisiún Chomhéadain), úsáideann an cliant glaonna API auth.exportAuthorization sa bhaile DC auth.importAuthorization sa DC nua.
  • Tá gach rud mar an gcéanna, d'fhéadfadh roinnt a bheith oscailte seisiúin MTProto (gach ceann lena chuid féin session_id) chuig an DC nua seo, faoi a údar_eochair.
  • Ar deireadh, b'fhéidir gur mhaith leis an gcliant Perfect Forward Secretcy. Gach údar_eochair bhí buan eochair - in aghaidh an DC - agus is féidir leis an gcliant glaoch auth.bindTempAuthKey le húsáid sealadach údar_eochair - agus arís, ach amháin temp_auth_eochair in aghaidh an DC, coiteann do chách seisiúin MTProto chuig an DC seo.

Tabhair faoi deara go salann (agus salainn sa todhchaí) freisin ceann ar údar_eochair siúd. roinnte idir gach duine seisiúin MTProto chuig an DC céanna.

Cad is brí le "idir naisc TCP éagsúla"? Mar sin ciallaíonn sé seo rud éigin mar fianán údaraithe ar láithreán gréasáin - leanann sé (marthanacht) go leor naisc TCP le freastalaí ar leith, ach lá amháin téann sé go dona. Murab ionann agus HTTP, déantar teachtaireachtaí MTProto laistigh de sheisiún a uimhriú agus a dhearbhú go seicheamhach; má tháinig siad isteach sa tollán, briseadh an nasc - tar éis nasc nua a bhunú, seolfaidh an freastalaí gach rud sa seisiún seo nach ndearna sé a sheachadadh san roimhe seo. Nasc TCP.

Mar sin féin, déantar achoimre ar an bhfaisnéis thuas tar éis míonna fada imscrúdaithe. Idir an dá linn, an bhfuilimid ag cur ár gcliant i bhfeidhm ón tús? - a ligean ar dul ar ais go dtí an tús.

Mar sin a ligean ar a ghiniúint auth_key ar Leaganacha Diffie-Hellman ó Telegram. Déanaimis iarracht na doiciméid a thuiscint...

Vasily, [19.06.18 20:05] data_with_hash := SHA1(sonraí) + sonraí + (aon bhearta randamacha); ionas go mbeidh an fad cothrom le 255 beart;
encrypted_data := RSA(data_with_hash, server_public_key); ardaítear uimhir fhada 255-beart (endian mór) go dtí an chumhacht riachtanach thar an modúl riachtanach, agus stóráiltear an toradh mar uimhir 256 beart.

Tá roinnt dope DH acu

Ní cosúil le DH duine sláintiúil
Níl dhá eochair phoiblí in dx

Bhuel, sa deireadh réitíodh é seo, ach d'fhan iarmhar - tá cruthúnas oibre déanta ag an gcliant go raibh sé in ann an uimhir a fhachtóir. Cineál cosanta i gcoinne ionsaithe DoS. Agus ní úsáidtear an eochair RSA ach uair amháin i dtreo amháin, go bunúsach le haghaidh criptithe new_nonce. Ach cé go n-éireoidh leis an oibríocht shimplí seo, cad a bheidh ort?

Vasily, [20.06.18/00/26 XNUMX:XNUMX] Níl an t-iarratas appid faighte agam fós

Chuir mé an t-iarratas seo chuig DH

Agus, sa duga iompair deir sé gur féidir leis freagairt le 4 bytes de chód earráide. Sin é an méid

Bhuel, dúirt sé liom -404, mar sin cad é?

Mar sin dúirt mé leis: "Glac do bullshit criptithe le eochair fhreastalaí le méarloirg mar seo, ba mhaith liom DH," agus d'fhreagair sé le dúr 404

Cad a shílfeá ar an bhfreagra freastalaí seo? Cad atá le déanamh? Níl aon duine le fiafraí (ach níos mó air sin sa dara cuid).

Anseo déantar an t-ús go léir ar an duga

Níl aon rud eile le déanamh agam, níor shamhlaigh mé ach uimhreacha a thiontú anonn is anall

Dhá uimhir 32 giotán. Phacáil mé iad cosúil le gach duine eile

Ach ní hea, is gá an dá cheann seo a chur leis an líne ar dtús mar BE

Vadim Goncharov, [20.06.18 15:49] agus mar gheall ar seo 404?

Vasily, [20.06.18 15:49] TÁ!

Vadim Goncharov, [20.06.18 15:50] mar sin ní thuigim cad is féidir leis “ní bhfuair sé”

Vasily, [20.06.18 15:50] thart

Níorbh fhéidir liom a leithéid de lobhadh a aimsiú ina phríomhfhachtóirí%)

Níor bhainistíomar fiú tuairisciú earráide

Vasily, [20.06.18 20:18] Ó, tá MD5 ann freisin. Cheana féin trí hashes éagsúla

Ríomhtar an eochair-mhéarloirg mar seo a leanas:

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

SHA1 agus sha2

Mar sin a ligean ar é a chur auth_key fuaireamar 2048 giotán i méid ag baint úsáide as Diffie-Hellman. Cad atá romhainn? Ansin aimsímid nach n-úsáidtear na 1024 giotán níos ísle den eochair seo ar bhealach ar bith ... ach déanaimis smaoineamh air seo faoi láthair. Ag an gcéim seo, tá rún roinnte againn leis an bhfreastalaí. Tá analóg den seisiún TLS bunaithe, ar nós imeachta an-chostasach é. Ach níl a fhios ag an bhfreastalaí fós cé muid féin! Níl go fóill, i ndáiríre. údarú. Iad siúd. má smaoinigh tú i dtéarmaí “login-password”, mar a rinne tú uair amháin in ICQ, nó ar a laghad “login-key”, mar atá i SSH (mar shampla, ar roinnt gitlab/github). Fuair ​​​​muid ceann gan ainm. Cad a tharlaíonn má insíonn an freastalaí dúinn “tá na huimhreacha gutháin seo seirbhísithe ag DC eile”? Nó fiú “tá cosc ​​ar d’uimhir theileafóin”? Is é an rud is fearr is féidir linn a dhéanamh ná an eochair a choinneáil le súil go mbeidh sé úsáideach agus nach mbeidh sé lofa faoin am sin.

Dála an scéil, “fuair” muid é le háirithintí. Mar shampla, an bhfuil muinín againn as an bhfreastalaí? Cad a tharlaíonn má tá sé falsa? Bheadh ​​gá le seiceálacha cripteagrafacha:

Vasily, [21.06.18 17:53] Cuireann siad ar fáil do chliaint soghluaiste chun uimhir 2kbit a sheiceáil le haghaidh prímhiúlacht%)

Ach níl sé soiléir ar chor ar bith, a stór

Vasily, [21.06.18 18:02] Ní deir an doiciméad cad atá le déanamh má tharlaíonn sé nach bhfuil sé simplí

Ní dúirt. A ligean ar a fheiceáil cad a dhéanann an cliant oifigiúil Android sa chás seo? A sin an méid (agus tá, tá an file ar fad suimiúil) - mar a deir siad, fágfaidh mé é seo díreach:

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

Níl, ar ndóigh tá sé fós ann roinnt Tá trialacha ann do phríomhacht uimhreach, ach go pearsanta níl dóthain eolais agam ar an matamaitic a thuilleadh.

Ceart go leor, fuair muid an eochair máistir. Chun logáil isteach, i.e. iarratais a sheoladh, ní mór duit a dhéanamh a thuilleadh criptithe, ag baint úsáide as AES.

Sainmhínítear an eochair teachtaireachta mar an 128 giotán lár de SHA256 an chomhlachta teachtaireachta (lena n-áirítear seisiún, ID na teachtaireachta, etc.), lena n-áirítear na bearta stuála, réamhullmhaithe ag 32 beart a tógadh ón eochair údaraithe.

Vasily, [22.06.18 14:08] Meán, soith, giotán

Faighte auth_key. Gach. Taobh amuigh díobh... níl sé soiléir ón doiciméad. Thig leat staidéar a dhéanamh ar an gcód foinse oscailte.

Tabhair faoi deara go n-éilíonn MTProto 2.0 idir 12 agus 1024 beart stuála, fós faoi réir an choinníll go mbeadh fad na teachtaireachta mar thoradh air sin inroinnte ar 16 beart.

Mar sin, cé mhéad stuáil ba chóir duit a chur leis?

Agus tá, tá 404 ann freisin i gcás earráide

Má rinne duine ar bith staidéar cúramach ar léaráid agus ar théacs na doiciméid, thug siad faoi deara nach bhfuil MAC ann. Agus go n-úsáidtear AES i mód IGE áirithe nach n-úsáidtear áit ar bith eile. Ar ndóigh, scríobhann siad faoi seo ina gCeisteanna Coitianta... Anseo, cosúil le, is í an eochair teachtaireachta féin an hash SHA de na sonraí díchriptithe, a úsáidtear chun sláine a sheiceáil - agus i gcás neamhréir, an doiciméadú ar chúis éigin molann neamhaird a dhéanamh orthu go ciúin (ach cad faoi shlándáil, cad é má bhriseann siad sinn?).

Ní cryptographer mé, b'fhéidir nach bhfuil aon rud cearr leis an modh seo sa chás seo ó thaobh teoiriciúil de. Ach is féidir liom fadhb phraiticiúil a ainmniú go soiléir, ag baint úsáide as Telegram Desktop mar shampla. Criptíonn sé an taisce áitiúil (iad seo go léir D877F783D5D3EF8C) ar an mbealach céanna le teachtaireachtaí i MTProto (ach amháin sa chás seo leagan 1.0), i.e. an eochair teachtaireacht ar dtús, ansin na sonraí féin (agus áit éigin ar leataobh an príomh-mór auth_key 256 beart, gan a msg_key gan úsáid). Mar sin, éiríonn an fhadhb faoi deara ar chomhaid mhóra. Is é sin, ní mór duit dhá chóip de na sonraí a choinneáil - criptithe agus díchriptithe. Agus má tá meigibheart, nó físeáin sruthú, mar shampla?.. Ligeann scéimeanna clasaiceacha le MAC tar éis an ciphertext duit sruth a léamh, agus é á tharchur láithreach. Ach le MTProto beidh ort ar dtús criptigh nó díchriptigh an teachtaireacht iomlán, ach ansin é a aistriú chuig an líonra nó chuig diosca. Dá bhrí sin, sna leaganacha is déanaí de Telegram Desktop sa taisce i user_data Úsáidtear formáid eile freisin - le AES i mód CTR.

Vasily, [21.06.18 01:27] Ó, fuair mé amach cad é IGE: ba é IGE an chéad iarracht ar “mód criptithe fíordheimhnithe,” do Kerberos ar dtús. Iarracht ar theip uirthi a bhí ann (ní sholáthraíonn sé cosaint sláine), agus b'éigean é a bhaint. Ba é sin tús le rompu 20 bliain le haghaidh modh criptithe fíordheimhnithe a oibríonn, a tháinig chun críche le déanaí le modhanna cosúil le OCB agus GCM.

Agus anois na hargóintí ó thaobh na cairte:

Tá an fhoireann taobh thiar de Telegram, faoi stiúir Nikolai Durov, comhdhéanta de shé Seaimpíní ACM, leath acu Ph.Ds sa mhatamaitic. Thóg sé thart ar dhá bhliain orthu an leagan reatha de MTProto a rolladh amach.

Tá sé sin greannmhar. Dhá bhliain ag an leibhéal níos ísle

Nó d'fhéadfá a ghlacadh ach tls

Ceart go leor, abair linn go bhfuil an criptiú agus na nuances eile déanta againn. An féidir ar deireadh iarrataí atá sraitheach in TL a sheoladh agus na freagraí a dhíscriosú? Mar sin, cad agus conas ba chóir duit a sheoladh? Anseo, a ligean le rá, an modh initCeangail, b'fhéidir é seo é?

Vasily, [25.06.18 18:46] Cuireann sé tús le nasc agus sábhálann sé faisnéis ar fheiste agus feidhmchlár an úsáideora.

Glacann sé le app_id, device_model, system_version, app_version agus lang_code.

Agus roinnt ceist

Doiciméadú mar i gcónaí. Thig leat staidéar a dhéanamh ar an bhfoinse oscailte

Má bhí gach rud beagnach soiléir le invokeWithLayer, cad atá mícheart anseo? Tharlaíonn sé, a ligean le rá go bhfuil muid - bhí an cliant cheana féin rud éigin a iarraidh ar an bhfreastalaí faoi - tá iarratas a theastaigh uainn a sheoladh:

Vasily, [25.06.18 19:13] Ag breithiúnas ag an gcód, tá an chéad ghlao fillte sa cacamas seo, agus tá an cacamas féin fillte i invokewithlayer

Cén fáth nach bhféadfadh initConnection a bheith ina ghlao ar leith, ach go gcaithfidh sé a bheith ina chumhdach? Sea, mar a d'éirigh sé amach, ní mór é a dhéanamh gach uair ag tús gach seisiún, agus ní uair amháin, mar atá leis an bpríomheochair. Ach! Ní féidir le húsáideoir neamhúdaraithe glaoch air! Anois tá an chéim bainte amach againn ina bhfuil sé infheidhme An ceann seo leathanach doiciméadaithe - agus insíonn sé dúinn go ...

Níl ach cuid bheag de na modhanna API ar fáil d’úsáideoirí neamhúdaraithe:

  • auth.sendCode
  • auth.resendCode
  • cuntas.getPassword
  • auth.checkPassword
  • auth.checkPhone
  • údar.clárú
  • údar.síniú isteach
  • auth.importAuthorization
  • help.getConfig
  • help.getNearestDc
  • help.getAppUpdate
  • help.getCdnConfig
  • langpack.getLangPack
  • langpack.getStrings
  • langpack.getDifference
  • langpack.getTeangacha
  • langpack.getLanguage

An chéad cheann acu, auth.sendCode, agus tá an chéad iarratas a chothaímid a sheolann muid api_id agus api_hash, agus ina dhiaidh sin a fháil againn SMS le cód. Agus má táimid sa DC mícheart (déantar freastal ar uimhreacha teileafóin sa tír seo ag duine eile, mar shampla), ansin gheobhaidh muid earráid le líon an DC atá ag teastáil. Chun a fháil amach cén seoladh IP de réir uimhir DC a gcaithfidh tú nascadh leis, cuidigh linn help.getConfig. Ag am amháin ní raibh ach 5 iontráil ann, ach tar éis imeachtaí cáiliúla 2018, tá méadú suntasach tagtha ar an líon.

Anois, déanaimis cuimhneamh go bhfuair muid go dtí an chéim seo ar an bhfreastalaí gan ainm. Nach bhfuil sé ró-chostasach seoladh IP a fháil? Cén fáth nach ndéanfaí é seo, agus oibríochtaí eile, sa chuid neamhchriptithe de MTProto? Cloisim an agóid: “conas is féidir linn a chinntiú nach é RKN a fhreagróidh le seoltaí bréagacha?” Chuige seo cuimhnímid, go ginearálta, cliaint oifigiúla Tá eochracha RSA leabaithe, i.e. an féidir leat ach a shíniú an t-eolas seo. I ndáiríre, tá sé seo á dhéanamh cheana féin le haghaidh faisnéise ar bhlocáil sheachbhóthar a fhaigheann cliaint trí bhealaí eile (go loighciúil, ní féidir é seo a dhéanamh i MTProto féin; ní mór duit fios a bheith agat freisin cá háit le nascadh).

ceart go leor. Ag an gcéim seo d'údarú na gcliant, nílimid údaraithe go fóill agus níl ár n-iarratas cláraithe againn. Níl uainn ach a fheiceáil cad a fhreagraíonn an freastalaí do mhodhanna atá ar fáil d'úsáideoir neamhúdaraithe. Agus anseo…

Vasily, [10.07.18 14:45] https://core.telegram.org/method/help.getConfig

config#7dae33e0 [...] = Config;
help.getConfig#c4f9186b = Config;

https://core.telegram.org/api/datacenter

config#232d5905 [...] = Config;
help.getConfig#c4f9186b = Config;

Sa scéim, tagann an chéad dara háit

Sa scéimre tdesktop is é an tríú luach

Sea, ó shin i leith, ar ndóigh, tá na doiciméid nuashonraithe. Cé go bhféadfadh sé a bheith neamhábhartha go luath arís. Conas ba chóir go mbeadh a fhios ag forbróir nua? B'fhéidir má chláraíonn tú d'iarratas, go gcuirfidh siad é sin in iúl duit? Rinne Vasily é seo, ach faraor, níor chuir siad rud ar bith chuige (arís, labhróimid faoi seo sa dara cuid).

...Thug tú faoi deara go bhfuil muid tar éis bogadh go dtí an API ar bhealach éigin cheana féin, i.e. go dtí an chéad leibhéal eile, agus rud éigin caillte san ábhar MTProto? Ní haon iontas:

Vasily, [28.06.18 02:04] Mm, tá siad ag rummaging trí roinnt de na halgartaim ar e2e

Sainmhíníonn Mtproto halgartaim criptiúcháin agus eochracha don dá fhearann, chomh maith le beagán de struchtúr fillteáin

Ach meascann siad leibhéil éagsúla den chruach i gcónaí, mar sin ní bhíonn sé soiléir i gcónaí cén áit ar chríochnaigh mtproto agus ar thosaigh an chéad leibhéal eile

Conas a mheascann siad? Bhuel, seo an eochair shealadach chéanna do PFS, mar shampla (dála an scéil, ní féidir le Telegram Desktop é a dhéanamh). Déantar é a fhorghníomhú trí iarratas API auth.bindTempAuthKey, i.e. ón leibhéal is airde. Ach ag an am céanna cuireann sé isteach ar chriptiú ag an leibhéal níos ísle - tar éis dó, mar shampla, ní mór duit é a dhéanamh arís initConnection etc., ní hé seo ach gnáthiarratas. Rud atá speisialta freisin ná nach féidir ach eochair shealadach AMHÁIN a bheith agat in aghaidh an DC, cé go bhfuil an réimse auth_key_id i ngach teachtaireacht is féidir leat an eochair a athrú ar a laghad gach teachtaireacht, agus go bhfuil an ceart ag an bhfreastalaí "dearmad" a dhéanamh ar an eochair shealadach ag am ar bith - ní deir an doiciméadú cad atá le déanamh sa chás seo ... bhuel, cén fáth nach 'Nach bhfuil roinnt eochracha agat, mar atá le sraith salainn sa todhchaí, agus ...

Tá cúpla rud eile ar fiú tabhairt faoi deara faoin téama MTProto.

Teachtaireachtaí teachtaireachta, msg_id, msg_seqno, dearbhuithe, pings sa treo mícheart agus sainchomharthaí eile

Cén fáth ar gá duit fios a bheith agat fúthu? Toisc go bhfuil siad “ag sceitheadh” go leibhéal níos airde, agus ní mór duit a bheith ar an eolas fúthu agus tú ag obair leis an API. Glacaimid leis nach bhfuil suim againn i msg_key; tá an leibhéal níos ísle tar éis gach rud a dhíchriptiú dúinn. Ach taobh istigh de na sonraí díchriptithe tá na réimsí seo a leanas againn (fad na sonraí freisin, ionas go mbeidh a fhios againn cá bhfuil an stuáil, ach níl sé sin tábhachtach):

  • salann - int64
  • seisiún_id - int64
  • teachtaireacht_id — int64
  • seq_no - int32

Cuir i gcuimhne duit nach bhfuil ach salann amháin ann don DC ar fad. Cén fáth a bhfuil a fhios aici? Ní hamháin toisc go bhfuil iarratas ann get_future_salts, a insíonn duit cé na hamanna a bheidh bailí, ach freisin mar má tá do shalann “lofa”, ansin caillfear an teachtaireacht (iarratas). Déanfaidh an freastalaí, ar ndóigh, an salann nua a thuairisciú trí eisiúint new_session_created - ach leis an seancheann beidh ort é a athsheoladh ar bhealach éigin, mar shampla. Agus bíonn tionchar ag an gceist seo ar ailtireacht an iarratais.

Tá cead ag an bhfreastalaí seisiúin a scaoileadh ar fad agus freagairt ar an mbealach seo ar go leor cúiseanna. I ndáiríre, cad é seisiún MTProto ó thaobh an chliaint? Is dhá uimhir iad seo session_id и seq_no teachtaireachtaí laistigh den seisiún seo. Bhuel, agus an nasc TCP bunúsach, ar ndóigh. Ligean le rá nach bhfuil a fhios ag ár gcliant go fóill conas a lán rudaí a dhéanamh, dhínascadh sé agus d'athcheangail sé. Má tharla sé seo go tapa - lean an sean-seisiún sa nasc TCP nua, méadú seq_no Tuilleadh. Má thógann sé i bhfad, d'fhéadfadh an freastalaí é a scriosadh, mar ar a thaobh tá sé freisin scuaine, mar a fuair muid amach.

Cad ba cheart dó a bheith seq_no? Ó, sin ceist fánach. Déan iarracht a thuiscint go hionraic cad a bhí i gceist:

Teachtaireacht a bhaineann le hábhar

Teachtaireacht a éilíonn admháil fhollasach. Ina measc seo tá na teachtaireachtaí go léir ó úsáideoirí agus go leor seirbhíse, beagnach gach ceann acu seachas coimeádáin agus admhálacha.

Uimhir Seicheamh na Teachtaireachta (msg_seqno)

Uimhir 32-giotán atá comhionann le dhá oiread líon na dteachtaireachtaí “a bhaineann le hábhar” (iad siúd a dteastaíonn admháil uathu, agus go háirithe iad siúd nach coimeádáin iad) a chruthaigh an seoltóir roimh an teachtaireacht seo agus a mhéadaítear ina dhiaidh sin le ceann amháin más teachtaireacht reatha í. teachtaireacht a bhaineann le hábhar. Gintear coimeádán i gcónaí tar éis a ábhar iomlán; mar sin, tá a sheicheamhuimhir níos mó ná nó cothrom le seicheamhuimhreacha na dteachtaireachtaí atá ann.

Cén cineál sorcais é seo le hincrimint faoi 1, agus ansin ceann eile faoi 2?.. Tá amhras orm gur chiallaigh siad ar dtús “an giotán is lú suntasaí do ACK, is uimhir é an chuid eile”, ach níl an toradh mar an gcéanna - go háirithe, a thagann sé amach, is féidir a sheoladh roinnt deimhnithe a bhfuil an gcéanna seq_no! Conas? Bhuel, mar shampla, cuireann an freastalaí rud éigin chugainn, cuireann sé é, agus fanann muid féin ciúin, gan freagra a thabhairt ach le teachtaireachtaí seirbhíse a dhearbhaíonn go bhfuarthas a chuid teachtaireachtaí. Sa chás seo, beidh an uimhir amach chéanna ag ár ndeimhnithe amach. Má tá tú eolach ar TCP agus shíl mé go fuaimeanna seo ar bhealach fiáin, ach is cosúil nach bhfuil an-fiáin, mar gheall ar i TCP seq_no ní athraíonn, ach téann deimhniú go seq_no ar an taobh eile, beidh mé hasten chun cur isteach ort. Cuirtear deimhnithe ar fáil in MTProto NACH ar seq_no, mar atá i TCP, ach le msg_id !

Cad é seo msg_id, an ceann is tábhachtaí de na réimsí seo? Aitheantóir teachtaireachta uathúil, mar a thugann an t-ainm le fios. Sainmhínítear é mar uimhir 64-giotán, a bhfuil an draíocht “freastalaí-ní-freastalaí” ag na giotáin is ísle acu arís, agus is stampa ama Unix an chuid eile, lena n-áirítear an chuid codánach, aistrithe 32 giotán ar chlé. Iad siúd. stampa ama per se (agus diúltóidh an freastalaí do theachtaireachtaí a bhfuil amanna éagsúla orthu). As seo is léir gur aitheantóir é seo atá domhanda don chliant. Ós rud é go - a ligean ar cuimhneamh session_id - táimid cinnte: Ní féidir i gcás ar bith teachtaireacht atá i gceist le haghaidh seisiún amháin a sheoladh chuig seisiún eile. Is é sin, casadh sé amach go bhfuil cheana féin trí leibhéal - seisiún, uimhir an tseisiúin, aitheantas na teachtaireachta. Cén fáth overcomplication den sórt sin, tá an Mystery an-mhór.

Mar sin, msg_id ag teastáil le haghaidh ...

RPC: iarratais, freagraí, earráidí. Daingnithe.

Mar a d'fhéadfadh a bheith tugtha faoi deara agat, níl aon chineál nó feidhm speisialta "déan iarratas RPC" áit ar bith sa léaráid, cé go bhfuil freagraí ann. Tar éis an tsaoil, tá teachtaireachtaí a bhaineann le hábhar againn! Is é sin, aon b'fhéidir gur iarratas é an teachtaireacht! Nó gan a bheith. Tar éis gach rud, gachmsg_id. Ach tá freagraí ann:

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

Seo an áit a gcuirtear in iúl cén teachtaireacht ar a bhfuil sé seo mar fhreagra. Mar sin, ag barrleibhéal an API, beidh ort cuimhneamh ar líon na n-iarratas a bhí agat - is dóigh liom nach gá a mhíniú go bhfuil an obair asincrónach, agus is féidir go mbeadh roinnt iarratas ar siúl ag an am céanna, ar féidir na freagraí orthu a chur ar ais in ord ar bith? I bprionsabal, uaidh seo agus ó theachtaireachtaí earráide amhail gan oibrithe ar bith, is féidir an ailtireacht taobh thiar de seo a rianú: is é an freastalaí a choinníonn nasc TCP leat cothromóir tosaigh, cuireann sé iarratais ar aghaidh chuig na hinnill agus bailíonn sé ar ais iad trí message_id. Dealraíonn sé go bhfuil gach rud anseo soiléir, loighciúil agus go maith.

Sea?.. Agus má cheapann tú faoi? Tar éis an tsaoil, tá réimse ag an bhfreagra RPC féin freisin msg_id! An gá dúinn a bheith ag béicíl ag an bhfreastalaí “níl tú ag tabhairt mo fhreagra!”? Agus tá, cad a bhí ann maidir le deimhnithe? Maidir le leathanach teachtaireachtaí faoi theachtaireachtaí insíonn dúinn cad é

msgs_ack#62d6b459 msg_ids:Vector long = MsgsAck;

agus ní mór é a dhéanamh ag gach taobh. Ach ní i gcónaí! Má fuair tú RpcResult, feidhmíonn sé féin mar dheimhniú. Is é sin, is féidir leis an bhfreastalaí freagra a thabhairt ar d'iarratas le MsgsAck - cosúil le, "Fuair ​​​​mé é." Is féidir le RpcResult freagairt láithreach. D'fhéadfadh sé a bheith araon.

Agus tá, caithfidh tú an freagra a fhreagairt fós! Daingniú. Seachas sin, measfaidh an freastalaí nach féidir é a sheachadadh agus seolfaidh sé ar ais chugat arís é. Fiú amháin tar éis athcheangal. Ach anseo, ar ndóigh, tagann ceist na dtréimhsí ama chun cinn. Breathnaímid orthu beagán níos déanaí.

Idir an dá linn, déanaimis féachaint ar earráidí a d'fhéadfadh a bheith i bhfeidhmiú fiosrúchán.

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

Ó, beidh duine éigin exclaim, anseo tá formáid níos daonnachtúla - tá líne! Tóg do chuid ama. Anseo liosta earráidí, ach ar ndóigh níl sé iomlán. Ó sé foghlaim againn go bhfuil an cód rud éigin mar Earráidí HTTP (bhuel, ar ndóigh, níl meas ar shéimeantaic na bhfreagraí, i roinnt áiteanna déantar iad a dháileadh go randamach i measc na gcód), agus is cosúil go bhfuil an líne CAPITAL_LETERS_AND_NUMBERS. Mar shampla, PHONE_NUMBER_OCCUPIED nó FILE_PART_Х_MISSING. Bhuel, is é sin, beidh an líne seo fós uait pharsáil. Mar shampla FLOOD_WAIT_3600 ciallóidh go bhfuil tú chun fanacht uair an chloig, agus PHONE_MIGRATE_5, go gcaithfear uimhir theileafóin leis an réimír seo a chlárú sa 5ú DC. Tá cineál teanga againn, ceart? Níl argóint ag teastáil uainn ó theaghrán, déanfaidh cinn rialta, ceart go leor.

Arís, níl sé seo ar an leathanach teachtaireachtaí seirbhíse, ach, mar is gnách cheana féin leis an tionscadal seo, is féidir an fhaisnéis a fháil ar leathanach doiciméadaithe eile. Nó amhras a chaitheamh. Gcéad dul síos, breathnú, clóscríobh / sárú ciseal - RpcError is féidir a neadú i RpcResult. Cén fáth nach bhfuil taobh amuigh? Cad nár chuireamar san áireamh?.. Dá réir sin, cá bhfuil an ráthaíocht sin RpcError NACH féidir a bheith leabaithe i RpcResult, ach a bheith díreach nó neadaithe i gcineál eile?.. Agus mura féidir, cén fáth nach bhfuil sé ag an mbarrleibhéal, i.e. tá sé ar iarraidh req_msg_id ?..

Ach leanaimis ar aghaidh faoi theachtaireachtaí seirbhíse. Seans go gceapfaidh an cliant go bhfuil an freastalaí ag smaoineamh ar feadh i bhfad agus go ndéanfaidh sé an t-iarratas iontach seo:

rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;

Tá trí fhreagra féideartha ar an gceist seo, ag trasnú arís leis an meicníocht deimhnithe; níl an cód foinse Telegram Desktop iomlán).

Andúil i ndrugaí: stádas teachtaireachta

Go ginearálta, fágann go leor áiteanna i TL, MTProto agus Telegram go ginearálta mothú stubbornness, ach as dea-bhéasacht, tact agus daoine eile. scileanna bog Choimeád muid go múinte tostach faoi, agus rinneamar cinsireacht ar na gáirsiúlachta sna comhráite. Mar sin féin, an áit seoОtá an chuid is mó den leathanach thart teachtaireachtaí faoi theachtaireachtaí Tá sé scanrúil fiú domsa, atá ag obair le prótacail líonra le fada an lá agus a chonaic rothair de leibhéil éagsúla cam.

Tosaíonn sé go neamhchiontach, le deimhnithe. Ansin insíonn siad dúinn faoi

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;

Bhuel, beidh ar gach duine a thosaíonn ag obair le MTProto déileáil leo; sa timthriall “ceartaithe - ath- tiomsaithe - seolta”, is rud coitianta é earráidí uimhreach nó salainn a fháil a d’éirigh go dona le linn eagarthóireachta. Mar sin féin, tá dhá phointe anseo:

  1. Ciallaíonn sé seo go bhfuil an teachtaireacht bunaidh caillte. Caithfimid roinnt scuainí a chruthú, féachfaimid air sin níos déanaí.
  2. Cad iad na huimhreacha aisteacha earráide seo? 16, 17, 18, 19, 20, 32, 33, 34, 35, 48, 64... cá bhfuil na huimhreacha eile, a Thommy?

Deir an doiciméadú:

Is é an rún go ndéantar luachanna error_code a ghrúpáil (error_code >> 4): mar shampla, comhfhreagraíonn na cóid 0x40 - 0x4f d'earráidí i ndianscaoileadh coimeádáin.

ach, ar dtús, athrú sa treo eile, agus ar an dara dul síos, is cuma, cá bhfuil na cóid eile? I gceann an údair?.. Is trifles iad seo, áfach.

Tosaíonn andúile i dteachtaireachtaí faoi stádas teachtaireachta agus cóipeanna teachtaireachta:

  • Iarratas ar Fhaisnéis Stádas Teachtaireachta
    Mura bhfuil faisnéis faighte ag ceachtar páirtí ar stádas a chuid teachtaireachtaí amach le tamall anuas, féadfaidh sé í a iarraidh go sainráite ar an bpáirtí eile:
    msgs_state_req#da69fb52 msg_ids:Vector long = MsgsStateReq;
  • Teachtaireacht Faisnéise maidir le Stádas Teachtaireachtaí
    msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
    Anseo, info is teaghrán é ina bhfuil beart amháin de stádas teachtaireachta do gach teachtaireacht ón liosta msg_ids isteach:

    • 1 = níl aon rud ar eolas faoin teachtaireacht (msg_id ró-íseal, seans go bhfuil dearmad déanta ag an bpáirtí eile uirthi)
    • 2 = teachtaireacht nach bhfuarthas (titeann msg_id laistigh de raon na n-aitheantóirí stóráilte; áfach, is cinnte nach bhfuair an páirtí eile teachtaireacht mar sin)
    • 3 = teachtaireacht nach bhfuarthas (msg_id ró-ard; áfach, is cinnte nach bhfuair an páirtí eile í fós)
    • 4 = teachtaireacht faighte (tabhair faoi deara go bhfuil an freagra seo freisin ag an am céanna admháil admhála)
    • +8 = teachtaireacht aitheanta cheana
    • +16 = teachtaireacht nach dteastaíonn admháil
    • +32 = Iarratas RPC sa teachtaireacht á próiseáil nó á próiseáil críochnaithe cheana féin
    • +64 = freagra a bhaineann le hábhar ar an teachtaireacht a gineadh cheana
    • +128 = tá a fhios ag páirtí eile go bhfuil an teachtaireacht faighte cheana
      Ní theastaíonn admháil ón bhfreagra seo. Is admháil é ar an msgs_state_req ábhartha, ann agus ann féin.
      Tabhair faoi deara má tharlaíonn sé go tobann nach bhfuil teachtaireacht ag an bpáirtí eile a bhfuil an chuma air gur seoladh é, is féidir an teachtaireacht a athsheoladh go simplí. Fiú dá bhfaigheadh ​​an páirtí eile dhá chóip den teachtaireacht ag an am céanna, ní thabharfar aird ar an dúblach. (Má tá an iomarca ama caite, agus mura bhfuil an bunaidh msg_id bailí a thuilleadh, tá an teachtaireacht le bheith fillte i msg_copy).
  • Stádas na dTeachtaireachtaí a Chur in iúl go Toilteanach
    Féadfaidh ceachtar páirtí stádas na dteachtaireachtaí arna dtarchur ag an bpáirtí eile a chur in iúl don pháirtí eile go deonach.
    msgs_all_info#8cc0d131 msg_ids:Vector long info:string = MsgsAllInfo
  • Teachtaireacht Dheonach Leathnaithe maidir le Stádas Aon Teachtaireacht amháin
    ...
    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;
  • Iarratas Sonrach chun Teachtaireachtaí a Athsheoladh
    msg_resend_req#7d861a08 msg_ids:Vector long = MsgResendReq;
    Freagraíonn an cianpháirtí láithreach trí na teachtaireachtaí iarrtha a athsheoladh […]
  • Iarratas Sonrach chun Freagraí a Athsheoladh
    msg_resend_ans_req#8610baeb msg_ids:Vector long = MsgResendReq;
    Freagraíonn an páirtí iargúlta láithreach trí athsheoladh freagraí chuig na teachtaireachtaí iarrtha […]
  • Cóipeanna Teachtaireachta
    I gcásanna áirithe, ní mór seanteachtaireacht le msg_id nach bhfuil bailí a thuilleadh a athsheoladh. Ansin, tá sé fillte i gcoimeádán cóip:
    msg_copy#e06046b2 orig_message:Message = MessageCopy;
    Nuair a fhaightear an teachtaireacht, próiseáiltear an teachtaireacht amhail is nach raibh an fillteán ann. Mar sin féin, má tá a fhios go cinnte go bhfuarthas an teachtaireacht orig_message.msg_id, ní dhéantar an teachtaireacht nua a phróiseáil (agus ag an am céanna, admhaítear í agus orig_message.msg_id). Caithfidh luach orig_message.msg_id a bheith níos ísle ná msg_id an choimeádáin.

A ligean ar a choinneáil fiú ciúin faoi cad msgs_state_info arís tá cluasa an TL neamhchríochnaithe ag gobadh amach (ní mór dúinn veicteoir beart, agus sa dá ghiotán níos ísle bhí enum, agus sa dá ghiotán níos airde bhí bratacha). Tá an pointe difriúil. An dtuigeann éinne cén fáth go bhfuil sé seo go léir i gcleachtas? i gcliant fíor gá?.. Le deacracht, ach is féidir le duine a shamhlú roinnt sochar má tá duine i mbun debugging, agus i mód idirghníomhach - a iarraidh ar an bhfreastalaí cad agus conas. Ach anseo tá cur síos ar na hiarratais turas cruinn.

Mar sin ní mór do gach páirtí ní hamháin teachtaireachtaí a chriptiú agus a sheoladh, ach freisin sonraí fúthu féin, faoi na freagraí orthu, a stóráil ar feadh tréimhse anaithnid ama. Ní dhéanann an doiciméadú cur síos ar amanna nó ar infheidhmeacht phraiticiúil na ngnéithe seo. ar aon bhealach. Is é an rud is iontach ná go n-úsáidtear iad i ndáiríre i gcód na gcliant oifigiúil! De réir dealraimh dúradh leo rud éigin nach raibh san áireamh sna doiciméid phoiblí. A thuiscint ón gcód cén fáth, nach bhfuil sé chomh simplí a thuilleadh agus i gcás TL - ní cuid (go coibhneasta) é atá scoite amach go loighciúil, ach píosa atá ceangailte le hailtireacht an fheidhmchláir, i.e. beidh i bhfad níos mó ama ag teastáil chun an cód iarratais a thuiscint.

Pingeanna agus uainiúcháin. scuainí.

Ó gach rud, má chuimhnímid ar na buille faoi thuairim faoi ailtireacht an fhreastalaí (dáileadh na n-iarratas ar fud na n-inneall), leanann rud sách brónach - in ainneoin na ráthaíochtaí seachadta go léir i TCP (ceachtar na sonraí a sheachadadh, nó cuirfear ar an eolas tú faoin mbearna, ach seachadfar na sonraí sula dtarlóidh an fhadhb), go ndeimhnítear i MTProto féin - aon ráthaíochtaí. Is féidir leis an bhfreastalaí do theachtaireacht a chailleadh nó a chaitheamh amach go héasca, agus ní féidir aon rud a dhéanamh faoi, ach cineálacha éagsúla crutches a úsáid.

Agus ar an gcéad dul síos - scuainí teachtaireachta. Bhuel, le rud amháin bhí gach rud soiléir ón tús - ní mór teachtaireacht neamhdhaingnithe a stóráil agus a bheith dochloíte. Agus tar éis cén t-am? Agus tá aithne ag an ngream air. B’fhéidir go réitíonn na teachtaireachtaí seirbhíse andúile sin ar bhealach éigin an fhadhb seo le crutches, abair, i Telegram Desktop tá thart ar 4 scuainí a fhreagraíonn dóibh (b’fhéidir níos mó, mar a luadh cheana, le haghaidh seo ní mór duit iniúchadh níos dáiríre a dhéanamh ar a chód agus a ailtireacht; ag an gcéanna am, táimid Tá a fhios againn nach féidir é a ghlacadh mar shampla;

Cén fáth go bhfuil sé seo ag tarlú? Is dócha, ní raibh na ríomhchláraitheoirí freastalaí in ann iontaofacht a chinntiú laistigh den bhraisle, nó fiú maolán a dhéanamh ar an gcothromóir tosaigh, agus d'aistrigh siad an fhadhb seo chuig an gcliant. As an éadóchas, rinne Vasily iarracht rogha eile a chur i bhfeidhm, gan ach dhá scuaine, ag baint úsáide as halgartaim ó TCP - an RTT a thomhas ar an bhfreastalaí agus méid na “fuinneog” (i dteachtaireachtaí) a choigeartú ag brath ar líon na n-iarratas neamhdheimhnithe. Is é sin, heuristic chomh garbh sin chun ualach an fhreastalaí a mheasúnú ná cé mhéad dár n-iarrataí is féidir leis a chew ag an am céanna agus gan a chailleadh.

Bhuel, is é sin, an dtuigeann tú, ceart? Má tá ort TCP a chur i bhfeidhm arís ar bharr prótacail a ritheann thar TCP, léiríonn sé seo prótacal atá deartha go dona.

Ó sea, cén fáth a bhfuil níos mó ná scuaine amháin ag teastáil uait, agus cad a chiallaíonn sé seo do dhuine atá ag obair le API ardleibhéil ar aon nós? Féach, déanann tú iarratas, déan sraithuimhir é, ach go minic ní féidir leat é a sheoladh láithreach. Cén fáth? Toisc go mbeidh an freagra msg_id, atá sealadachаIs lipéad mé, agus is fearr a shannadh a chur siar go dtí chomh déanach agus is féidir - ar eagla go ndiúltóidh an freastalaí é mar gheall ar neamhréir ama idir sinn féin agus eisean (ar ndóigh, is féidir linn magairlín a dhéanamh a aistríonn ár gcuid ama ón am i láthair chuig an bhfreastalaí trí dheilt arna ríomh ó fhreagraí an fhreastalaí a chur leis - déanann cliaint oifigiúla é seo, ach tá sé amh agus míchruinn mar gheall ar mhaolánaithe). Mar sin, nuair a dhéanann tú iarratas le glao feidhm áitiúil ón leabharlann, téann an teachtaireacht trí na céimeanna seo a leanas:

  1. Tá sé i scuaine amháin agus ag fanacht ar chriptiú.
  2. Ceaptha msg_id agus chuaigh an teachtaireacht chuig scuaine eile - cur ar aghaidh b'fhéidir; seol chuig an soicéad.
  3. a) D’fhreagair an freastalaí MsgsAck - seachadadh an teachtaireacht, scriosaimid ón “scuaine eile” í.
    b) Nó a mhalairt, níor thaitin rud éigin leis, d’fhreagair sé badmsg - athsheol ó “scuaine eile”
    c) Ní fios aon rud, ní mór an teachtaireacht a bheith doicheall ó scuaine eile - ach ní fios cathain go díreach.
  4. D'fhreagair an freastalaí ar deireadh RpcResult - an freagra iarbhír (nó an earráid) - ní hamháin seachadadh, ach próiseáilte freisin.

B'fhéidir, d'fhéadfadh úsáid coimeádáin an fhadhb a réiteach go páirteach. Seo nuair a phacáiltear cuid mhór teachtaireachtaí isteach i gceann amháin, agus d'fhreagair an freastalaí le deimhniú dóibh go léir ag an am céanna, i gceann amháin msg_id. Ach diúltóidh sé freisin don phacáiste seo, má chuaigh rud éigin mícheart, ina iomláine.

Agus ag an bpointe seo, tagann cúinsí neamhtheicniúla san áireamh. Ó thaithí, tá go leor crutches feicthe againn, agus ina theannta sin, feicfimid níos mó samplaí de dhroch-chomhairle agus ailtireacht anois - i gcoinníollacha den sórt sin, is fiú muinín a dhéanamh agus cinntí den sórt sin a dhéanamh? Tá an cheist reitriciúil (ar ndóigh ní).

Cad faoi a bhfuilimid ag caint? Más rud é ar an ábhar “teachtaireachtaí drugaí faoi theachtaireachtaí” is féidir leat tuairimíocht a dhéanamh fós faoi agóidí mar “tá tú dúr, níor thuig tú ár bplean iontach!” (mar sin scríobh an doiciméadú ar dtús, mar ba chóir do ghnáthdhaoine, le réasúnaíocht agus samplaí de mhalartú paicéid, ansin labhróimid), ansin is ceist phraiticiúil agus shainiúil amháin iad na hamanna/na tréimhsí ama, tá gach rud ar eolas anseo le fada an lá. Cad a insíonn na doiciméid dúinn faoi am istigh?

Is gnách go n-admhaíonn freastalaí go bhfuarthas teachtaireacht ó chliant (go hiondúil, ceist RPC) ag baint úsáide as freagra RPC. Má tá freagra fada ag teacht, féadfaidh freastalaí admháil admhála a sheoladh ar dtús, agus beagán níos déanaí, an freagra RPC féin.

De ghnáth admhaíonn cliant go bhfuarthas teachtaireacht ó fhreastalaí (go hiondúil, freagra RPC) trí admháil a chur leis an gcéad cheist RPC eile mura dtarchuirtear é ró-dhéanach (má ghintear é, abair, 60-120 soicind tar éis an admháil de theachtaireacht ón bhfreastalaí). Mar sin féin, más rud é ar feadh tréimhse fada ama nach bhfuil aon chúis teachtaireachtaí a sheoladh chuig an bhfreastalaí nó má tá líon mór de theachtaireachtaí gan admháil ón bhfreastalaí (abair, os cionn 16), tarchuireann an cliant admháil neamhspleách.

... aistrím: níl a fhios againn féin cé mhéad agus conas a theastaíonn uainn é, mar sin glacaimis leis gur mar seo a bheidh sé.

Agus faoi pings:

Teachtaireachtaí Ping (PING/PONG)

ping#7abe77ec ping_id:long = Pong;

Seoltar freagra ar ais chuig an nasc céanna de ghnáth:

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

Ní theastaíonn admháil ó na teachtaireachtaí seo. Ní tharchuirtear pong ach mar fhreagra ar phing agus is féidir le ping a thionscnamh ag an dá thaobh.

Dúnadh Ceangal Iarchurtha + PING

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

Oibríonn sé cosúil le ping. Ina theannta sin, tar éis é seo a fháil, tosaíonn an freastalaí lasc ama a dhúnfaidh an nasc reatha disconnect_delay soicind níos déanaí ach amháin má fhaigheann sé teachtaireacht nua den chineál céanna a athshocróidh go huathoibríoch gach amadóir roimhe seo. Má sheolann an cliant na pings seo uair amháin gach 60 soicind, mar shampla, féadfaidh sé disconnect_delay a shocrú cothrom le 75 soicind.

An bhfuil tú craiceáilte?! I 60 soicind, rachaidh an traein isteach sa stáisiún, scaoilfidh agus piocadh suas paisinéirí, agus arís caillfidh teagmháil sa tollán. I 120 soicind, agus tú ag éisteacht leis, tiocfaidh sé ar cheann eile, agus is dócha go mbrisfidh an nasc. Bhuel, tá sé soiléir cad as a dtagann na cosa - “Chuala mé glaoch, ach níl a fhios agam cá bhfuil sé”, tá algartam Nagl agus an rogha TCP_NODELAY, atá beartaithe le haghaidh obair idirghníomhach. Ach, gabh mo leithscéal, coinnigh ar a luach réamhshocraithe - 200 Millisoicind Más mian leat rud éigin cosúil leis a léiriú agus a shábháil ar chúpla paicéad a d’fhéadfadh a bheith agat, ansin é a chur amach ar feadh 5 soicind, nó is cuma cad é an teorainn ama teachtaireachta “Tá an tÚsáideoir ag clóscríobh...” anois. Ach nach bhfuil níos mó.

Agus ar deireadh, pings. Is é sin, beocht an naisc TCP a sheiceáil. Tá sé greannmhar, ach thart ar 10 mbliana ó shin scríobh mé téacs criticiúil faoi theachtaire dorm ár dáimhe - chuir na húdair ann freisin an freastalaí ón gcliant, agus ní vice versa. Ach is rud amháin é mic léinn na tríú bliana, agus is rud eile oifig idirnáisiúnta, ceart?..

Gcéad dul síos, clár oideachais beag. Is féidir le nasc TCP, in éagmais malartú paicéid, maireachtáil ar feadh seachtainí. Tá sé seo go maith agus go dona, ag brath ar an gcuspóir. Tá sé go maith má bhí nasc SSH ar oscailt don fhreastalaí agat, d'éirigh tú ón ríomhaire, d'aththosaigh tú an ródaire, d'fhill tú ar d'áit - níor stróic an seisiún tríd an bhfreastalaí seo (níor chlóscríobh tú tada, ní raibh paicéid ann) , tá sé áisiúil. Is olc an rud é má tá na mílte cliant ar an bhfreastalaí, gach ceann acu ag glacadh acmhainní (hello, Postgres!), Agus b’fhéidir gur atosaigh óstach an chliaint i bhfad ó shin - ach ní bheidh a fhios againn faoi.

Titeann córais Chat/IM isteach sa dara cás ar chúis amháin eile - stádas ar líne. Má "thit an t-úsáideoir as", ní mór duit a chuid idirghabhálaithe a chur ar an eolas faoi seo. Seachas sin, beidh tú ag deireadh suas le botún a rinne an creators Jabber (agus a cheartú ar feadh 20 bliain) - tá an t-úsáideoir dícheangailte, ach leanann siad ag scríobh teachtaireachtaí dó, a chreidiúint go bhfuil sé ar líne (a bhí caillte go hiomlán freisin sna. cúpla nóiméad sular thángthas ar an dícheangal). Ní chuideoidh an rogha TCP_KEEPALIVE, a chuireann go leor daoine nach dtuigeann an chaoi a n-oibríonn amadóirí TCP isteach go randamach (trí luachanna fiáine cosúil le deich soicind) a shocrú - ní mór duit a chinntiú, ní hamháin an eithne OS. Tá meaisín an úsáideora beo, ach ag feidhmiú de ghnáth freisin, in ann freagra a thabhairt, agus an feidhmchlár féin (an dóigh leat nach féidir é a reo? Reoite Telegram Desktop ar Ubuntu 18.04 dom níos mó ná uair amháin).

Sin an fáth go gcaithfidh tú ping freastalaí cliant, agus ní vice versa - má dhéanann an cliant é seo, má tá an nasc briste, ní bheidh an ping a sheachadadh, ní bheidh an sprioc a bhaint amach.

Cad a fheiceann muid ar Telegram? Tá sé díreach a mhalairt! Bhuel, is é sin. Go foirmiúil, ar ndóigh, is féidir leis an dá thaobh ping a chéile. Go praiticiúil, úsáideann cliaint crutch ping_delay_disconnect, a leagann an t-amadóir ar an bhfreastalaí. Bhuel, gabh mo leithscéal, ní faoin gcliant atá sé a chinneadh cé chomh fada is mian leis cónaí ann gan ping. Tá a fhios níos fearr ag an bhfreastalaí, bunaithe ar a ualach. Ach, ar ndóigh, mura miste leat na hacmhainní, ansin beidh tú i do chuid Pinocchio olc féin, agus déanfaidh crutch...

Conas ba chóir é a dhearadh?

Creidim go léiríonn na fíricí thuas go soiléir nach bhfuil an fhoireann Telegram/VKontakte an-inniúil i réimse an iompair (agus leibhéal níos ísle) líonraí ríomhaireachta agus a gcáilíochtaí ísle i gcúrsaí ábhartha.

Cén fáth go raibh sé chomh casta sin, agus conas is féidir le hailtirí Telegram iarracht a dhéanamh agóid a dhéanamh? Ós rud é go ndearna siad iarracht seisiún a dhéanamh a mhaireann briseadh nasc TCP, i.e., an rud nár seachadadh anois, déanfaimid níos déanaí. Is dócha go ndearna siad iarracht iompar UDP a dhéanamh freisin, ach bhí deacrachtaí acu agus thréig siad é (sin an fáth go bhfuil an doiciméadú folamh - ní raibh aon rud le brag faoi). Ach mar gheall ar easpa tuisceana ar conas a oibríonn líonraí i gcoitinne agus TCP go háirithe, áit ar féidir leat brath air, agus nuair is gá duit é a dhéanamh leat féin (agus conas), agus iarracht é seo a chomhcheangal le cripteagrafaíocht “dhá éan le cloch amháin”, is é seo an toradh.

Conas a bhí sé riachtanach? Bunaithe ar an bhfíric go msg_id is stampa ama atá riachtanach ó thaobh cripteagrafach de chun ionsaithe athimeartha a chosc, is botún é feidhm aitheantóra uathúil a cheangal leis. Mar sin, gan athrú bunúsach a dhéanamh ar an ailtireacht reatha (nuair a ghintear an sruth Nuashonruithe, sin ábhar API ardleibhéil do chuid eile den tsraith post seo), bheadh ​​gá le ceann amháin:

  1. Glacann an freastalaí a bhfuil nasc TCP aige leis an gcliant freagracht - má tá sé léite ón soicéad, le do thoil admhaigh, próiseáil nó cuir ar ais earráid, gan aon chaillteanas. Ansin ní veicteoir aitheantais atá sa deimhniú, ach go simplí “an seq_no deiridh a fuarthas” - gan ach uimhir, mar atá i TCP (dhá uimhir - do seq agus an ceann deimhnithe). Táimid i gcónaí laistigh den seisiún, nach bhfuil?
  2. Éiríonn an stampa ama chun ionsaithe athimeartha a chosc ina réimse ar leith, a la nonce. Déantar é a sheiceáil, ach ní dhéanann sé difear do rud ar bith eile. Go leor agus uint32 - má athraíonn ár salann gach leath lá ar a laghad, is féidir linn 16 giotán a leithdháileadh ar ghiotán íseal-ordú cuid slánuimhir den am reatha, an chuid eile - go dtí cuid codánach de soicind (mar atá anois).
  3. Bhaint msg_id ar chor ar bith - ó thaobh idirdhealú a dhéanamh ar iarratais ar na hinnill, tá, ar an gcéad dul síos, aitheantas an chliaint, agus sa dara háit, an t-aitheantas seisiúin, comhcheangail iad. Dá réir sin, ní leor ach rud amháin mar aitheantóir iarratais seq_no.

Ní hé seo an rogha is rathúla freisin; Bheadh ​​sé níos fearr an ailtireacht a athdhéanamh go hiomlán ó choibhneasta go hiomlán, ach is ábhar é seo do chuid eile, ní sa phost seo.

API?

Ta-daam! Mar sin, tar éis dúinn dul i ngleic le cosán lán le pian agus maidí, bhíomar in ann faoi dheireadh aon iarratais a sheoladh chuig an bhfreastalaí agus aon fhreagraí a fháil orthu, chomh maith le nuashonruithe a fháil ón bhfreastalaí (ní mar fhreagra ar iarratas, ach é féin seolann chugainn, cosúil le PUSH, má tá sé níos soiléire ag éinne mar sin).

Tabhair aird, anois beidh an t-aon sampla i Perl san alt! (dóibh siúd nach bhfuil eolach ar an chomhréir, is é struchtúr sonraí an oibiachta an chéad argóint faoi bheannaigh, is é an dara ceann a rang):

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

Sea, ní spoiler cuspóireach é - mura bhfuil sé léite agat fós, téigh ar aghaidh agus déan é!

Ó, wai~~... cén chuma atá air seo? Rud an-eolach... b'fhéidir gurb é seo an struchtúr sonraí de ghnáth-API Gréasáin i JSON, ach amháin go bhfuil ranganna ceangailte le réada freisin?..

Mar sin, is é seo conas a casadh sé amach ... Cad é go léir faoi, gcomrádaithe?.. Iarracht an oiread sin - agus stop muid a gcuid eile i gcás na ríomhchláraitheoirí Gréasáin díreach ag tosú?..Nach mbeadh JSON níos simplí thar HTTPS?! Cad a fuair muid mar mhalairt? Arbh fhiú an iarracht?

Déanaimis measúnú ar an méid a thug TL+MTProto dúinn agus cad iad na roghanna eile is féidir. Bhuel, tá HTTP, a dhíríonn ar an tsamhail iarratas-freagra, oiriúnach go dona, ach ar a laghad rud éigin ar bharr TLS?

Srathú Dlúth. Agus an struchtúr sonraí seo á fheiceáil, cosúil le JSON, is cuimhin liom go bhfuil leaganacha dénártha de. Marcáil MsgPack mar nach bhfuil sé in-sínte go leor, ach tá, mar shampla, CBOR - dála an scéil, caighdeán a bhfuil cur síos air in RFC 7049. Tá sé suntasach mar gheall ar an bhfíric go sainmhíníonn sé clibeanna, mar mheicníocht leathnaithe, agus i measc caighdeánaithe cheana féin ar fáil:

  • 25 + 256 - tagairt don uimhir líne a chur in ionad línte arís agus arís eile, modh comhbhrú saor den sórt sin
  • 26 - réad Perl sraitheach le hainm ranga agus argóintí cruthaitheoir
  • 27 - réad sraitheach neamhspleách ar theanga le cineál-ainm agus argóintí cruthaitheoir

Bhuel, rinne mé iarracht na sonraí céanna a shraithiú in TL agus i CBOR le pacáil teaghrán agus réad cumasaithe. Thosaigh an toradh ag athrú i bhfabhar CBOR áit éigin ó mheigibheart:

cborlen=1039673 tl_len=1095092

Mar sin, conclúid: Tá formáidí substaintiúla níos simplí ann nach bhfuil faoi réir fadhb na teipe sioncrónaithe nó aitheantóir anaithnid, le héifeachtacht inchomparáide.

Bunú nasc tapa. Ciallaíonn sé seo náid RTT tar éis athcheangal (nuair a bheidh an eochair gineadh uair amháin cheana féin) - is infheidhme ón gcéad teachtaireacht MTProto, ach le roinnt áirithintí - bhuail an salann céanna, níl an seisiún lofa, etc. Cad a thairgeann TLS dúinn ina ionad sin? Athfhriotail ar an ábhar:

Agus PFS in úsáid in TLS, ticéid seisiúin TLS (RFC 5077) seisiún criptithe a atosú gan eochracha a ath-idirbheartaíocht agus gan eochairfhaisnéis a stóráil ar an bhfreastalaí. Nuair a bhíonn an chéad nasc á oscailt agus ag cruthú eochracha, criptíonn an freastalaí an stát nasc agus tarchuireann sé chuig an gcliant é (i bhfoirm ticéad seisiúin). Dá réir sin, nuair a atosófar an nasc, seolann an cliant ticéad seisiúin, lena n-áirítear an eochair seisiúin, ar ais chuig an bhfreastalaí. Tá an ticéad féin criptithe le heochair shealadach (eochair ticéad seisiúin), a stóráiltear ar an bhfreastalaí agus ní mór é a dháileadh ar gach freastalaithe tosaigh a phróiseálann SSL i réitigh bhraisle.[10]. Mar sin, d'fhéadfadh tabhairt isteach ticéad seisiúin sárú ar PFS má chuirtear eochracha freastalaí sealadach i mbaol, mar shampla, nuair a stóráiltear iad ar feadh i bhfad (Stórálann OpenSSL, nginx, Apache iad de réir réamhshocraithe ar feadh ré iomlán an chláir; úsáideann suíomhanna coitianta iad. an eochair ar feadh roinnt uaireanta, suas le laethanta).

Anseo nach bhfuil an RTT nialas, is gá duit a mhalartú ar a laghad ClientHello agus ServerHello, tar éis ar féidir leis an gcliant sonraí a sheoladh chomh maith le Críochnaithe. Ach anseo ba cheart dúinn cuimhneamh nach bhfuil againn ar an nGréasán, lena scata naisc nua-oscailte, ach teachtaire, ar minic gur iarratas fada nó níos lú fadsaoil, sách gearr ar leathanaigh Ghréasáin a nasctar - tá gach rud ilphléacsáilte. go hinmheánach. Is é sin, tá sé inghlactha go leor murar tháinig muid trasna ar alt subway fíor-dhona.

Dearmad ar rud éigin eile? Scríobh sna tuairimí.

Le leanúint!

Sa dara cuid den tsraith post seo beimid ag smaoineamh ar cheisteanna nach teicniúla, ach eagrúcháin - cur chuige, idé-eolaíocht, comhéadan, dearcadh i leith úsáideoirí, etc. Bunaithe, áfach, ar an bhfaisnéis theicniúil a cuireadh i láthair anseo.

Leanfaidh an tríú cuid d'anailís a dhéanamh ar an gcomhpháirt theicniúil / taithí forbartha. Foghlaimeoidh tú, go háirithe:

  • leanúint leis an pandemonium leis an éagsúlacht de chineálacha TL
  • rudaí anaithnid faoi chainéil agus sárghrúpaí
  • cén fáth go bhfuil dialóga níos measa ná an uainchlár
  • faoi ​​absalóideach vs seoladh teachtaireachta coibhneasta
  • cad é an difríocht idir grianghraf agus íomhá
  • conas a chuireann emoji isteach ar théacs iodálach

agus crutches eile! Fanacht tiúnta!

Foinse: will.com

Add a comment