టెలిగ్రామ్ ప్రోటోకాల్ మరియు సంస్థాగత విధానాలపై విమర్శలు. పార్ట్ 1, సాంకేతికత: మొదటి నుండి క్లయింట్‌ను వ్రాసే అనుభవం - TL, MT

ఇటీవల, టెలిగ్రామ్ ఎంత మంచిదో, నెట్‌వర్క్ సిస్టమ్‌లను నిర్మించడంలో డ్యూరోవ్ సోదరులు ఎంత తెలివైనవారు మరియు అనుభవజ్ఞులు మొదలైన వాటి గురించిన పోస్ట్‌లు హబ్రేలో తరచుగా కనిపించడం ప్రారంభించాయి. అదే సమయంలో, చాలా తక్కువ మంది వ్యక్తులు నిజంగా సాంకేతిక పరికరంలో మునిగిపోయారు - గరిష్టంగా, వారు JSON ఆధారంగా చాలా సరళమైన (మరియు MTProto నుండి చాలా భిన్నమైన) Bot APIని ఉపయోగిస్తారు మరియు సాధారణంగా అంగీకరిస్తారు విశ్వాసం మీద మెసెంజర్ చుట్టూ తిరిగే అన్ని ప్రశంసలు మరియు PR. దాదాపు ఏడాదిన్నర క్రితం, Eshelon NGO వాసిలీలో నా సహోద్యోగి (దురదృష్టవశాత్తూ, డ్రాఫ్ట్‌తో పాటు హబ్రేపై అతని ఖాతా తొలగించబడింది) పెర్ల్‌లో మొదటి నుండి తన స్వంత టెలిగ్రామ్ క్లయింట్‌ను రాయడం ప్రారంభించాడు మరియు తరువాత ఈ పంక్తుల రచయిత చేరాడు. ఎందుకు పెర్ల్, కొందరు వెంటనే అడుగుతారు? ఇతర భాషలలో ఇప్పటికే ఇటువంటి ప్రాజెక్టులు ఉన్నందున, ఇది విషయం కాదు, లేని చోట ఏదైనా ఇతర భాష ఉండవచ్చు రెడీమేడ్ లైబ్రరీ, మరియు తదనుగుణంగా రచయిత అన్ని విధాలుగా వెళ్ళాలి మొదటి నుండి. అంతేకాకుండా, క్రిప్టోగ్రఫీ అనేది నమ్మకానికి సంబంధించిన విషయం, కానీ ధృవీకరించండి. భద్రతను లక్ష్యంగా చేసుకున్న ఉత్పత్తితో, మీరు తయారీదారు నుండి సిద్ధంగా ఉన్న లైబ్రరీపై ఆధారపడలేరు మరియు దానిని గుడ్డిగా విశ్వసించలేరు (అయితే, ఇది రెండవ భాగానికి సంబంధించిన అంశం). ప్రస్తుతానికి, లైబ్రరీ "సగటు" స్థాయిలో బాగా పని చేస్తుంది (ఏదైనా API అభ్యర్థనలను చేయడానికి మిమ్మల్ని అనుమతిస్తుంది).

అయితే, ఈ పోస్ట్‌ల శ్రేణిలో ఎక్కువ క్రిప్టోగ్రఫీ లేదా గణితం ఉండదు. కానీ అనేక ఇతర సాంకేతిక వివరాలు మరియు నిర్మాణ క్రచెస్ (మొదటి నుండి వ్రాయని వారికి కూడా ఉపయోగకరంగా ఉంటుంది, కానీ ఏ భాషలోనైనా లైబ్రరీని ఉపయోగిస్తుంది). కాబట్టి, క్లయింట్‌ను మొదటి నుండి అమలు చేయడానికి ప్రయత్నించడం ప్రధాన లక్ష్యం అధికారిక డాక్యుమెంటేషన్ ప్రకారం. అంటే, అధికారిక క్లయింట్‌ల సోర్స్ కోడ్ మూసివేయబడిందని అనుకుందాం (మళ్ళీ, రెండవ భాగంలో ఇది నిజం అనే అంశాన్ని మరింత వివరంగా కవర్ చేస్తాము అది జరుగుతుంది కాబట్టి), కానీ, పాత రోజుల్లో వలె, ఉదాహరణకు, RFC వంటి ప్రమాణం ఉంది - సోర్స్ కోడ్‌లో “చూడకుండా” స్పెసిఫికేషన్ ప్రకారం మాత్రమే క్లయింట్‌ను వ్రాయడం సాధ్యమేనా, అది అధికారికం (టెలిగ్రామ్ డెస్క్‌టాప్, మొబైల్), లేదా అనధికారిక టెలిథాన్?

ఆటలు:

డాక్యుమెంటేషన్... అది ఉంది, సరియైనదా? ఇది నిజమా?..

ఈ వ్యాసం కోసం గమనికల శకలాలు గత వేసవిలో సేకరించడం ప్రారంభించాయి. అధికారిక వెబ్‌సైట్‌లో ఈ సమయం అంతా https://core.telegram.org డాక్యుమెంటేషన్ లేయర్ 23 నాటికి ఉంది, అనగా. 2014లో ఎక్కడో ఇరుక్కుపోయింది (గుర్తుంచుకోండి, అప్పటికి ఛానెల్‌లు కూడా లేవు?). వాస్తవానికి, సిద్ధాంతపరంగా, ఇది 2014లో ఆ సమయంలో కార్యాచరణతో క్లయింట్‌ను అమలు చేయడానికి మాకు అనుమతించి ఉండాలి. కానీ ఈ స్థితిలో కూడా, డాక్యుమెంటేషన్, మొదట, అసంపూర్ణంగా ఉంది మరియు రెండవది, ప్రదేశాలలో అది విరుద్ధంగా ఉంది. కేవలం ఒక నెల క్రితం, సెప్టెంబర్ 2019లో, అది అనుకోకుండా ఇటీవలి లేయర్ 105 కోసం సైట్‌లో డాక్యుమెంటేషన్ యొక్క పెద్ద నవీకరణ ఉందని కనుగొనబడింది, ఇప్పుడు ప్రతిదీ మళ్లీ చదవాల్సిన అవసరం ఉంది. నిజానికి, చాలా వ్యాసాలు సవరించబడ్డాయి, కానీ చాలా వరకు మారలేదు. అందువల్ల, డాక్యుమెంటేషన్ గురించి దిగువ విమర్శలను చదివేటప్పుడు, ఈ విషయాలలో కొన్ని ఇకపై సంబంధితంగా లేవని మీరు గుర్తుంచుకోవాలి, కానీ కొన్ని ఇప్పటికీ చాలా ఉన్నాయి. అన్ని తరువాత, ఆధునిక ప్రపంచంలో 5 సంవత్సరాలు కేవలం చాలా కాలం కాదు, కానీ చాలా పెద్ద మొత్తంలో. ఆ కాలం నుండి (ముఖ్యంగా మీరు విస్మరించిన మరియు పునరుద్ధరించబడిన జియోచాట్ సైట్‌లను పరిగణనలోకి తీసుకోకపోతే), పథకంలోని API పద్ధతుల సంఖ్య వంద నుండి రెండు వందల యాభైకి పెరిగింది!

యువ రచయితగా ఎక్కడ ప్రారంభించాలి?

మీరు మొదటి నుండి వ్రాసినా లేదా ఉపయోగించాలా అనేది పట్టింపు లేదు, ఉదాహరణకు, రెడీమేడ్ లైబ్రరీలు వంటివి పైథాన్ కోసం టెలిథాన్ లేదా PHP కోసం మేడ్‌లైన్, ఏ సందర్భంలో, మీరు మొదటి అవసరం మీ దరఖాస్తును నమోదు చేయండి - పారామితులను పొందండి api_id и api_hash (VKontakte APIతో పనిచేసిన వారు వెంటనే అర్థం చేసుకుంటారు) దీని ద్వారా సర్వర్ అప్లికేషన్‌ను గుర్తిస్తుంది. ఈ కలిగి ఉండాలి చట్టపరమైన కారణాల కోసం దీన్ని చేయండి, అయితే లైబ్రరీ రచయితలు దీన్ని రెండవ భాగంలో ఎందుకు ప్రచురించలేరు అనే దాని గురించి మేము మరింత మాట్లాడుతాము. మీరు పరీక్ష విలువలతో సంతృప్తి చెందవచ్చు, అవి చాలా పరిమితం అయినప్పటికీ - వాస్తవం ఇప్పుడు మీరు నమోదు చేసుకోవచ్చు ఒకే ఒక్కటి యాప్, కాబట్టి దానిలోకి తొందరపడకండి.

ఇప్పుడు, సాంకేతిక దృక్కోణం నుండి, రిజిస్ట్రేషన్ తర్వాత మేము డాక్యుమెంటేషన్, ప్రోటోకాల్ మొదలైన వాటికి నవీకరణల గురించి టెలిగ్రామ్ నుండి నోటిఫికేషన్‌లను స్వీకరించాలనే వాస్తవంపై మేము ఆసక్తి కలిగి ఉండాలి. అంటే, డాక్స్‌తో ఉన్న సైట్ కేవలం వదిలివేయబడిందని మరియు క్లయింట్‌లను తయారు చేయడం ప్రారంభించిన వారితో ప్రత్యేకంగా పని చేయడం కొనసాగించిందని ఎవరైనా అనుకోవచ్చు, ఎందుకంటే ఇది సులభం. కానీ, అలాంటిదేమీ గమనించలేదు, సమాచారం రాలేదు.

మరియు మీరు మొదటి నుండి వ్రాస్తే, అప్పుడు పొందిన పారామితులను ఉపయోగించడం వాస్తవానికి ఇంకా చాలా దూరంగా ఉంటుంది. అయినప్పటికీ https://core.telegram.org/ మరియు మొదటగా ప్రారంభించడంలో వాటి గురించి మాట్లాడుతుంది, వాస్తవానికి, మీరు మొదట అమలు చేయాల్సి ఉంటుంది MTP ప్రోటోకాల్ - కానీ మీరు విశ్వసిస్తే OSI మోడల్ ప్రకారం లేఅవుట్ ప్రోటోకాల్ యొక్క సాధారణ వివరణ కోసం పేజీ చివరిలో, అది పూర్తిగా ఫలించలేదు.

వాస్తవానికి, MTProtoకి ముందు మరియు తర్వాత, ఒకేసారి అనేక స్థాయిలలో (OS కెర్నల్‌లో పనిచేసే విదేశీ నెట్‌వర్కర్లు చెప్పినట్లు, లేయర్ ఉల్లంఘన), పెద్ద, బాధాకరమైన మరియు భయంకరమైన అంశం దారిలోకి వస్తుంది...

బైనరీ సీరియలైజేషన్: TL (టైప్ లాంగ్వేజ్) మరియు దాని స్కీమ్, మరియు లేయర్‌లు మరియు అనేక ఇతర భయానక పదాలు

ఈ అంశం, వాస్తవానికి, టెలిగ్రామ్ సమస్యలకు కీలకం. మరియు మీరు దానిని లోతుగా పరిశోధించడానికి ప్రయత్నిస్తే చాలా భయంకరమైన పదాలు ఉంటాయి.

కాబట్టి, ఇక్కడ రేఖాచిత్రం ఉంది. ఈ మాట మీ మనసులోకి వస్తే ఇలా చెప్పండి JSON స్కీమా, మీరు సరిగ్గా ఆలోచించారు. లక్ష్యం ఒకటే: ప్రసారం చేయబడిన డేటా యొక్క సాధ్యమైన సెట్‌ను వివరించడానికి కొన్ని భాష. ఇక్కడే సారూప్యతలు ముగుస్తాయి. పేజీ నుండి ఉంటే MTP ప్రోటోకాల్, లేదా అధికారిక క్లయింట్ యొక్క మూల వృక్షం నుండి, మేము కొన్ని స్కీమాను తెరవడానికి ప్రయత్నిస్తాము, మేము ఇలాంటివి చూస్తాము:

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;

దీన్ని మొదటిసారి చూసే వ్యక్తి అకారణంగా వ్రాసిన వాటిలో కొంత భాగాన్ని మాత్రమే గుర్తించగలడు - బాగా, ఇవి స్పష్టంగా నిర్మాణాలు (పేరు ఎక్కడ ఉన్నప్పటికీ, ఎడమ లేదా కుడి వైపున ఉంది?), వాటిలో ఫీల్డ్‌లు ఉన్నాయి, దీని తర్వాత ఒక పెద్దప్రేగు తర్వాత ఒక రకం వస్తుంది... బహుశా. ఇక్కడ యాంగిల్ బ్రాకెట్లలో బహుశా C++ (వాస్తవానికి, నిజంగా కాదు) మరియు అన్ని ఇతర చిహ్నాల అర్థం ఏమిటి, ప్రశ్న గుర్తులు, ఆశ్చర్యార్థక గుర్తులు, శాతాలు, హాష్ గుర్తులు (మరియు స్పష్టంగా అవి వేర్వేరు ప్రదేశాలలో వేర్వేరు విషయాలను సూచిస్తాయి), కొన్నిసార్లు ప్రస్తుత మరియు కొన్నిసార్లు కాదు, హెక్సాడెసిమల్ సంఖ్యలు - మరియు ముఖ్యంగా, దీని నుండి ఎలా పొందాలి సరైనది (సర్వర్ ద్వారా తిరస్కరించబడదు) బైట్ స్ట్రీమ్? మీరు డాక్యుమెంటేషన్ చదవవలసి ఉంటుంది (అవును, సమీపంలోని JSON వెర్షన్‌లో స్కీమాకి లింక్‌లు ఉన్నాయి - కానీ అది మరింత స్పష్టంగా లేదు).

పేజీని తెరవండి బైనరీ డేటా సీరియలైజేషన్ మరియు పుట్టగొడుగులు మరియు వివిక్త గణితశాస్త్రం యొక్క మాయా ప్రపంచంలోకి ప్రవేశించండి, ఇది 4వ సంవత్సరంలో మటన్ లాగా ఉంటుంది. ఆల్ఫాబెట్, టైప్, వాల్యూ, కాంబినేటర్, ఫంక్షనల్ కాంబినేటర్, నార్మల్ ఫారమ్, కాంపోజిట్ టైప్, పాలిమార్ఫిక్ టైప్... మరియు అది మొదటి పేజీ మాత్రమే! తదుపరిది మీ కోసం వేచి ఉంది TL భాష, ఇది ఇప్పటికే ఒక పనికిమాలిన అభ్యర్థన మరియు ప్రతిస్పందన యొక్క ఉదాహరణను కలిగి ఉన్నప్పటికీ, మరింత విలక్షణమైన కేసులకు అస్సలు సమాధానం ఇవ్వదు, అంటే మీరు రష్యన్ నుండి ఆంగ్లంలోకి అనువదించబడిన గణితాన్ని మరో ఎనిమిది పొందుపరిచిన రీటెల్లింగ్ ద్వారా చదవవలసి ఉంటుంది. పేజీలు!

ఫంక్షనల్ లాంగ్వేజ్‌లు మరియు ఆటోమేటిక్ టైప్ ఇన్‌ఫరెన్స్‌తో పరిచయం ఉన్న పాఠకులు, ఈ భాషలోని వివరణ భాషని, ఉదాహరణ నుండి కూడా, మరింత సుపరిచితమైనట్లుగా చూస్తారు మరియు ఇది వాస్తవానికి చెడ్డది కాదని చెప్పగలరు. దీనికి అభ్యంతరాలు:

  • అవును, లక్ష్యం బాగుంది, కానీ అయ్యో, ఆమె సాధించలేదు
  • రష్యన్ విశ్వవిద్యాలయాలలో విద్య IT ప్రత్యేకతల మధ్య కూడా మారుతుంది - ప్రతి ఒక్కరూ సంబంధిత కోర్సును తీసుకోలేదు
  • చివరగా, మేము చూస్తాము, ఆచరణలో ఇది అవసరం లేదు, వివరించిన TL యొక్క పరిమిత ఉపసమితి మాత్రమే ఉపయోగించబడుతుంది

చెప్పినట్లు లియోనెర్డ్ ఛానెల్‌లో #perl FreeNode IRC నెట్‌వర్క్‌లో, టెలిగ్రామ్ నుండి మ్యాట్రిక్స్‌కు గేట్‌ను అమలు చేయడానికి ప్రయత్నించారు (కోట్ యొక్క అనువాదం మెమరీ నుండి సరికాదు):

ఎవరైనా మొదటిసారిగా థియరీని టైప్ చేయడానికి పరిచయం చేయబడినట్లు అనిపిస్తుంది, ఉత్సాహంగా ఉంది మరియు ఆచరణలో ఇది అవసరమా లేదా అని నిజంగా పట్టించుకోకుండా దానితో ఆడుకోవడానికి ప్రయత్నించడం ప్రారంభించింది.

బేర్-టైప్‌ల (పూర్ణాంక, పొడవు, మొదలైనవి) ఏదైనా ప్రాథమికంగా అవసరం అనేది ప్రశ్నలను లేవనెత్తకపోతే - అంతిమంగా అవి మాన్యువల్‌గా అమలు చేయబడాలి - ఉదాహరణకు, వాటి నుండి ఉద్భవించే ప్రయత్నాన్ని చేద్దాం. వెక్టర్. అంటే నిజానికి శ్రేణి, మీరు ఫలిత వస్తువులను వాటి సరైన పేర్లతో పిలిస్తే.

కానీ ముందు

అధికారిక డాక్యుమెంటేషన్‌ను చదవని వారి కోసం TL సింటాక్స్ యొక్క ఉపసమితి యొక్క చిన్న వివరణ

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

fixed#abcdef34 id:int = Type2;

fixedVec set:Vector<Type2> = FixedVec;

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

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

నిర్వచనం ఎల్లప్పుడూ ప్రారంభమవుతుంది కన్స్ట్రక్టర్, దాని తర్వాత ఐచ్ఛికంగా (ఆచరణలో - ఎల్లప్పుడూ) చిహ్నం ద్వారా # ఉండాలి CRC32 ఈ రకమైన సాధారణ వివరణ స్ట్రింగ్ నుండి. తదుపరి ఫీల్డ్‌ల వివరణ వస్తుంది; అవి ఉనికిలో ఉంటే, రకం ఖాళీగా ఉండవచ్చు. ఇవన్నీ సమాన సంకేతంతో ముగుస్తాయి, ఈ కన్స్ట్రక్టర్ ఏ రకం పేరు - అంటే, వాస్తవానికి, సబ్టైప్ - చెందినది. సమాన గుర్తుకు కుడి వైపున ఉన్న వ్యక్తి బహురూప - అంటే, అనేక నిర్దిష్ట రకాలు దానికి అనుగుణంగా ఉంటాయి.

లైన్ తర్వాత నిర్వచనం ఏర్పడితే ---functions---, అప్పుడు వాక్యనిర్మాణం అలాగే ఉంటుంది, కానీ అర్థం భిన్నంగా ఉంటుంది: కన్స్ట్రక్టర్ RPC ఫంక్షన్ పేరు అవుతుంది, ఫీల్డ్‌లు పారామీటర్‌లుగా మారుతాయి (అలాగే, అంటే, క్రింద వివరించిన విధంగా ఇది సరిగ్గా అదే నిర్మాణంగా ఉంటుంది , ఇది కేవలం కేటాయించిన అర్థం), మరియు “పాలిమార్ఫిక్ రకం" - తిరిగి వచ్చిన ఫలితం రకం. నిజమే, ఇది ఇప్పటికీ పాలిమార్ఫిక్‌గా ఉంటుంది - విభాగంలో నిర్వచించబడింది ---types---, కానీ ఈ కన్స్ట్రక్టర్ "పరిగణించబడదు". కాల్డ్ ఫంక్షన్‌ల రకాలను వాటి వాదనల ద్వారా ఓవర్‌లోడ్ చేయడం, అనగా. కొన్ని కారణాల వలన, C++లో వలె ఒకే పేరుతో కానీ విభిన్న సంతకాలతో అనేక విధులు TLలో అందించబడలేదు.

OOP కాకపోతే "కన్‌స్ట్రక్టర్" మరియు "పాలిమార్ఫిక్" ఎందుకు? బాగా, నిజానికి, ఎవరైనా దీని గురించి OOP పరంగా ఆలోచించడం సులభం అవుతుంది - ఒక నైరూప్య తరగతిగా పాలిమార్ఫిక్ రకం, మరియు కన్స్ట్రక్టర్‌లు దాని ప్రత్యక్ష సంతతి తరగతులు, మరియు final అనేక భాషల పరిభాషలో. వాస్తవానికి, ఇక్కడ మాత్రమే సారూప్యత OO ప్రోగ్రామింగ్ భాషలలో నిజమైన ఓవర్‌లోడ్ కన్స్ట్రక్టర్ పద్ధతులతో. ఇక్కడ కేవలం డేటా స్ట్రక్చర్‌లు మాత్రమే ఉన్నందున, పద్ధతులు లేవు (ఫంక్షన్‌లు మరియు పద్ధతుల వివరణ మరింతగా అవి ఉన్నాయని తలలో గందరగోళాన్ని సృష్టించే సామర్థ్యాన్ని కలిగి ఉన్నప్పటికీ, అది వేరే విషయం) - మీరు కన్స్ట్రక్టర్‌ని దీని నుండి విలువగా భావించవచ్చు. ఏది నిర్మిస్తున్నారు బైట్ స్ట్రీమ్ చదివేటప్పుడు టైప్ చేయండి.

ఇది ఎలా జరుగుతుంది? ఎల్లప్పుడూ 4 బైట్‌లను చదివే డీరియలైజర్ విలువను చూస్తుంది 0xcrc32 - మరియు తరువాత ఏమి జరుగుతుందో అర్థం చేసుకుంటుంది field1 రకంతో int, అనగా సరిగ్గా 4 బైట్‌లను రీడ్ చేస్తుంది, దీనిపై టైప్‌తో ఓవర్‌లైయింగ్ ఫీల్డ్ PolymorType చదవండి. చూస్తాడు 0x2crc32 మరియు ముందుగా రెండు ఫీల్డ్‌లు ఉన్నాయని అర్థం చేసుకుంటాడు long, అంటే మనం 8 బైట్‌లను చదువుతాము. ఆపై మళ్లీ ఒక సంక్లిష్ట రకం, ఇది అదే విధంగా డీరియలైజ్ చేయబడింది. ఉదాహరణకి, Type3 ఇద్దరు కన్‌స్ట్రక్టర్‌లను వరుసగా సర్క్యూట్‌లో ప్రకటించవచ్చు, అప్పుడు వారు తప్పక కలుసుకోవాలి 0x12abcd34, ఆ తర్వాత మీరు మరో 4 బైట్‌లను చదవాలి int, లేదా 0x6789cdef, దాని తర్వాత ఏమీ ఉండదు. మరేదైనా - మీరు ఒక మినహాయింపు త్రో అవసరం. ఏమైనప్పటికీ, దీని తర్వాత మేము 4 బైట్లను చదవడానికి తిరిగి వెళ్తాము int ఖాళీలను field_c в constructorTwo మరియు దానితో మేము మా చదవడం పూర్తి చేస్తాము PolymorType.

చివరగా, మీరు పట్టుబడితే 0xdeadcrc కోసం constructorThree, అప్పుడు ప్రతిదీ మరింత క్లిష్టంగా మారుతుంది. మా మొదటి ఫీల్డ్ bit_flags_of_what_really_present రకంతో # - నిజానికి, ఇది రకానికి మారుపేరు మాత్రమే nat, "సహజ సంఖ్య" అని అర్థం. అంటే, వాస్తవానికి, సంతకం చేయని పూర్ణాంకానికి, నిజమైన సర్క్యూట్లలో సంతకం చేయని సంఖ్యలు సంభవించినప్పుడు మాత్రమే. కాబట్టి, తదుపరిది ప్రశ్న గుర్తుతో కూడిన నిర్మాణం, అంటే ఈ ఫీల్డ్ - సంబంధిత బిట్ సూచించిన ఫీల్డ్‌లో (సుమారుగా టెర్నరీ ఆపరేటర్ లాగా) సెట్ చేయబడితే మాత్రమే అది వైర్‌లో ఉంటుంది. కాబట్టి, ఈ బిట్ సెట్ చేయబడిందని అనుకుందాం, అంటే మనం మరింత ఫీల్డ్‌ని చదవాలి Type, ఇది మా ఉదాహరణలో 2 కన్స్ట్రక్టర్లను కలిగి ఉంది. ఒకటి ఖాళీగా ఉంది (ఐడెంటిఫైయర్‌ను మాత్రమే కలిగి ఉంటుంది), మరొకదానికి ఫీల్డ్ ఉంది ids రకంతో ids:Vector<long>.

టెంప్లేట్‌లు మరియు జెనరిక్స్ రెండూ ప్రోస్ లేదా జావాలో ఉన్నాయని మీరు అనుకోవచ్చు. కానీ కాదు. దాదాపు. ఈ మాత్రమే రియల్ సర్క్యూట్‌లలో యాంగిల్ బ్రాకెట్‌లను ఉపయోగించే సందర్భంలో, మరియు ఇది వెక్టర్ కోసం మాత్రమే ఉపయోగించబడుతుంది. బైట్ స్ట్రీమ్‌లో, ఇవి వెక్టర్ రకానికి 4 CRC32 బైట్‌లుగా ఉంటాయి, ఎల్లప్పుడూ ఒకే విధంగా ఉంటాయి, ఆపై 4 బైట్‌లు - శ్రేణి మూలకాల సంఖ్య, ఆపై ఈ మూలకాలు వాటికవే.

సీరియలైజేషన్ ఎల్లప్పుడూ 4 బైట్‌ల పదాలలో జరుగుతుంది అనే వాస్తవాన్ని దీనికి జోడించండి, అన్ని రకాలు దాని గుణకాలు - అంతర్నిర్మిత రకాలు కూడా వివరించబడ్డాయి bytes и string పొడవు యొక్క మాన్యువల్ సీరియలైజేషన్ మరియు 4 ద్వారా ఈ అమరికతో - బాగా, ఇది సాధారణంగా మరియు సాపేక్షంగా ప్రభావవంతంగా అనిపిస్తుంది? TL అనేది ప్రభావవంతమైన బైనరీ సీరియలైజేషన్ అని చెప్పబడినప్పటికీ, వాటితో నరకయాతన, దాదాపు ఏదైనా, బూలియన్ విలువలు మరియు సింగిల్ క్యారెక్టర్ స్ట్రింగ్‌లను 4 బైట్‌లకు విస్తరించడంతో, JSON ఇంకా చాలా మందంగా ఉంటుందా? చూడండి, అనవసరమైన ఫీల్డ్‌లను కూడా బిట్ ఫ్లాగ్‌లతో దాటవేయవచ్చు, ప్రతిదీ చాలా బాగుంది మరియు భవిష్యత్తు కోసం విస్తరించదగినది, కాబట్టి కొత్త ఐచ్ఛిక ఫీల్డ్‌లను తర్వాత కన్స్ట్రక్టర్‌కు ఎందుకు జోడించకూడదు?..

కానీ కాదు, మీరు నా క్లుప్త వివరణ కాదు, పూర్తి డాక్యుమెంటేషన్ చదివి, అమలు గురించి ఆలోచించినట్లయితే. ముందుగా, కన్స్ట్రక్టర్ యొక్క CRC32 స్కీమ్ యొక్క టెక్స్ట్ వివరణ యొక్క సాధారణీకరించిన లైన్ ప్రకారం లెక్కించబడుతుంది (అదనపు ఖాళీని తొలగించడం మొదలైనవి) - కాబట్టి కొత్త ఫీల్డ్ జోడించబడితే, టైప్ డిస్క్రిప్షన్ లైన్ మారుతుంది మరియు అందువల్ల దాని CRC32 మరియు , పర్యవసానంగా, సీరియలైజేషన్. మరియు పాత క్లయింట్ కొత్త ఫ్లాగ్‌లు సెట్ చేయబడిన ఫీల్డ్‌ను స్వీకరిస్తే, ఆపై వాటిని ఏమి చేయాలో అతనికి తెలియకపోతే ఏమి చేస్తాడు?...

రెండవది, గుర్తుంచుకోండి CRC32, ఇది ఇక్కడ తప్పనిసరిగా ఉపయోగించబడుతుంది హాష్ విధులు ఏ రకం (డి)సీరియలైజ్ చేయబడుతుందో ప్రత్యేకంగా గుర్తించడానికి. ఇక్కడ మనం ఘర్షణల సమస్యను ఎదుర్కొంటున్నాము - మరియు కాదు, సంభావ్యత 232లో ఒకటి కాదు, కానీ చాలా ఎక్కువ. కమ్యూనికేషన్ ఛానెల్‌లోని లోపాలను గుర్తించడానికి (మరియు సరిదిద్దడానికి) CRC32 రూపొందించబడిందని మరియు తదనుగుణంగా ఇతరులకు హాని కలిగించేలా ఈ లక్షణాలను మెరుగుపరుస్తుందని ఎవరు గుర్తు చేసుకున్నారు? ఉదాహరణకు, ఇది బైట్‌లను క్రమాన్ని మార్చడం గురించి పట్టించుకోదు: మీరు CRC32ని రెండు పంక్తుల నుండి గణిస్తే, రెండవది మీరు మొదటి 4 బైట్‌లను తదుపరి 4 బైట్‌లతో మార్చుకుంటారు - అదే విధంగా ఉంటుంది. మా ఇన్‌పుట్ లాటిన్ వర్ణమాల నుండి టెక్స్ట్ స్ట్రింగ్‌లుగా ఉన్నప్పుడు (మరియు కొద్దిగా విరామ చిహ్నాలు), మరియు ఈ పేర్లు ప్రత్యేకంగా యాదృచ్ఛికంగా లేనప్పుడు, అటువంటి పునర్వ్యవస్థీకరణ సంభావ్యత బాగా పెరుగుతుంది.

మార్గం ద్వారా, అక్కడ ఉన్నదాన్ని ఎవరు తనిఖీ చేశారు? నిజంగా CRC32? ప్రారంభ సోర్స్ కోడ్‌లలో ఒకటి (వాల్ట్‌మాన్ కంటే ముందు కూడా) హాష్ ఫంక్షన్‌ని కలిగి ఉంది, అది ప్రతి అక్షరాన్ని 239 సంఖ్యతో గుణించేది, ఈ వ్యక్తులకు చాలా ఇష్టమైనది, హ హ!

చివరగా, సరే, ఫీల్డ్ రకంతో కన్స్ట్రక్టర్లు ఉన్నారని మేము గ్రహించాము Vector<int> и Vector<PolymorType> విభిన్న CRC32ని కలిగి ఉంటుంది. ఆన్‌లైన్ పనితీరు గురించి ఏమిటి? మరియు సైద్ధాంతిక కోణం నుండి, ఇది రకంలో భాగం అవుతుందా? మనం పదివేల సంఖ్యల శ్రేణిని పాస్ చేశామని అనుకుందాం Vector<int> ప్రతిదీ స్పష్టంగా ఉంది, పొడవు మరియు మరో 40000 బైట్లు. మరియు ఇది ఉంటే Vector<Type2>, ఇది ఒకే ఫీల్డ్‌ను కలిగి ఉంటుంది int మరియు ఇది టైప్‌లో ఒంటరిగా ఉంది - మనం 10000xabcdef0 34 సార్లు మరియు 4 బైట్‌లను పునరావృతం చేయాలి int, లేదా భాష దానిని కన్స్ట్రక్టర్ నుండి మన కోసం స్వతంత్రంగా చేయగలదు fixedVec మరియు 80000 బైట్‌లకు బదులుగా, మళ్లీ 40000 మాత్రమే బదిలీ చేయాలా?

ఇది అస్సలు నిష్క్రియ సైద్ధాంతిక ప్రశ్న కాదు - మీరు సమూహ వినియోగదారుల జాబితాను స్వీకరిస్తారని ఊహించుకోండి, వారిలో ప్రతి ఒక్కరికి ఒక id, మొదటి పేరు, చివరి పేరు ఉంది - మొబైల్ కనెక్షన్ ద్వారా బదిలీ చేయబడిన డేటా మొత్తంలో వ్యత్యాసం గణనీయంగా ఉంటుంది. ఇది ఖచ్చితంగా టెలిగ్రామ్ సీరియలైజేషన్ యొక్క ప్రభావం గురించి మాకు ప్రచారం చేయబడింది.

కాబట్టి…

వెక్టర్, ఇది ఎప్పుడూ విడుదల కాలేదు

మీరు కాంబినేటర్‌ల వివరణ పేజీలను చదవడానికి ప్రయత్నిస్తే, వెక్టర్ (మరియు మ్యాట్రిక్స్ కూడా) అధికారికంగా అనేక షీట్‌ల టుపుల్‌ల ద్వారా అవుట్‌పుట్ చేయడానికి ప్రయత్నిస్తున్నట్లు మీరు చూస్తారు. కానీ చివరికి వారు మరచిపోతారు, చివరి దశ దాటవేయబడింది మరియు వెక్టర్ యొక్క నిర్వచనం కేవలం ఇవ్వబడుతుంది, ఇది ఇంకా ఒక రకానికి ముడిపడి లేదు. ఏంటి విషయం? భాషలలో ప్రోగ్రామింగ్, ముఖ్యంగా క్రియాత్మకమైనవి, నిర్మాణాన్ని పునరావృతంగా వివరించడం చాలా విలక్షణమైనది - దాని సోమరి మూల్యాంకనంతో కంపైలర్ ప్రతిదీ స్వయంగా అర్థం చేసుకుంటుంది మరియు చేస్తుంది. భాషలో డేటా సీరియలైజేషన్ కావలసిందల్లా సమర్థత: ఇది కేవలం వివరించడానికి సరిపోతుంది జాబితా, అనగా రెండు మూలకాల నిర్మాణం - మొదటిది డేటా మూలకం, రెండవది అదే నిర్మాణం లేదా తోక (ప్యాక్) కోసం ఖాళీ స్థలం (cons) లిస్ప్‌లో). కానీ ఇది స్పష్టంగా అవసరం ప్రతి మూలకం దాని రకాన్ని వివరించడానికి అదనంగా 4 బైట్‌లను (TLలో CRC32) ఖర్చు చేస్తుంది. శ్రేణిని కూడా సులభంగా వర్ణించవచ్చు స్థిర పరిమాణం, కానీ ముందుగానే తెలియని పొడవు యొక్క శ్రేణి విషయంలో, మేము విచ్ఛిన్నం చేస్తాము.

అందువల్ల, TL వెక్టార్‌ను అవుట్‌పుట్ చేయడాన్ని అనుమతించదు కాబట్టి, దానిని పక్కన జోడించాల్సి ఉంటుంది. చివరికి డాక్యుమెంటేషన్ ఇలా చెబుతోంది:

సీరియలైజేషన్ ఎల్లప్పుడూ ఒకే కన్స్ట్రక్టర్ “వెక్టర్” (const 0x1cb5c415 = crc32(“వెక్టర్ t:రకం # [t ] = వెక్టర్ t”)ని ఉపయోగిస్తుంది, ఇది టైప్ t యొక్క వేరియబుల్ యొక్క నిర్దిష్ట విలువపై ఆధారపడి ఉండదు.

ఐచ్ఛిక పరామితి t యొక్క విలువ సీరియలైజేషన్‌లో పాల్గొనదు ఎందుకంటే ఇది ఫలితం రకం నుండి తీసుకోబడింది (డీరియలైజేషన్‌కు ముందు ఎల్లప్పుడూ తెలిసినది).

నిశితంగా పరిశీలించండి: vector {t:Type} # [ t ] = Vector t - కానీ ఎక్కడా ఈ నిర్వచనం కూడా మొదటి సంఖ్య వెక్టార్ పొడవుకు సమానంగా ఉండాలి అని చెప్పలేదు! మరియు అది ఎక్కడి నుండి రాదు. ఇది గుర్తుంచుకోవలసిన మరియు మీ చేతులతో అమలు చేయవలసిన అవసరం. మరెక్కడా, డాక్యుమెంటేషన్ కూడా నిజాయితీగా ఈ రకం నిజమైనది కాదని పేర్కొంది:

వెక్టర్ t పాలిమార్ఫిక్ సూడోటైప్ అనేది ఒక “రకం”, దీని విలువ బాక్స్‌డ్ లేదా బేర్‌గా ఉండే ఏదైనా రకం t యొక్క విలువల క్రమం.

... కానీ దానిపై దృష్టి పెట్టదు. మీరు గణితాన్ని సాగదీయడం ద్వారా అలసిపోయినప్పుడు (మీకు యూనివర్సిటీ కోర్సు నుండి కూడా తెలిసి ఉండవచ్చు), వదిలివేయాలని నిర్ణయించుకుని, ఆచరణలో దానితో ఎలా పని చేయాలో చూడండి, ఇది చాలా తీవ్రమైనది అనే అభిప్రాయం మీ తలలో మిగిలిపోతుంది. కోర్ వద్ద గణితశాస్త్రం, ఇది కూల్ పీపుల్ (ఇద్దరు గణిత శాస్త్రజ్ఞులు - ACM విజేత) ద్వారా స్పష్టంగా కనుగొనబడింది మరియు ఎవరైనా కాదు. లక్ష్యం - ప్రదర్శించడం - సాధించబడింది.

మార్గం ద్వారా, సంఖ్య గురించి. అది మీకు గుర్తు చేద్దాం # అది ఒక పర్యాయపదం nat, సహజ సంఖ్య:

టైప్ ఎక్స్‌ప్రెషన్స్ ఉన్నాయి (రకం-expr) మరియు సంఖ్యా వ్యక్తీకరణలు (nat-expr) అయితే, అవి అదే విధంగా నిర్వచించబడ్డాయి.

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

కానీ వ్యాకరణంలో అవి అదే విధంగా వివరించబడ్డాయి, అనగా. ఈ వ్యత్యాసాన్ని మళ్లీ గుర్తుంచుకోవాలి మరియు మానవీయంగా అమలులోకి తీసుకురావాలి.

సరే, అవును, టెంప్లేట్ రకాలు (vector<int>, vector<User>) ఒక సాధారణ ఐడెంటిఫైయర్ (#1cb5c415), అనగా. మీకు తెలిస్తే కాల్ అని ప్రకటించబడింది

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

అప్పుడు మీరు ఇకపై కేవలం వెక్టర్ కోసం వేచి ఉండరు, కానీ వినియోగదారుల వెక్టర్. చాల ఖచ్చితంగా, తప్పక వేచి ఉండండి - నిజమైన కోడ్‌లో, ప్రతి మూలకం, బేర్ రకం కాకపోతే, ఒక కన్స్ట్రక్టర్‌ను కలిగి ఉంటుంది మరియు అమలులో మంచి మార్గంలో తనిఖీ చేయడం అవసరం - కానీ మేము ఈ వెక్టర్‌లోని ప్రతి మూలకంలో ఖచ్చితంగా పంపబడ్డాము ఆ రకం? ఇది ఒక రకమైన PHP అయితే, శ్రేణి వివిధ అంశాలలో వివిధ రకాలను కలిగి ఉంటే?

ఈ సమయంలో మీరు ఆలోచించడం ప్రారంభిస్తారు - అటువంటి TL అవసరమా? బహుశా బండి కోసం మానవ సీరియలైజర్‌ను ఉపయోగించడం సాధ్యమేనా, అప్పటికి ఇప్పటికే ఉన్న అదే ప్రోటోబఫ్? అది సిద్ధాంతం, ఆచరణలో చూద్దాం.

కోడ్‌లో ఇప్పటికే ఉన్న TL అమలులు

డ్యూరోవ్ వాటా విక్రయంతో ప్రసిద్ధ సంఘటనలకు ముందే TL VKontakte యొక్క లోతులలో జన్మించింది మరియు (బహుశా), టెలిగ్రామ్ అభివృద్ధి ప్రారంభానికి ముందే. మరియు ఓపెన్ సోర్స్‌లో మొదటి అమలు యొక్క సోర్స్ కోడ్ మీరు చాలా ఫన్నీ క్రచెస్‌లను కనుగొనవచ్చు. మరియు టెలిగ్రామ్‌లో ఇప్పుడు ఉన్నదాని కంటే భాష కూడా పూర్తిగా అక్కడ అమలు చేయబడింది. ఉదాహరణకు, స్కీమ్‌లో హాష్‌లు అస్సలు ఉపయోగించబడవు (అంటే విపరీతమైన ప్రవర్తనతో అంతర్నిర్మిత సూడోటైప్ (వెక్టార్ లాంటిది)). లేదా

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

అయితే సంపూర్ణత కొరకు, ఆలోచనా దిగ్గజం యొక్క పరిణామాన్ని కనుక్కోవడానికి, కనుక్కోవడానికి పరిశీలిద్దాం.

#define ZHUKOV_BYTES_HACK

#ifdef ZHUKOV_BYTES_HACK

/* dirty hack for Zhukov request */

లేదా ఈ అందమైనది:

    static const char *reserved_words_polymorhic[] = {

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

      };

ఈ భాగం ఇలాంటి టెంప్లేట్‌లకు సంబంధించినది:

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

ఇది హ్యాష్‌మ్యాప్ టెంప్లేట్ రకానికి పూర్ణాంక - రకం జతల వెక్టర్‌గా నిర్వచనం. C++లో ఇది ఇలా ఉంటుంది:

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

కాబట్టి, alpha - కీవర్డ్! కానీ C++ లో మాత్రమే మీరు T వ్రాయగలరు, కానీ మీరు ఆల్ఫా, బీటా వ్రాయాలి ... కానీ 8 పారామీటర్ల కంటే ఎక్కువ ఉండకూడదు, ఇక్కడ ఫాంటసీ ముగుస్తుంది. ఒకప్పుడు సెయింట్ పీటర్స్‌బర్గ్‌లో ఇలాంటి డైలాగులు జరిగినట్లు అనిపిస్తుంది:

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

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

కానీ ఇది "సాధారణంగా" TL యొక్క మొదటి ప్రచురించబడిన అమలు గురించి. టెలిగ్రామ్ క్లయింట్‌లలోనే అమలులను పరిగణలోకి తీసుకుంటాము.

వాసిలీకి పదం:

వాసిలీ, [09.10.18 17:07] అన్నింటికంటే, గాడిద వేడిగా ఉంది, ఎందుకంటే వారు సంగ్రహాల సమూహాన్ని సృష్టించారు, ఆపై వాటిపై ఒక బోల్ట్‌ను కొట్టారు మరియు కోడ్ జనరేటర్‌ను క్రచెస్‌తో కప్పారు.
ఫలితంగా, మొదట డాక్ pilot.jpg నుండి
అప్పుడు కోడ్ dzhekichan.webp నుండి

వాస్తవానికి, అల్గారిథమ్‌లు మరియు గణితశాస్త్రం గురించి తెలిసిన వ్యక్తుల నుండి, వారు అహో, ఉల్‌మాన్‌లను చదివారని మరియు వారి DSL కంపైలర్‌లను వ్రాయడానికి దశాబ్దాలుగా పరిశ్రమలో వాస్తవ ప్రమాణంగా మారిన సాధనాలతో సుపరిచితులని మేము ఆశించవచ్చు, సరియైనదా?

రచయిత టెలిగ్రామ్-cli విటాలీ వాల్ట్‌మాన్, TLO ఫార్మాట్ దాని (cli) సరిహద్దుల వెలుపల కనిపించడం ద్వారా అర్థం చేసుకోవచ్చు, జట్టు సభ్యుడు - ఇప్పుడు TL పార్సింగ్ కోసం లైబ్రరీ కేటాయించబడింది విడిగా, ఆమె యొక్క ముద్ర ఏమిటి TL పార్సర్? ..

16.12 04:18 వాసిలీ: లెక్స్+యాక్‌లో ఎవరైనా నైపుణ్యం సాధించలేదని నేను అనుకుంటున్నాను
16.12 04:18 వాసిలీ: నేను దానిని వేరే విధంగా వివరించలేను
16.12 04:18 వాసిలీ: బాగా, లేదా VKలోని పంక్తుల సంఖ్యకు వారు చెల్లించబడ్డారు
16.12 04:19 వాసిలీ: 3k+ పంక్తులు మొదలైనవి.<censored> పార్సర్‌కు బదులుగా

బహుశా మినహాయింపు? ఎలాగో చూద్దాం తయారీలను ఇది అధికారిక క్లయింట్ - టెలిగ్రామ్ డెస్క్‌టాప్:

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

పైథాన్‌లో 1100+ పంక్తులు, రెండు సాధారణ వ్యక్తీకరణలు + వెక్టర్ వంటి ప్రత్యేక సందర్భాలు, ఇది TL సింటాక్స్ ప్రకారం ఉండాలి అని స్కీమ్‌లో ప్రకటించబడింది, అయితే వారు దానిని అన్వయించడానికి ఈ సింటాక్స్‌పై ఆధారపడ్డారు... ప్రశ్న తలెత్తుతుంది, ఇదంతా ఎందుకు అద్భుతం?иఏమైనప్పటికీ డాక్యుమెంటేషన్ ప్రకారం ఎవరూ దానిని అన్వయించనట్లయితే ఇది మరింత పొరలుగా ఉంటుంది?!

మార్గం ద్వారా... మేము CRC32 తనిఖీ గురించి మాట్లాడినట్లు గుర్తుందా? కాబట్టి, టెలిగ్రామ్ డెస్క్‌టాప్ కోడ్ జెనరేటర్‌లో CRC32 లెక్కించబడిన రకాలకు మినహాయింపుల జాబితా ఉంది. సరిపోలడం లేదు రేఖాచిత్రంలో సూచించిన దానితో!

వాసిలీ, [18.12/22 49:XNUMX] మరియు ఇక్కడ నేను అలాంటి TL అవసరమా అని ఆలోచిస్తాను
నేను ప్రత్యామ్నాయ అమలులతో గజిబిజి చేయాలనుకుంటే, నేను లైన్ బ్రేక్‌లను చొప్పించడం ప్రారంభిస్తాను, సగం పార్సర్‌లు బహుళ-లైన్ నిర్వచనాలపై విరిగిపోతాయి
tdesktop, అయితే, కూడా

వన్-లైనర్ గురించి విషయాన్ని గుర్తుంచుకోండి, మేము కొంచెం తర్వాత దానికి తిరిగి వస్తాము.

సరే, టెలిగ్రామ్-క్లి అనధికారికం, టెలిగ్రామ్ డెస్క్‌టాప్ అధికారికం, అయితే మిగతా వాటి సంగతేంటి? ఎవరికి తెలుసు?.. ఆండ్రాయిడ్ క్లయింట్ కోడ్‌లో స్కీమా పార్సర్ అస్సలు లేదు (ఇది ఓపెన్ సోర్స్ గురించి ప్రశ్నలను లేవనెత్తుతుంది, కానీ ఇది రెండవ భాగానికి సంబంధించినది), కానీ అనేక ఇతర ఫన్నీ ముక్కలు ఉన్నాయి, కానీ వాటిపై మరిన్ని దిగువ ఉపవిభాగం.

సీరియలైజేషన్ ఆచరణలో ఏ ఇతర ప్రశ్నలను లేవనెత్తుతుంది? ఉదాహరణకు, వారు బిట్ ఫీల్డ్‌లు మరియు షరతులతో కూడిన ఫీల్డ్‌లతో చాలా పనులు చేసారు:

వాసిలీ: flags.0? true
ఫీల్డ్ ఉంది మరియు జెండా సెట్ చేయబడితే అది నిజం అని అర్థం

వాసిలీ: flags.1? int
ఫీల్డ్ ప్రస్తుతం ఉందని మరియు డీరియలైజ్ చేయబడాలని అర్థం

వాసిలీ: గాడిద, మీరు ఏమి చేస్తున్నారో చింతించకండి!
వాసిలీ: నిజం అనేది బేర్ జీరో-లెంగ్త్ రకం అని డాక్యుమెంట్‌లో ఎక్కడో ప్రస్తావించబడింది, కానీ వారి పత్రం నుండి ఏదైనా సమీకరించడం అసాధ్యం
వాసిలీ: ఓపెన్ సోర్స్ ఇంప్లిమెంటేషన్స్‌లో ఇది అలా కాదు, కానీ కొన్ని క్రచెస్ మరియు సపోర్టులు ఉన్నాయి

టెలిథాన్ గురించి ఏమిటి? MTProto అంశం కోసం ఎదురుచూడడం, ఒక ఉదాహరణ - డాక్యుమెంటేషన్‌లో అటువంటి ముక్కలు ఉన్నాయి, కానీ గుర్తు % ఇది "ఇచ్చిన బేర్-టైప్‌కు సంబంధించినది" అని మాత్రమే వర్ణించబడింది, అనగా. దిగువ ఉదాహరణలలో లోపం లేదా ఏదైనా నమోదుకానిది ఉంది:

వాసిలీ, [22.06.18 18:38] ఒకే చోట:

msg_container#73f1f8dc messages:vector message = MessageContainer;

వేరొకదానిలో:

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

మరియు ఇవి రెండు పెద్ద తేడాలు, నిజ జీవితంలో ఒక రకమైన నేకెడ్ వెక్టర్ వస్తుంది

నేను బేర్ వెక్టార్ నిర్వచనాన్ని చూడలేదు మరియు దానిని చూడలేదు

విశ్లేషణ టెలిథాన్‌లో చేతితో వ్రాయబడింది

అతని రేఖాచిత్రంలో నిర్వచనం వ్యాఖ్యానించబడింది msg_container

మళ్ళీ, ప్రశ్న % గురించి మిగిలి ఉంది. ఇది వర్ణించబడలేదు.

వాడిమ్ గోంచరోవ్, [22.06.18 19:22] మరియు tdesktopలో ఉన్నారా?

వాసిలీ, [22.06.18 19:23] కానీ సాధారణ ఇంజిన్‌లలోని వారి TL పార్సర్ దీన్ని కూడా తినదు.

// parsed manually

TL అనేది ఒక అందమైన సంగ్రహణ, ఎవరూ దానిని పూర్తిగా అమలు చేయరు

మరియు % వారి స్కీమ్ వెర్షన్‌లో లేదు

కానీ ఇక్కడ డాక్యుమెంటేషన్ విరుద్ధంగా ఉంది, కాబట్టి idk

ఇది వ్యాకరణంలో కనుగొనబడింది, వారు అర్థశాస్త్రాన్ని వివరించడం మర్చిపోయారు

మీరు TLలో పత్రాన్ని చూశారు, అర లీటరు లేకుండా మీరు దాన్ని గుర్తించలేరు

"సరే, చెప్పనివ్వండి," మరొక పాఠకుడు ఇలా అంటాడు, "మీరు దేనినైనా విమర్శిస్తారు, కాబట్టి అది ఎలా చేయాలో నాకు చూపించండి."

వాసిలీ ఇలా సమాధానమిచ్చాడు: “పార్సర్ విషయానికొస్తే, నాకు ఇలాంటివి ఇష్టం

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

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

ఏదో ఒకవిధంగా దాని కంటే బాగా ఇష్టం

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

లేదా

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

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

ఇది హోల్ లెక్సర్:

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

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

ఆ. తేలికగా ఉంచడం చాలా సులభం."

సాధారణంగా, ఫలితంగా, TL యొక్క వాస్తవంగా ఉపయోగించిన ఉపసమితి కోసం పార్సర్ మరియు కోడ్ జనరేటర్ సుమారుగా 100 లైన్ల వ్యాకరణం మరియు ~300 లైన్ల జనరేటర్‌లకు సరిపోతాయి (అన్నీ లెక్కించబడతాయి printయొక్క రూపొందించిన కోడ్), ప్రతి తరగతిలో ఆత్మపరిశీలన కోసం టైప్ ఇన్ఫర్మేషన్ బన్నీస్‌తో సహా. ప్రతి పాలిమార్ఫిక్ రకం ఖాళీ అబ్‌స్ట్రాక్ట్ బేస్ క్లాస్‌గా మారుతుంది మరియు కన్స్ట్రక్టర్‌లు దాని నుండి వారసత్వంగా మరియు సీరియలైజేషన్ మరియు డీరియలైజేషన్ కోసం పద్ధతులను కలిగి ఉంటారు.

రకం భాషలో రకాలు లేకపోవడం

బలమైన టైపింగ్ మంచి విషయం, సరియైనదా? లేదు, ఇది హోలివర్ కాదు (నేను డైనమిక్ భాషలను ఇష్టపడుతున్నాను), కానీ TL ఫ్రేమ్‌వర్క్‌లోని ఒక ప్రతిపాదన. దాని ఆధారంగా, భాష మాకు అన్ని రకాల చెక్కులను అందించాలి. బాగా, సరే, బహుశా అతను స్వయంగా కాదు, కానీ అమలు, కానీ అతను కనీసం వాటిని వివరించాలి. మరి మనకు ఎలాంటి అవకాశాలు కావాలి?

అన్నింటిలో మొదటిది, పరిమితులు. ఫైల్‌లను అప్‌లోడ్ చేయడానికి మేము డాక్యుమెంటేషన్‌లో ఇక్కడ చూస్తాము:

ఫైల్ యొక్క బైనరీ కంటెంట్ అప్పుడు భాగాలుగా విభజించబడింది. అన్ని భాగాలు ఒకే పరిమాణాన్ని కలిగి ఉండాలి ( భాగం_పరిమాణం ) మరియు కింది షరతులు తప్పక పాటించాలి:

  • part_size % 1024 = 0 (1KB ద్వారా విభజించబడింది)
  • 524288 % part_size = 0 (512KB తప్పనిసరిగా పార్ట్_సైజ్ ద్వారా సమానంగా విభజించబడాలి)

చివరి భాగం ఈ షరతులను సంతృప్తిపరచవలసిన అవసరం లేదు, దాని పరిమాణం part_size కంటే తక్కువగా ఉంటే.

ప్రతి భాగానికి క్రమం సంఖ్య ఉండాలి, ఫైల్_భాగం, విలువ 0 నుండి 2,999 వరకు ఉంటుంది.

ఫైల్ విభజించబడిన తర్వాత మీరు దానిని సర్వర్‌లో సేవ్ చేయడానికి ఒక పద్ధతిని ఎంచుకోవాలి. వా డు upload.saveBigFilePart ఫైల్ యొక్క పూర్తి పరిమాణం 10 MB కంటే ఎక్కువగా ఉంటే మరియు upload.saveFilePart చిన్న ఫైళ్ళ కోసం.
[…] కింది డేటా ఇన్‌పుట్ ఎర్రర్‌లలో ఒకటి తిరిగి రావచ్చు:

  • FILE_PARTS_INVALID — చెల్లని భాగాల సంఖ్య. విలువ మధ్య లేదు 1..3000

రేఖాచిత్రంలో వీటిలో ఏదైనా ఉందా? ఇది TLని ఉపయోగించి ఏదో విధంగా వ్యక్తీకరించబడుతుందా? నం. కానీ నన్ను క్షమించండి, తాత యొక్క టర్బో పాస్కల్ కూడా పేర్కొన్న రకాలను వివరించగలిగింది పరిధులు. మరియు అతనికి మరొక విషయం తెలుసు, ఇప్పుడు బాగా ప్రసిద్ధి చెందింది enum - స్థిరమైన (చిన్న) విలువల సంఖ్యను కలిగి ఉండే రకం. సి-న్యూమరిక్ వంటి భాషలలో, మేము ఇప్పటివరకు రకాలు గురించి మాత్రమే మాట్లాడామని గమనించండి సంఖ్యలు. కానీ శ్రేణులు, స్ట్రింగ్‌లు కూడా ఉన్నాయి... ఉదాహరణకు, ఈ స్ట్రింగ్‌లో ఫోన్ నంబర్ మాత్రమే ఉంటుందని వివరించడం మంచిది, సరియైనదా?

ఇవేవీ TLలో లేవు. కానీ, ఉదాహరణకు, JSON స్కీమాలో ఉంది. మరియు ఎవరైనా 512 KB యొక్క విభజన గురించి వాదించినట్లయితే, ఇది ఇప్పటికీ కోడ్‌లో తనిఖీ చేయబడాలి, అప్పుడు క్లయింట్ కేవలం అని నిర్ధారించుకోండి నేను చేయలేకపోయాను పరిధి వెలుపల సంఖ్యను పంపండి 1..3000 (మరియు సంబంధిత లోపం తలెత్తలేదు) ఇది సాధ్యమయ్యేది, సరియైనదా? ..

మార్గం ద్వారా, లోపాలు మరియు రిటర్న్ విలువల గురించి. TLతో పనిచేసిన వారు కూడా తమ కళ్లను అస్పష్టం చేస్తారు - అది మాకు వెంటనే తెలియలేదు ప్రతి ఒక్కరు TLలోని ఒక ఫంక్షన్ వాస్తవానికి వివరించిన రిటర్న్ రకాన్ని మాత్రమే కాకుండా, ఎర్రర్‌ను కూడా అందిస్తుంది. కానీ ఇది TL ను ఉపయోగించి ఏ విధంగానూ తీసివేయబడదు. వాస్తవానికి, ఇది ఇప్పటికే స్పష్టంగా ఉంది మరియు ఆచరణలో ఏమీ అవసరం లేదు (వాస్తవానికి, RPCని వివిధ మార్గాల్లో చేయవచ్చు, మేము దీని తర్వాత తిరిగి వస్తాము) - కానీ వియుక్త రకాల గణిత భావనల స్వచ్ఛత గురించి ఏమిటి స్వర్గ లోకం నుండి?

మరియు చివరగా, చదవడం గురించి ఏమిటి? బాగా, అక్కడ, సాధారణంగా, నేను కోరుకుంటున్నాను వివరణ ఇది స్కీమాలో సరిగ్గా ఉందా (JSON స్కీమాలో, మళ్ళీ, ఇది), కానీ మీరు ఇప్పటికే దానితో ఒత్తిడికి గురైతే, ఆచరణాత్మక పక్షం గురించి ఏమిటి - కనీసం అప్‌డేట్‌ల సమయంలో తేడాలను చూడటం లేదా? వద్ద మీ కోసం చూడండి నిజమైన ఉదాహరణలు:

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

లేదా

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

ఇది ప్రతి ఒక్కరిపై ఆధారపడి ఉంటుంది, అయితే GitHub, ఉదాహరణకు, అటువంటి పొడవైన పంక్తులలో మార్పులను హైలైట్ చేయడానికి నిరాకరిస్తుంది. గేమ్ “10 తేడాలను కనుగొనండి”, మరియు మెదడు వెంటనే చూసేది ఏమిటంటే, రెండు ఉదాహరణలలోని ప్రారంభాలు మరియు ముగింపులు ఒకేలా ఉంటాయి, మీరు మధ్యలో ఎక్కడో ఒకచోట విసుగుగా చదవాలి... నా అభిప్రాయం ప్రకారం, ఇది సిద్ధాంతంలో మాత్రమే కాదు, కానీ పూర్తిగా దృశ్యమానంగా మురికి మరియు అలసత్వము.

మార్గం ద్వారా, సిద్ధాంతం యొక్క స్వచ్ఛత గురించి. మనకు బిట్ ఫీల్డ్‌లు ఎందుకు అవసరం? వారు అని అనిపించడం లేదు వాసన రకం సిద్ధాంతం దృక్కోణం నుండి చెడు? రేఖాచిత్రం యొక్క మునుపటి సంస్కరణల్లో వివరణను చూడవచ్చు. మొదట, అవును, అది ఎలా ఉంది, ప్రతి తుమ్ము కోసం ఒక కొత్త రకం సృష్టించబడింది. ఈ మూలాధారాలు ఇప్పటికీ ఈ రూపంలో ఉన్నాయి, ఉదాహరణకు:

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

కానీ ఇప్పుడు ఊహించుకోండి, మీరు మీ నిర్మాణంలో 5 ఐచ్ఛిక ఫీల్డ్‌లను కలిగి ఉంటే, అప్పుడు సాధ్యమయ్యే అన్ని ఎంపికల కోసం మీకు 32 రకాలు అవసరం. కాంబినేటోరియల్ పేలుడు. అందువలన, TL సిద్ధాంతం యొక్క క్రిస్టల్ స్వచ్ఛత మరోసారి సీరియలైజేషన్ యొక్క కఠినమైన వాస్తవికత యొక్క తారాగణం-ఇనుప గాడిదకు వ్యతిరేకంగా పగిలిపోయింది.

అదనంగా, కొన్ని ప్రదేశాలలో ఈ కుర్రాళ్ళు తమ స్వంత టైపోలాజీని ఉల్లంఘిస్తారు. ఉదాహరణకు, MTProto (తదుపరి అధ్యాయం)లో ప్రతిస్పందనను Gzip ద్వారా కుదించవచ్చు, ప్రతిదీ బాగానే ఉంటుంది - పొరలు మరియు సర్క్యూట్ ఉల్లంఘించబడటం మినహా. మరోసారి, అది RpcResult కాదు, కానీ దాని కంటెంట్. సరే, ఇలా ఎందుకు చేయాలి?.. కుదింపు ఎక్కడైనా పని చేసేలా నేను ఊతకర్రగా కత్తిరించాల్సి వచ్చింది.

లేదా మరొక ఉదాహరణ, మేము ఒకసారి లోపాన్ని కనుగొన్నాము - అది పంపబడింది InputPeerUser బదులుగా InputUser. లేదా వైస్ వెర్సా. కానీ అది పని చేసింది! అంటే, సర్వర్ రకం గురించి పట్టించుకోలేదు. ఇది ఎలా ఉంటుంది? టెలిగ్రామ్-క్లి నుండి కోడ్ శకలాలు మాకు సమాధానం ఇవ్వవచ్చు:

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

మరో మాటలో చెప్పాలంటే, ఇక్కడే సీరియలైజేషన్ జరుగుతుంది మానవీయంగా, కోడ్ రూపొందించబడలేదు! బహుశా సర్వర్ ఇదే విధంగా అమలు చేయబడి ఉంటుందా?.. సూత్రప్రాయంగా, ఇది ఒకసారి చేస్తే పని చేస్తుంది, కానీ నవీకరణల సమయంలో దీన్ని ఎలా సపోర్ట్ చేయవచ్చు? అందుకే ఈ పథకం కనిపెట్టారా? మరియు ఇక్కడ మేము తదుపరి ప్రశ్నకు వెళ్తాము.

సంస్కరణ. పొరలు

స్కీమాటిక్ వెర్షన్‌లను లేయర్‌లు అని ఎందుకు అంటారు అనేది ప్రచురించబడిన స్కీమాటిక్స్ చరిత్ర ఆధారంగా మాత్రమే ఊహించవచ్చు. స్పష్టంగా, మొదట రచయితలు మారని స్కీమ్‌ను ఉపయోగించి ప్రాథమిక పనులు చేయవచ్చని భావించారు మరియు అవసరమైన చోట మాత్రమే, నిర్దిష్ట అభ్యర్థనల కోసం, అవి వేరే సంస్కరణను ఉపయోగించి జరుగుతున్నాయని సూచిస్తున్నాయి. సూత్రప్రాయంగా, ఇది చెడ్డ ఆలోచన కానప్పటికీ, కొత్తది "మిశ్రమంగా" ఉంటుంది, అది పాతదానిపై పొరలుగా ఉంటుంది. అయితే అది ఎలా జరిగిందో చూద్దాం. నిజమే, నేను దీన్ని మొదటి నుండి చూడలేకపోయాను - ఇది ఫన్నీ, కానీ బేస్ లేయర్ యొక్క రేఖాచిత్రం ఉనికిలో లేదు. లేయర్‌లు 2తో ప్రారంభమయ్యాయి. డాక్యుమెంటేషన్ ప్రత్యేక TL ఫీచర్ గురించి చెబుతుంది:

క్లయింట్ లేయర్ 2కి మద్దతిస్తే, కింది కన్స్ట్రక్టర్‌ని తప్పనిసరిగా ఉపయోగించాలి:

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

ఆచరణలో, దీని అర్థం ప్రతి API కాల్‌కు ముందు, విలువతో కూడిన పూర్ణాంక 0x289dd1f6 పద్ధతి సంఖ్యకు ముందు తప్పనిసరిగా జోడించాలి.

మామూలుగా అనిపిస్తుంది. అయితే తర్వాత ఏం జరిగింది? అప్పుడు కనిపించింది

invokeWithLayer3#b7475268 query:!X = X;

కాబట్టి తదుపరి ఏమిటి? మీరు ఊహించినట్లుగా,

invokeWithLayer4#dea0d430 query:!X = X;

తమాషా? లేదు, నవ్వడం చాలా తొందరగా ఉంది, దాని గురించి ఆలోచించండి ప్రతి మరొక పొర నుండి ఒక అభ్యర్థన అటువంటి ప్రత్యేక రకంలో చుట్టబడాలి - అవన్నీ మీకు భిన్నంగా ఉంటే, మీరు వాటిని ఎలా వేరు చేయవచ్చు? మరియు ముందు కేవలం 4 బైట్‌లను జోడించడం చాలా సమర్థవంతమైన పద్ధతి. కాబట్టి,

invokeWithLayer5#417a57ae query:!X = X;

కానీ కొంతకాలం తర్వాత ఇది ఒక రకమైన బచ్చనాలియాగా మారుతుందని స్పష్టంగా తెలుస్తుంది. మరియు పరిష్కారం వచ్చింది:

అప్‌డేట్: లేయర్ 9తో ప్రారంభించి, సహాయక పద్ధతులు invokeWithLayerN కలిపి మాత్రమే ఉపయోగించవచ్చు initConnection

హుర్రే! 9 సంస్కరణల తర్వాత, 80వ దశకంలో ఇంటర్నెట్ ప్రోటోకాల్‌లలో చేసిన దానికి మేము చివరకు వచ్చాము - కనెక్షన్ ప్రారంభంలో ఒకసారి సంస్కరణను అంగీకరించడం!

కాబట్టి తదుపరి ఏమిటి? ..

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

కానీ ఇప్పుడు మీరు ఇంకా నవ్వగలరు. మరో 9 లేయర్‌ల తర్వాత మాత్రమే, వెర్షన్ నంబర్‌తో యూనివర్సల్ కన్స్ట్రక్టర్ చివరకు జోడించబడింది, ఇది కనెక్షన్ ప్రారంభంలో ఒక్కసారి మాత్రమే కాల్ చేయవలసి ఉంటుంది మరియు లేయర్‌ల అర్థం అదృశ్యమైనట్లు అనిపించింది, ఇప్పుడు ఇది కేవలం షరతులతో కూడిన సంస్కరణ. మిగతా అన్నిచోట్లా. సమస్య తీరింది.

సరిగ్గా? ..

వాసిలీ, [16.07.18 14:01] శుక్రవారం కూడా నేను ఇలా అనుకున్నాను:
టెలిసర్వర్ అభ్యర్థన లేకుండా ఈవెంట్‌లను పంపుతుంది. అభ్యర్థనలు తప్పనిసరిగా InvokeWithLayerలో చుట్టబడి ఉండాలి. సర్వర్ నవీకరణలను చుట్టదు;

ఆ. క్లయింట్ అతను నవీకరణలను కోరుకుంటున్న లేయర్‌ను పేర్కొనలేరు

వాడిమ్ గోంచరోవ్, [16.07.18 14:02] ఇన్‌వోక్‌విత్‌లేయర్ సూత్రప్రాయంగా ఊతకర్ర కాదా?

వాసిలీ, [16.07.18 14:02] ఇది ఒక్కటే మార్గం

వాడిమ్ గోంచరోవ్, [16.07.18 14:02] అంటే సెషన్ ప్రారంభంలో పొరను అంగీకరించడం

మార్గం ద్వారా, క్లయింట్ డౌన్‌గ్రేడ్ అందించబడలేదని ఇది అనుసరిస్తుంది

నవీకరణలు, అనగా. రకం Updates పథకంలో, API అభ్యర్థనకు ప్రతిస్పందనగా కాకుండా, ఈవెంట్ సంభవించినప్పుడు స్వతంత్రంగా సర్వర్ క్లయింట్‌కు పంపుతుంది. ఇది మరొక పోస్ట్‌లో చర్చించబడే సంక్లిష్టమైన అంశం, అయితే క్లయింట్ ఆఫ్‌లైన్‌లో ఉన్నప్పుడు కూడా సర్వర్ నవీకరణలను సేవ్ చేస్తుందని తెలుసుకోవడం ముఖ్యం.

అందువలన, మీరు చుట్టడానికి నిరాకరిస్తే ప్రతి ప్యాకేజీ దాని సంస్కరణను సూచించడానికి, ఇది తార్కికంగా క్రింది సాధ్యమయ్యే సమస్యలకు దారి తీస్తుంది:

  • క్లయింట్ ఏ సంస్కరణకు మద్దతు ఇస్తుందో తెలియజేయడానికి ముందే సర్వర్ క్లయింట్‌కు నవీకరణలను పంపుతుంది
  • క్లయింట్‌ని అప్‌గ్రేడ్ చేసిన తర్వాత నేను ఏమి చేయాలి?
  • ఎవరు гарантируетప్రక్రియ సమయంలో లేయర్ సంఖ్య గురించి సర్వర్ అభిప్రాయం మారదు?

ఇది పూర్తిగా సైద్ధాంతిక ఊహాగానాలు అని మీరు అనుకుంటున్నారా మరియు ఆచరణలో ఇది జరగదు, ఎందుకంటే సర్వర్ సరిగ్గా వ్రాయబడింది (కనీసం, ఇది బాగా పరీక్షించబడింది)? హా! అది ఎలా ఉన్నా!

సరిగ్గా ఇదే మేము ఆగస్టులో ఎదుర్కొన్నాము. ఆగస్టు 14న టెలిగ్రామ్ సర్వర్‌లలో ఏదో అప్‌డేట్ అవుతున్నట్లు మెసేజ్‌లు వచ్చాయి... ఆపై లాగ్‌లలో:

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

ఆపై అనేక మెగాబైట్ల స్టాక్ జాడలు (బాగా, అదే సమయంలో లాగింగ్ పరిష్కరించబడింది). అన్నింటికంటే, మీ TLలో ఏదైనా గుర్తించబడకపోతే, అది సంతకం ద్వారా బైనరీగా ఉంటుంది అన్ని వెళుతుంది, డీకోడింగ్ అసాధ్యం అవుతుంది. అటువంటి పరిస్థితిలో మీరు ఏమి చేయాలి?

సరే, డిస్‌కనెక్ట్ చేసి మళ్లీ ప్రయత్నించడం అనేది ఎవరికైనా ముందుగా గుర్తుకు వచ్చే విషయం. సహాయం చేయలేదు. మేము google CRC32 - ఇవి స్కీమ్ 73 నుండి వస్తువులుగా మారాయి, అయినప్పటికీ మేము 82లో పని చేసాము. మేము లాగ్‌లను జాగ్రత్తగా పరిశీలిస్తాము - రెండు వేర్వేరు స్కీమ్‌ల నుండి ఐడెంటిఫైయర్‌లు ఉన్నాయి!

బహుశా సమస్య పూర్తిగా మా అనధికారిక క్లయింట్‌లో ఉందా? లేదు, మేము టెలిగ్రామ్ డెస్క్‌టాప్ 1.2.17 (అనేక Linux పంపిణీలలో అందించబడిన సంస్కరణ)ని ప్రారంభిస్తాము, ఇది మినహాయింపు లాగ్‌కు వ్రాస్తుంది: MTP ఊహించని రకం id #b5223b0f MTPMessageMediaలో చదవబడింది…

టెలిగ్రామ్ ప్రోటోకాల్ మరియు సంస్థాగత విధానాలపై విమర్శలు. పార్ట్ 1, సాంకేతికత: మొదటి నుండి క్లయింట్‌ను వ్రాసే అనుభవం - TL, MT

అనధికారిక క్లయింట్‌లలో ఒకరికి ఇలాంటి సమస్య ఇప్పటికే సంభవించిందని గూగుల్ చూపించింది, అయితే సంస్కరణ సంఖ్యలు మరియు తదనుగుణంగా, అంచనాలు భిన్నంగా ఉన్నాయి...

కాబట్టి మనం ఏమి చేయాలి? వాసిలీ మరియు నేను విడిపోయాము: అతను సర్క్యూట్‌ను 91కి అప్‌డేట్ చేయడానికి ప్రయత్నించాడు, నేను కొన్ని రోజులు వేచి ఉండి 73లో ప్రయత్నించాలని నిర్ణయించుకున్నాను. రెండు పద్ధతులు పనిచేశాయి, కానీ అవి అనుభావికమైనవి కాబట్టి, మీకు ఎన్ని వెర్షన్లు పైకి లేదా క్రిందికి అవసరమో అర్థం కావడం లేదు. దూకడం లేదా మీరు ఎంతసేపు వేచి ఉండాలి .

తరువాత నేను పరిస్థితిని పునరుత్పత్తి చేయగలిగాను: మేము క్లయింట్‌ను ప్రారంభించాము, దాన్ని ఆపివేస్తాము, సర్క్యూట్‌ను మరొక లేయర్‌కు రీకంపైల్ చేస్తాము, పునఃప్రారంభించండి, సమస్యను మళ్లీ పట్టుకోండి, మునుపటిదానికి తిరిగి వెళ్లండి - అయ్యో, సర్క్యూట్ మారడం లేదు మరియు క్లయింట్ పునఃప్రారంభించబడుతుంది కొన్ని నిమిషాలు సహాయపడతాయి. మీరు వివిధ లేయర్‌ల నుండి డేటా స్ట్రక్చర్‌ల మిశ్రమాన్ని అందుకుంటారు.

వివరణ? మీరు వివిధ పరోక్ష లక్షణాల నుండి ఊహించగలిగినట్లుగా, సర్వర్ వివిధ యంత్రాలలో వివిధ రకాలైన అనేక ప్రక్రియలను కలిగి ఉంటుంది. చాలా మటుకు, "బఫరింగ్"కి బాధ్యత వహించే సర్వర్ దాని ఉన్నతాధికారులు ఇచ్చిన దానిని క్యూలో ఉంచింది మరియు వారు దానిని ఉత్పత్తి సమయంలో అమలులో ఉన్న పథకంలో ఇచ్చారు. మరియు ఈ క్యూ "కుళ్ళిన" వరకు, దాని గురించి ఏమీ చేయలేము.

బహుశా... అయితే ఇది భయంకరమైన ఊతకర్ర?!.. కాదు, పిచ్చి ఆలోచనల గురించి ఆలోచించే ముందు, అధికారిక ఖాతాదారుల కోడ్ చూద్దాం. ఆండ్రాయిడ్ వెర్షన్‌లో మేము ఏ TL పార్సర్‌ను కనుగొనలేదు, కానీ (డి)సీరియలైజేషన్‌తో కూడిన భారీ ఫైల్‌ను (GitHub టచ్ చేయడానికి నిరాకరించింది) కనుగొంటాము. కోడ్ స్నిప్పెట్‌లు ఇక్కడ ఉన్నాయి:

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

లేదా

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

హ్మ్... అడవిగా కనిపిస్తోంది. కానీ, బహుశా, ఇది రూపొందించబడిన కోడ్, అప్పుడు సరేనా?.. కానీ ఇది ఖచ్చితంగా అన్ని వెర్షన్‌లకు మద్దతు ఇస్తుంది! నిజమే, ప్రతిదీ ఎందుకు మిళితం చేయబడిందో, రహస్య చాట్‌లు మరియు అన్ని రకాలుగా ఎందుకు మిక్స్ అయ్యాయో స్పష్టంగా తెలియదు _old7 ఏదో ఒకవిధంగా మెషిన్ జనరేషన్ లాగా కనిపించడం లేదు... అయితే, అన్నింటికంటే నేను ఎగిరిపోయాను

TL_message_layer104
TL_message_layer104_2
TL_message_layer104_3

అబ్బాయిలు, ఒక పొర లోపల ఏమి ఉందో కూడా మీరు నిర్ణయించలేదా?! సరే, సరే, “రెండు” లోపంతో విడుదలయ్యాయని అనుకుందాం, అలాగే, అది జరుగుతుంది, కానీ మూడు?.. వెంటనే, మళ్లీ అదే రేక్? ఇది ఎలాంటి అశ్లీలత, క్షమించండి?..

టెలిగ్రామ్ డెస్క్‌టాప్ యొక్క సోర్స్ కోడ్‌లో, మార్గం ద్వారా, ఇదే విధమైన విషయం జరుగుతుంది - అలా అయితే, స్కీమ్‌కు వరుసగా అనేక కమిట్‌లు దాని లేయర్ నంబర్‌ను మార్చవు, కానీ ఏదైనా పరిష్కరించండి. స్కీమ్ కోసం అధికారిక డేటా మూలం లేని పరిస్థితుల్లో, అధికారిక క్లయింట్ యొక్క సోర్స్ కోడ్ మినహా దానిని ఎక్కడ నుండి పొందవచ్చు? మరియు మీరు దానిని అక్కడ నుండి తీసుకుంటే, మీరు అన్ని పద్ధతులను పరీక్షించే వరకు పథకం పూర్తిగా సరైనదని మీరు ఖచ్చితంగా చెప్పలేరు.

దీన్ని కూడా ఎలా పరీక్షించవచ్చు? యూనిట్, ఫంక్షనల్ మరియు ఇతర పరీక్షల అభిమానులు వ్యాఖ్యలలో భాగస్వామ్యం చేస్తారని నేను ఆశిస్తున్నాను.

సరే, మరొక కోడ్ ముక్కను చూద్దాం:

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;

ఈ వ్యాఖ్య "మాన్యువల్‌గా సృష్టించబడింది" ఈ ఫైల్‌లో కొంత భాగం మాత్రమే మాన్యువల్‌గా వ్రాయబడిందని సూచిస్తుంది (మొత్తం నిర్వహణ పీడకలని మీరు ఊహించగలరా?), మరియు మిగిలినది యంత్రం-ఉత్పత్తి చేయబడింది. అయితే, మరొక ప్రశ్న తలెత్తుతుంది - మూలాలు అందుబాటులో ఉన్నాయి పూర్తిగా కాదు (Linux కెర్నల్‌లో a la GPL బ్లాబ్స్), కానీ ఇది ఇప్పటికే రెండవ భాగానికి సంబంధించిన అంశం.

కానీ తగినంత. ఈ ధారావాహిక అంతా నడిచే ప్రోటోకాల్‌కు వెళ్దాం.

MTPప్రోటో

కాబట్టి, తెరవండి సాధారణ వివరణ и ప్రోటోకాల్ యొక్క వివరణాత్మక వివరణ మరియు మనం పొరపాట్లు చేసే మొదటి విషయం పరిభాష. మరియు ప్రతిదీ సమృద్ధిగా. సాధారణంగా, ఇది టెలిగ్రామ్ యొక్క యాజమాన్య లక్షణంగా కనిపిస్తుంది - వేర్వేరు ప్రదేశాలలో విషయాలను వేర్వేరుగా లేదా ఒక పదంతో విభిన్న విషయాలను లేదా దీనికి విరుద్ధంగా (ఉదాహరణకు, ఉన్నత స్థాయి APIలో, మీరు స్టిక్కర్ ప్యాక్‌ని చూసినట్లయితే, అది కాదు మీరు ఏమి అనుకున్నారు).

ఉదాహరణకు, "మెసేజ్" మరియు "సెషన్" అంటే ఇక్కడ సాధారణ టెలిగ్రామ్ క్లయింట్ ఇంటర్‌ఫేస్ కంటే భిన్నమైనది. సరే, సందేశంతో ప్రతిదీ స్పష్టంగా ఉంది, దీనిని OOP పరంగా అర్థం చేసుకోవచ్చు లేదా “ప్యాకెట్” అనే పదం అని పిలుస్తారు - ఇది తక్కువ, రవాణా స్థాయి, ఇంటర్‌ఫేస్‌లో ఉన్న సందేశాలు లేవు, చాలా సేవా సందేశాలు ఉన్నాయి . కానీ సెషన్ ... కానీ మొదటి విషయాలు మొదటి.

రవాణా పొర

మొదటి విషయం రవాణా. వారు మాకు 5 ఎంపికల గురించి చెబుతారు:

  • TCP
  • వెబ్‌సాకెట్
  • HTTPS ద్వారా వెబ్‌సాకెట్
  • HTTP
  • HTTPS

వాసిలీ, [15.06.18 15:04] UDP రవాణా కూడా ఉంది, కానీ అది డాక్యుమెంట్ చేయబడలేదు.

మరియు TCP మూడు వేరియంట్లలో

మొదటిది TCP కంటే UDPని పోలి ఉంటుంది, ప్రతి ప్యాకెట్‌లో సీక్వెన్స్ నంబర్ మరియు crc ఉంటాయి
బండిపై పత్రాలను చదవడం ఎందుకు చాలా బాధాకరమైనది?

సరే, అది ఇప్పుడు ఉంది TCP ఇప్పటికే 4 వేరియంట్‌లలో ఉంది:

  • అబ్రిడ్జ్డ్
  • ఇంటర్మీడియట్
  • ప్యాడెడ్ ఇంటర్మీడియట్
  • పూర్తి

బాగా, సరే, MTProxy కోసం ప్యాడెడ్ ఇంటర్మీడియట్, ఇది బాగా తెలిసిన ఈవెంట్‌ల కారణంగా తర్వాత జోడించబడింది. కానీ మీరు ఒకదానితో పొందగలిగేటప్పుడు మరో రెండు వెర్షన్లు (మొత్తం మూడు) ఎందుకు? ప్రధాన MTProto యొక్క పొడవు మరియు పేలోడ్‌ను ఎలా సెట్ చేయాలి అనే విషయంలో మాత్రమే నలుగురికీ తేడా ఉంటుంది, ఇది మరింత చర్చించబడుతుంది:

  • సంక్షిప్తంగా అది 1 లేదా 4 బైట్‌లు, కానీ 0xef కాదు, తర్వాత శరీరం
  • ఇంటర్మీడియట్‌లో ఇది 4 బైట్‌ల పొడవు మరియు ఫీల్డ్, మరియు క్లయింట్ తప్పనిసరిగా పంపాల్సిన మొదటిసారి 0xeeeeeeee ఇది ఇంటర్మీడియట్ అని సూచించడానికి
  • నెట్‌వర్కర్ దృష్టికోణంలో పూర్తిగా అత్యంత వ్యసనపరుడైనది: పొడవు, క్రమం సంఖ్య మరియు ప్రధానంగా MTProto, బాడీ, CRC32 కాదు. అవును, ఇదంతా TCP పైన ఉంది. ఇది సీక్వెన్షియల్ బైట్ స్ట్రీమ్ రూపంలో మాకు విశ్వసనీయ రవాణాను అందిస్తుంది, ముఖ్యంగా చెక్‌సమ్‌లు అవసరం లేదు. సరే, ఇప్పుడు TCPకి 16-బిట్ చెక్‌సమ్ ఉందని ఎవరైనా నన్ను వ్యతిరేకిస్తారు, కాబట్టి డేటా అవినీతి జరుగుతుంది. చాలా బాగుంది, కానీ వాస్తవానికి మేము 16 బైట్‌ల కంటే ఎక్కువ పొడవు గల హాష్‌లతో కూడిన క్రిప్టోగ్రాఫిక్ ప్రోటోకాల్‌ని కలిగి ఉన్నాము, ఈ ఎర్రర్‌లు - ఇంకా ఎక్కువ - SHA అసమతుల్యత ద్వారా అధిక స్థాయిలో క్యాచ్ చేయబడతాయి. దీని పైన CRC32లో ఎటువంటి పాయింట్ లేదు.

సంక్షిప్తీకరణను సరిపోల్చండి, దీనిలో ఒక బైట్ పొడవు సాధ్యమవుతుంది, ఇది ఇంటర్మీడియట్‌తో సరిపోల్చండి, ఇది "4-బైట్ డేటా అమరిక అవసరమైతే" అని సమర్థిస్తుంది, ఇది చాలా అర్ధంలేనిది. టెలిగ్రామ్ ప్రోగ్రామర్లు చాలా అసమర్థులని నమ్ముతారు, వారు సాకెట్ నుండి సమలేఖనం చేయబడిన బఫర్‌లోకి డేటాను చదవలేరు? మీరు దీన్ని ఇంకా చేయాల్సి ఉంటుంది, ఎందుకంటే చదవడం వల్ల మీకు ఎన్ని బైట్‌లైనా తిరిగి ఇవ్వవచ్చు (మరియు ప్రాక్సీ సర్వర్లు కూడా ఉన్నాయి, ఉదాహరణకు...). లేదా మరోవైపు, మనకు ఇంకా 16 బైట్‌ల పైన ఎక్కువ ప్యాడింగ్ ఉంటే సంక్షిప్తీకరణను ఎందుకు బ్లాక్ చేయండి - 3 బైట్‌లను సేవ్ చేయండి కొన్నిసార్లు ?

నెట్‌వర్క్ ప్రోటోకాల్‌లతో సహా, నిజమైన ఆచరణాత్మక అవసరం లేకుండా చక్రాలను తిరిగి ఆవిష్కరించడానికి నికోలాయ్ డ్యూరోవ్ నిజంగా ఇష్టపడుతున్నారనే అభిప్రాయాన్ని ఒకరు పొందుతారు.

ఇతర రవాణా ఎంపికలు, సహా. వెబ్ మరియు MTProxy, మేము ఇప్పుడు పరిగణించము, బహుశా మరొక పోస్ట్‌లో, అభ్యర్థన ఉంటే. ఇదే MTProxy గురించి, 2018లో విడుదలైన కొద్దిసేపటికే, ప్రొవైడర్లు దీన్ని బ్లాక్ చేయడం త్వరగా నేర్చుకున్నారని ఇప్పుడు గుర్తుంచుకోండి. బైపాస్ నిరోధించడంప్యాకేజీ సైజు! మరియు సిలో వ్రాసిన (మళ్ళీ వాల్ట్‌మాన్ చేత) MTProxy సర్వర్ Linux ప్రత్యేకతలతో అతిగా ముడిపడి ఉంది, అయితే ఇది అస్సలు అవసరం లేదు (ఫిల్ కులిన్ నిర్ధారిస్తుంది), మరియు Go లేదా Node.jsలో ఇదే విధమైన సర్వర్ ఉంటుంది. వంద కంటే తక్కువ లైన్లలో సరిపోతుంది.

కానీ మేము ఇతర సమస్యలను పరిగణనలోకి తీసుకున్న తర్వాత, విభాగం చివరిలో ఈ వ్యక్తుల సాంకేతిక అక్షరాస్యత గురించి తీర్మానాలు చేస్తాము. ప్రస్తుతానికి, OSI లేయర్ 5, సెషన్‌కి వెళ్దాం - దానిపై వారు MTProto సెషన్‌ను ఉంచారు.

కీలు, సందేశాలు, సెషన్‌లు, డిఫీ-హెల్మాన్

వారు దానిని పూర్తిగా సరిగ్గా ఉంచలేదు... సెషన్ అనేది యాక్టివ్ సెషన్‌ల క్రింద ఇంటర్‌ఫేస్‌లో కనిపించే అదే సెషన్ కాదు. కానీ క్రమంలో.

టెలిగ్రామ్ ప్రోటోకాల్ మరియు సంస్థాగత విధానాలపై విమర్శలు. పార్ట్ 1, సాంకేతికత: మొదటి నుండి క్లయింట్‌ను వ్రాసే అనుభవం - TL, MT

కాబట్టి మేము రవాణా పొర నుండి తెలిసిన పొడవు యొక్క బైట్ స్ట్రింగ్‌ను అందుకున్నాము. ఇది ఎన్‌క్రిప్టెడ్ మెసేజ్ లేదా సాదా వచనం - మనం ఇప్పటికీ కీలక ఒప్పంద దశలోనే ఉండి, నిజంగానే చేస్తున్నట్లయితే. మనం "కీ" అని పిలవబడే భావనల సమూహంలో ఏది గురించి మాట్లాడుతున్నాము? టెలిగ్రామ్ బృందం కోసం ఈ సమస్యను స్పష్టం చేద్దాం (ఉదయం 4 గంటలకు అలసిపోయిన మెదడుతో ఇంగ్లీష్ నుండి నా స్వంత డాక్యుమెంటేషన్‌ను అనువదించినందుకు నేను క్షమాపణలు కోరుతున్నాను, కొన్ని పదబంధాలను అలాగే ఉంచడం సులభం):

అనే రెండు సంస్థలు ఉన్నాయి సెషన్ - "ప్రస్తుత సెషన్‌లు" కింద అధికారిక క్లయింట్‌ల UIలో ఒకటి, ప్రతి సెషన్ మొత్తం పరికరం / OSకి అనుగుణంగా ఉంటుంది.
రెండవ - MTPప్రోటో సెషన్, దీనిలో సందేశం యొక్క క్రమ సంఖ్య (తక్కువ-స్థాయి అర్థంలో) ఉంది మరియు ఏది వివిధ TCP కనెక్షన్‌ల మధ్య ఉండవచ్చు. అనేక MTProto సెషన్‌లను ఒకే సమయంలో ఇన్‌స్టాల్ చేయవచ్చు, ఉదాహరణకు, ఫైల్ డౌన్‌లోడ్‌ను వేగవంతం చేయడానికి.

ఈ రెండింటి మధ్య సెషన్స్ ఒక భావన ఉంది అధికార. క్షీణించిన సందర్భంలో, మనం చెప్పగలం UI సెషన్ దాని లాంటిదేనా అధికార, కానీ అయ్యో, ప్రతిదీ సంక్లిష్టంగా ఉంది. చూద్దాం:

  • కొత్త పరికరంలో వినియోగదారు ముందుగా ఉత్పత్తి చేస్తారు auth_key మరియు ఖాతాకు కట్టుబడి ఉంటుంది, ఉదాహరణకు SMS ద్వారా - అందుకే అధికార
  • ఇది మొదటి లోపల జరిగింది MTPప్రోటో సెషన్, కలిగి ఉంది session_id మీ లోపల.
  • ఈ దశలో, కలయిక అధికార и session_id అని పిలవవచ్చు ఉదాహరణకు - ఈ పదం కొంతమంది క్లయింట్‌ల డాక్యుమెంటేషన్ మరియు కోడ్‌లో కనిపిస్తుంది
  • అప్పుడు, క్లయింట్ తెరవవచ్చు అనేక MTPప్రోటో సెషన్‌లు అదే కింద auth_key - అదే DCకి.
  • అప్పుడు, ఒక రోజు క్లయింట్ ఫైల్‌ను అభ్యర్థించవలసి ఉంటుంది మరొక DC - మరియు ఈ DC కోసం కొత్తది రూపొందించబడుతుంది auth_key !
  • రిజిస్టర్ చేస్తున్న కొత్త వినియోగదారు కాదని, అదే విధంగా సిస్టమ్‌కు తెలియజేయడానికి అధికార (UI సెషన్), క్లయింట్ API కాల్‌లను ఉపయోగిస్తుంది auth.exportAuthorization ఇంటి DC లో auth.importAuthorization కొత్త DC లో.
  • ప్రతిదీ ఒకేలా ఉంటుంది, అనేకం తెరవబడి ఉండవచ్చు MTPప్రోటో సెషన్‌లు (ప్రతి దాని స్వంతదానితో session_id) ఈ కొత్త DCకి, కింద తన auth_key.
  • చివరగా, క్లయింట్ పర్ఫెక్ట్ ఫార్వర్డ్ సీక్రెసీని కోరుకోవచ్చు. ప్రతి auth_key ఇది శాశ్వత కీ - ప్రతి DC - మరియు క్లయింట్ కాల్ చేయవచ్చు auth.bindTempAuthKey వాడేందుకు తాత్కాలిక auth_key - మరియు మళ్ళీ, ఒకటి మాత్రమే temp_auth_key ప్రతి DCకి, అందరికీ సాధారణం MTPప్రోటో సెషన్‌లు ఈ DCకి.

గమనించండి, అది ఉ ప్పు (మరియు భవిష్యత్ లవణాలు) కూడా ఒకటి auth_key ఆ. అందరి మధ్య పంచుకున్నారు MTPప్రోటో సెషన్‌లు అదే DCకి.

"వివిధ TCP కనెక్షన్‌ల మధ్య" అంటే ఏమిటి? కాబట్టి దీని అర్థం అలాంటిదే వెబ్‌సైట్‌లో ఆథరైజేషన్ కుక్కీ - ఇది ఇచ్చిన సర్వర్‌కు అనేక TCP కనెక్షన్‌లను కొనసాగిస్తుంది (సజీవంగా ఉంటుంది), కానీ ఒక రోజు అది చెడిపోతుంది. HTTP వలె కాకుండా, ఒక సెషన్‌లోని MTProto సందేశాలు వరుసగా లెక్కించబడతాయి మరియు అవి సొరంగంలోకి ప్రవేశించినట్లయితే, కనెక్షన్ విచ్ఛిన్నమైంది - కొత్త కనెక్షన్‌ని స్థాపించిన తర్వాత, సర్వర్ ఈ సెషన్‌లో మునుపటిలో అందించని ప్రతిదాన్ని పంపుతుంది; TCP కనెక్షన్.

అయితే, పై సమాచారం చాలా నెలల విచారణ తర్వాత సంగ్రహించబడింది. ఈలోగా, మేము మా క్లయింట్‌ను మొదటి నుండి అమలు చేస్తున్నామా? - ప్రారంభానికి తిరిగి వెళ్దాం.

కాబట్టి ఉత్పత్తి చేద్దాం auth_key పై టెలిగ్రామ్ నుండి Diffie-Hellman వెర్షన్లు. డాక్యుమెంటేషన్‌ను అర్థం చేసుకోవడానికి ప్రయత్నిద్దాం...

Vasily, [19.06.18 20:05] data_with_hash := SHA1(డేటా) + డేటా + (ఏదైనా యాదృచ్ఛిక బైట్‌లు); అంటే పొడవు 255 బైట్‌లకు సమానం;
encrypted_data := RSA(data_with_hash, server_public_key); 255-బైట్ పొడవైన సంఖ్య (బిగ్ ఎండియన్) అవసరమైన మాడ్యులస్‌పై అవసరమైన శక్తికి పెంచబడుతుంది మరియు ఫలితం 256-బైట్ సంఖ్యగా నిల్వ చేయబడుతుంది.

వారికి కొంత డోప్ DH ఉంది

ఆరోగ్యకరమైన వ్యక్తి యొక్క DH లాగా కనిపించడం లేదు
dxలో రెండు పబ్లిక్ కీలు లేవు

సరే, చివరికి ఇది క్రమబద్ధీకరించబడింది, కానీ అవశేషాలు మిగిలి ఉన్నాయి - క్లయింట్ అతను సంఖ్యను కారకం చేయగలడని పని రుజువు చేయబడుతుంది. DoS దాడులకు వ్యతిరేకంగా రక్షణ రకం. మరియు RSA కీ ఒక దిశలో ఒకసారి మాత్రమే ఉపయోగించబడుతుంది, ముఖ్యంగా ఎన్క్రిప్షన్ కోసం new_nonce. అయితే ఈ సాధారణ ఆపరేషన్ విజయవంతం అయితే, మీరు ఏమి ఎదుర్కోవలసి ఉంటుంది?

వాసిలీ, [20.06.18/00/26 XNUMX:XNUMX] నేను ఇంకా appid అభ్యర్థనను పొందలేదు

నేను ఈ అభ్యర్థనను DHకి పంపాను

మరియు, ట్రాన్స్‌పోర్ట్ డాక్‌లో అది ఎర్రర్ కోడ్ యొక్క 4 బైట్‌లతో ప్రతిస్పందించగలదని చెప్పింది. అంతే

సరే, అతను నాకు -404 చెప్పాడు, కాబట్టి ఏమిటి?

కాబట్టి నేను అతనితో ఇలా చెప్పాను: “ఇలాంటి వేలిముద్రతో సర్వర్ కీతో ఎన్‌క్రిప్ట్ చేయబడిన మీ బుల్‌షిట్‌ని పట్టుకోండి, నాకు DH కావాలి,” మరియు అది తెలివితక్కువ 404తో ప్రతిస్పందించింది.

ఈ సర్వర్ ప్రతిస్పందన గురించి మీరు ఏమనుకుంటున్నారు? ఏం చేయాలి? అడగడానికి ఎవరూ లేరు (కానీ రెండవ భాగంలో దాని గురించి మరింత).

ఇక్కడ వడ్డీ అంతా డాక్‌పైనే జరుగుతుంది

నాకు వేరే పని లేదు, నేను అంకెలను ముందుకు వెనుకకు మార్చాలని కలలు కన్నాను

రెండు 32 బిట్ సంఖ్యలు. నేను అందరిలాగే వాటిని ప్యాక్ చేసాను

కానీ లేదు, ఈ రెండింటిని ముందుగా లైన్‌లో BE గా జోడించాలి

వాడిమ్ గోంచరోవ్, [20.06.18 15:49] మరియు ఈ 404 కారణంగా?

వాసిలీ, [20.06.18 15:49] అవును!

వాడిమ్ గోంచరోవ్, [20.06.18 15:50] కాబట్టి అతను "కనుగొనలేదు" అని నాకు అర్థం కాలేదు

వాసిలీ, [20.06.18 15:50] గురించి

అటువంటి కుళ్ళిపోవడాన్ని నేను ప్రధాన కారకాలుగా కనుగొనలేకపోయాను%)

మేము ఎర్రర్ రిపోర్టింగ్‌ను కూడా నిర్వహించలేదు

వాసిలీ, [20.06.18 20:18] ఓహ్, MD5 కూడా ఉంది. ఇప్పటికే మూడు విభిన్న మ హేష్

కీ వేలిముద్ర క్రింది విధంగా లెక్కించబడుతుంది:

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

SHA1 మరియు sha2

అందుకే పెట్టుకుందాం auth_key మేము Diffie-Hellman ఉపయోగించి పరిమాణంలో 2048 బిట్‌లను అందుకున్నాము. తరవాత ఏంటి? ఈ కీ యొక్క దిగువ 1024 బిట్‌లు ఏ విధంగానూ ఉపయోగించబడలేదని మేము కనుగొన్నాము... అయితే ప్రస్తుతానికి దీని గురించి ఆలోచిద్దాం. ఈ దశలో, మేము సర్వర్‌తో భాగస్వామ్య రహస్యాన్ని కలిగి ఉన్నాము. TLS సెషన్ యొక్క అనలాగ్ స్థాపించబడింది, ఇది చాలా ఖరీదైన విధానం. కానీ మనం ఎవరో సర్వర్‌కి ఇంకా ఏమీ తెలియదు! ఇంకా కాదు, నిజానికి. అధికారం. ఆ. మీరు "లాగిన్-పాస్‌వర్డ్" పరంగా ఆలోచించినట్లయితే, మీరు ఒకప్పుడు ICQలో చేసినట్లు లేదా కనీసం "లాగిన్-కీ", SSHలో వలె (ఉదాహరణకు, కొన్ని gitlab/githubలో). మేము ఒక అనామకుడిని పొందాము. "ఈ ఫోన్ నంబర్‌లు మరొక DC ద్వారా సేవలు అందించబడ్డాయి" అని సర్వర్ మాకు చెబితే ఏమి చేయాలి? లేదా "మీ ఫోన్ నంబర్ నిషేధించబడింది"? మనం చేయగలిగినది ఏమిటంటే, కీ అది ఉపయోగకరంగా ఉంటుందని మరియు అప్పటికి కుళ్ళిపోకుండా ఉండాలనే ఆశతో ఉంచడం.

మార్గం ద్వారా, మేము దానిని రిజర్వేషన్లతో "అందించాము". ఉదాహరణకు, మేము సర్వర్‌ను విశ్వసిస్తామా? అది నకిలీ అయితే? క్రిప్టోగ్రాఫిక్ తనిఖీలు అవసరం:

వాసిలీ, [21.06.18 17:53] వారు మొబైల్ క్లయింట్‌లకు 2kbit నంబర్‌ని ప్రైమాలిటీ% కోసం తనిఖీ చేయడానికి అందిస్తారు)

కానీ అది స్పష్టంగా లేదు, నఫీజోవా

వాసిలీ, [21.06.18 18:02] పత్రం సాధారణమైనది కాదని తేలితే ఏమి చేయాలో చెప్పలేదు

చెప్పలేదు. ఈ సందర్భంలో అధికారిక Android క్లయింట్ ఏమి చేస్తుందో చూద్దాం? ఎ అందు కోసమే (మరియు అవును, మొత్తం ఫైల్ ఆసక్తికరంగా ఉంది) - వారు చెప్పినట్లు, నేను దీన్ని ఇక్కడ వదిలివేస్తాను:

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

లేదు, అది ఇప్పటికీ ఉంది కొన్ని సంఖ్య యొక్క ఆధిక్యత కోసం పరీక్షలు ఉన్నాయి, కానీ వ్యక్తిగతంగా నాకు గణితంలో తగినంత జ్ఞానం లేదు.

సరే, మాకు మాస్టర్ కీ వచ్చింది. లాగిన్ చేయడానికి, అనగా. అభ్యర్థనలను పంపండి, మీరు AESని ఉపయోగించి తదుపరి గుప్తీకరణను నిర్వహించాలి.

మెసేజ్ కీ అనేది మెసేజ్ బాడీ యొక్క SHA128 యొక్క 256 మిడిల్ బిట్‌లుగా నిర్వచించబడింది (సెషన్, మెసేజ్ ID మొదలైన వాటితో సహా), పాడింగ్ బైట్‌లతో సహా, అధీకృత కీ నుండి తీసుకోబడిన 32 బైట్‌ల ద్వారా ముందుగా ఉంటుంది.

వాసిలీ, [22.06.18 14:08] సగటు, బిచ్, బిట్స్

అందుకుంది auth_key. అన్నీ. వాటిని మించి... అది పత్రం నుండి స్పష్టంగా లేదు. ఓపెన్ సోర్స్ కోడ్‌ని అధ్యయనం చేయడానికి సంకోచించకండి.

MTProto 2.0కి 12 నుండి 1024 బైట్ల ప్యాడింగ్ అవసరమని గమనించండి, ఫలితంగా సందేశం పొడవు 16 బైట్‌లతో భాగించబడాలనే షరతుకు లోబడి ఉంటుంది.

కాబట్టి మీరు ఎంత పాడింగ్ జోడించాలి?

మరియు అవును, లోపం విషయంలో 404 కూడా ఉంది

ఎవరైనా డాక్యుమెంటేషన్ యొక్క రేఖాచిత్రం మరియు వచనాన్ని జాగ్రత్తగా అధ్యయనం చేస్తే, అక్కడ MAC లేదని వారు గమనించారు. మరియు AES ఒక నిర్దిష్ట IGE మోడ్‌లో ఉపయోగించబడుతుంది, అది మరెక్కడా ఉపయోగించబడదు. వారు, వాస్తవానికి, వారి FAQలో దీని గురించి వ్రాస్తారు... ఇక్కడ, మెసేజ్ కీ కూడా డీక్రిప్టెడ్ డేటా యొక్క SHA హాష్, సమగ్రతను తనిఖీ చేయడానికి ఉపయోగించబడుతుంది - మరియు సరిపోలని పక్షంలో, కొన్ని కారణాల వల్ల డాక్యుమెంటేషన్ నిశ్శబ్దంగా వాటిని విస్మరించమని సిఫార్సు చేస్తుంది (కానీ భద్రత గురించి ఏమిటి, వారు మమ్మల్ని విచ్ఛిన్నం చేస్తే?).

నేను క్రిప్టోగ్రాఫర్‌ని కాదు, సైద్ధాంతిక దృక్కోణం నుండి ఈ సందర్భంలో ఈ మోడ్‌లో తప్పు ఏమీ లేదు. కానీ నేను టెలిగ్రామ్ డెస్క్‌టాప్‌ను ఉదాహరణగా ఉపయోగించి ఒక ఆచరణాత్మక సమస్యను స్పష్టంగా చెప్పగలను. ఇది స్థానిక కాష్‌ని (ఈ D877F783D5D3EF8C) MTProtoలోని సందేశాల మాదిరిగానే గుప్తీకరిస్తుంది (ఈ సందర్భంలో వెర్షన్ 1.0లో మాత్రమే), అనగా. మొదట మెసేజ్ కీ, ఆ తర్వాత డేటా (మరియు ఎక్కడో ప్రధానమైన పెద్దది auth_key 256 బైట్లు, ఇది లేకుండా msg_key పనికిరానిది). కాబట్టి, సమస్య పెద్ద ఫైళ్ళలో గుర్తించదగినదిగా మారుతుంది. అవి, మీరు డేటా యొక్క రెండు కాపీలను ఉంచాలి - ఎన్క్రిప్టెడ్ మరియు డీక్రిప్టెడ్. మరియు మెగాబైట్‌లు లేదా స్ట్రీమింగ్ వీడియో ఉంటే, ఉదాహరణకు?.. సాంకేతికలిపి తర్వాత MACతో క్లాసిక్ స్కీమ్‌లు దానిని స్ట్రీమ్‌ని చదవడానికి మిమ్మల్ని అనుమతిస్తాయి, వెంటనే దానిని ప్రసారం చేస్తాయి. కానీ MTProto తో మీరు చేయాల్సి ఉంటుంది మొదట మొత్తం సందేశాన్ని ఎన్‌క్రిప్ట్ చేయండి లేదా డీక్రిప్ట్ చేయండి, ఆ తర్వాత మాత్రమే దానిని నెట్‌వర్క్‌కి లేదా డిస్క్‌కి బదిలీ చేయండి. అందువల్ల, కాష్‌లోని టెలిగ్రామ్ డెస్క్‌టాప్ యొక్క తాజా వెర్షన్‌లలో user_data మరొక ఫార్మాట్ కూడా ఉపయోగించబడుతుంది - CTR మోడ్‌లో AES తో.

వాసిలీ, [21.06.18 01:27] ఓహ్, IGE అంటే ఏమిటో నేను కనుగొన్నాను: IGE అనేది కెర్బెరోస్ కోసం "ప్రామాణీకరించే ఎన్‌క్రిప్షన్ మోడ్"లో మొదటి ప్రయత్నం. ఇది విఫల ప్రయత్నం (ఇది సమగ్రత రక్షణను అందించదు), మరియు తీసివేయవలసి వచ్చింది. అది పని చేసే ప్రామాణీకరించే ఎన్‌క్రిప్షన్ మోడ్ కోసం 20 సంవత్సరాల అన్వేషణకు నాంది, ఇది ఇటీవల OCB మరియు GCM వంటి మోడ్‌లలో ముగిసింది.

మరియు ఇప్పుడు కార్ట్ వైపు నుండి వాదనలు:

నికోలాయ్ దురోవ్ నేతృత్వంలోని టెలిగ్రామ్ వెనుక ఉన్న జట్టులో ఆరుగురు ACM ఛాంపియన్‌లు ఉన్నారు, వారిలో సగం మంది గణితంలో Ph.Dలు ఉన్నారు. MTProto యొక్క ప్రస్తుత వెర్షన్‌ను రూపొందించడానికి వారికి దాదాపు రెండు సంవత్సరాలు పట్టింది.

నవ్వు తెప్పించే విషయం. దిగువ స్థాయిలో రెండేళ్లు

లేదా మీరు కేవలం tls తీసుకోవచ్చు

సరే, మేము ఎన్‌క్రిప్షన్ మరియు ఇతర సూక్ష్మ నైపుణ్యాలను పూర్తి చేసామని చెప్పండి. చివరకు TLలో సీరియల్‌గా అభ్యర్థనలను పంపడం మరియు ప్రతిస్పందనలను డీరియలైజ్ చేయడం సాధ్యమేనా? కాబట్టి మీరు ఏమి మరియు ఎలా పంపాలి? ఇక్కడ, ఉదాహరణకు, పద్ధతి initకనెక్షన్, బహుశా ఇదేనా?

Vasily, [25.06.18 18:46] కనెక్షన్‌ని ప్రారంభిస్తుంది మరియు వినియోగదారు పరికరం మరియు అప్లికేషన్‌లో సమాచారాన్ని సేవ్ చేస్తుంది.

ఇది app_id, device_model, system_version, app_version మరియు lang_codeని అంగీకరిస్తుంది.

మరియు కొంత ప్రశ్న

ఎప్పటిలాగే డాక్యుమెంటేషన్. ఓపెన్ సోర్స్‌ని అధ్యయనం చేయడానికి సంకోచించకండి

invokeWithLayerతో ప్రతిదీ దాదాపుగా స్పష్టంగా ఉంటే, ఇక్కడ తప్పు ఏమిటి? ఇది తేలింది, మన దగ్గర ఉందని అనుకుందాం - క్లయింట్ ఇప్పటికే సర్వర్‌ని అడగడానికి ఏదైనా కలిగి ఉంది - మేము పంపాలనుకుంటున్న అభ్యర్థన ఉంది:

వాసిలీ, [25.06.18 19:13] కోడ్‌ను బట్టి చూస్తే, మొదటి కాల్ ఈ చెత్తలో చుట్టబడి ఉంటుంది మరియు చెత్త కూడా ఇన్‌వోక్‌విత్‌లేయర్‌లో చుట్టబడి ఉంటుంది.

initConnection ఒక ప్రత్యేక కాల్ ఎందుకు కాలేకపోయింది, కానీ తప్పనిసరిగా రేపర్ అయి ఉండాలి? అవును, అది ముగిసినట్లుగా, ఇది ప్రతి సెషన్ ప్రారంభంలో ప్రతిసారీ చేయాలి మరియు ప్రధాన కీతో ఒకసారి కాదు. కానీ! ఇది అనధికార వినియోగదారు ద్వారా కాల్ చేయబడదు! ఇప్పుడు అది వర్తించే దశకు చేరుకున్నాము ఇది డాక్యుమెంటేషన్ పేజీ - మరియు అది మాకు చెబుతుంది...

API పద్ధతులలో కొద్ది భాగం మాత్రమే అనధికార వినియోగదారులకు అందుబాటులో ఉన్నాయి:

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

వాటిలో మొదటిది, auth.sendCode, మరియు మేము api_id మరియు api_hashని పంపే ప్రతిష్టాత్మకమైన మొదటి అభ్యర్థన ఉంది మరియు దాని తర్వాత మేము కోడ్‌తో SMSని అందుకుంటాము. మరియు మనం తప్పు DCలో ఉంటే (ఈ దేశంలోని టెలిఫోన్ నంబర్‌లు మరొకరి ద్వారా అందించబడతాయి, ఉదాహరణకు), అప్పుడు మేము కోరుకున్న DC నంబర్‌తో ఎర్రర్‌ను అందుకుంటాము. మీరు DC నంబర్ ద్వారా ఏ IP చిరునామాకు కనెక్ట్ కావాలో తెలుసుకోవడానికి, మాకు సహాయం చేయండి help.getConfig. ఒక సమయంలో కేవలం 5 ఎంట్రీలు మాత్రమే ఉన్నాయి, కానీ 2018 యొక్క ప్రసిద్ధ సంఘటనల తర్వాత, సంఖ్య గణనీయంగా పెరిగింది.

ఇప్పుడు మనం అనామకంగా సర్వర్‌లో ఈ దశకు చేరుకున్నామని గుర్తుంచుకోండి. IP చిరునామాను పొందడం చాలా ఖరీదైనది కాదా? MTProto యొక్క ఎన్‌క్రిప్ట్ చేయని భాగంలో దీన్ని మరియు ఇతర కార్యకలాపాలను ఎందుకు చేయకూడదు? నేను అభ్యంతరం విన్నాను: "తప్పుడు చిరునామాలతో ప్రతిస్పందించేది RKN కాదని మనం ఎలా నిర్ధారించుకోవాలి?" దీనికి మేము సాధారణంగా, అధికారిక క్లయింట్లు గుర్తుంచుకోవాలి RSA కీలు పొందుపరచబడ్డాయి, అనగా మీరు చేయగలరు చందా చేయండి ఈ సమాచారము. వాస్తవానికి, క్లయింట్‌లు ఇతర ఛానెల్‌ల ద్వారా స్వీకరించే నిరోధించడాన్ని దాటవేయడం గురించిన సమాచారం కోసం ఇది ఇప్పటికే చేయబడుతుంది (తార్కికంగా, MTProtoలోనే ఇది చేయలేము; మీరు ఎక్కడ కనెక్ట్ చేయాలో కూడా తెలుసుకోవాలి).

అలాగే. క్లయింట్ అధికారం యొక్క ఈ దశలో, మేము ఇంకా అధికారం పొందలేదు మరియు మా దరఖాస్తును నమోదు చేసుకోలేదు. అనధికార వినియోగదారుకు అందుబాటులో ఉన్న పద్ధతులకు సర్వర్ ఏమి స్పందిస్తుందో మేము ఇప్పుడు చూడాలనుకుంటున్నాము. మరియు ఇక్కడ…

వాసిలీ, [10.07.18 14:45] https://core.telegram.org/method/help.getConfig

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

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

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

పథకంలో, మొదటిది రెండవది

tdesktop స్కీమాలో మూడవ విలువ

అవును, అప్పటి నుండి, వాస్తవానికి, డాక్యుమెంటేషన్ నవీకరించబడింది. ఇది త్వరలో మళ్లీ అసంబద్ధం కావచ్చు. అనుభవం లేని డెవలపర్ ఎలా తెలుసుకోవాలి? బహుశా మీరు మీ దరఖాస్తును నమోదు చేస్తే, వారు మీకు తెలియజేస్తారా? వాసిలీ ఇలా చేసాడు, కానీ అయ్యో, వారు అతనికి ఏమీ పంపలేదు (మళ్ళీ, మేము దీని గురించి రెండవ భాగంలో మాట్లాడుతాము).

...మేము ఇప్పటికే ఏదో విధంగా APIకి తరలించామని మీరు గమనించారు, అనగా. తదుపరి స్థాయికి, మరియు MTProto అంశంలో ఏదైనా మిస్ అయ్యారా? ఆశ్చర్యం లేదు:

వాసిలీ, [28.06.18 02:04] Mm, వారు e2eలోని కొన్ని అల్గారిథమ్‌ల ద్వారా చమత్కరిస్తున్నారు

Mtproto రెండు డొమైన్‌ల కోసం ఎన్‌క్రిప్షన్ అల్గారిథమ్‌లు మరియు కీలను నిర్వచిస్తుంది, అలాగే కొంచెం రేపర్ స్ట్రక్చర్‌ను నిర్వచిస్తుంది

కానీ అవి స్టాక్‌లోని వివిధ స్థాయిలను నిరంతరం మిళితం చేస్తాయి, కాబట్టి mtproto ఎక్కడ ముగిసింది మరియు తదుపరి స్థాయి ప్రారంభమవుతుందనేది ఎల్లప్పుడూ స్పష్టంగా ఉండదు.

అవి ఎలా కలపాలి? సరే, ఇక్కడ PFS కోసం అదే తాత్కాలిక కీ ఉంది, ఉదాహరణకు (మార్గం ద్వారా, టెలిగ్రామ్ డెస్క్‌టాప్ దీన్ని చేయలేము). ఇది API అభ్యర్థన ద్వారా అమలు చేయబడుతుంది auth.bindTempAuthKey, అనగా ఉన్నత స్థాయి నుండి. కానీ అదే సమయంలో ఇది దిగువ స్థాయిలో ఎన్క్రిప్షన్‌తో జోక్యం చేసుకుంటుంది - దాని తర్వాత, ఉదాహరణకు, మీరు దీన్ని మళ్లీ చేయాలి initConnection మొదలైనవి, ఇది కాదు కేవలం సాధారణ అభ్యర్థన. ఫీల్డ్‌లో ఉన్నప్పటికీ, మీరు ఒక్కో DCకి ఒక తాత్కాలిక కీని మాత్రమే కలిగి ఉండటం కూడా ప్రత్యేకత auth_key_id ప్రతి సందేశంలో కనీసం ప్రతి సందేశమైనా కీని మార్చడానికి మిమ్మల్ని అనుమతిస్తుంది మరియు తాత్కాలిక కీని ఎప్పుడైనా "మర్చిపోవడానికి" సర్వర్‌కు హక్కు ఉంది - ఈ సందర్భంలో ఏమి చేయాలో డాక్యుమెంటేషన్ చెప్పలేదు ... సరే, ఎందుకు కాలేదు భవిష్యత్ లవణాల సమితి వలె మీకు అనేక కీలు లేవు మరియు?..

MTProto థీమ్ గురించి గమనించదగ్గ కొన్ని ఇతర విషయాలు ఉన్నాయి.

సందేశ సందేశాలు, msg_id, msg_seqno, నిర్ధారణలు, తప్పు దిశలో పింగ్‌లు మరియు ఇతర ప్రత్యేకతలు

మీరు వాటి గురించి ఎందుకు తెలుసుకోవాలి? ఎందుకంటే అవి అధిక స్థాయికి "లీక్" అవుతాయి మరియు APIతో పని చేస్తున్నప్పుడు మీరు వాటి గురించి తెలుసుకోవాలి. msg_keyపై మాకు ఆసక్తి లేదని అనుకుందాం, దిగువ స్థాయి మన కోసం ప్రతిదీ డీక్రిప్ట్ చేసింది. కానీ డీక్రిప్ట్ చేయబడిన డేటా లోపల మనకు ఈ క్రింది ఫీల్డ్‌లు ఉన్నాయి (డేటా యొక్క పొడవు కూడా, కాబట్టి పాడింగ్ ఎక్కడ ఉందో మాకు తెలుసు, కానీ అది ముఖ్యం కాదు):

  • ఉప్పు - int64
  • session_id - int64
  • message_id — int64
  • seq_no - int32

మొత్తం DCకి ఒక ఉప్పు మాత్రమే ఉందని మీకు గుర్తు చేద్దాం. ఆమె గురించి ఎందుకు తెలుసు? అభ్యర్థన ఉన్నందున మాత్రమే కాదు get_future_salts, ఏ విరామాలు చెల్లుబాటు అవుతాయని ఇది మీకు చెబుతుంది, కానీ మీ ఉప్పు "కుళ్ళిపోయినట్లయితే", సందేశం (అభ్యర్థన) కేవలం పోతుంది. సర్వర్, కొత్త ఉప్పును జారీ చేయడం ద్వారా నివేదిస్తుంది new_session_created - కానీ పాతదానితో మీరు దానిని ఏదో ఒకవిధంగా తిరిగి పంపవలసి ఉంటుంది, ఉదాహరణకు. మరియు ఈ సమస్య అప్లికేషన్ నిర్మాణాన్ని ప్రభావితం చేస్తుంది.

అనేక కారణాల వల్ల సెషన్‌లను పూర్తిగా వదిలివేయడానికి మరియు ఈ విధంగా ప్రతిస్పందించడానికి సర్వర్ అనుమతించబడుతుంది. వాస్తవానికి, క్లయింట్ వైపు నుండి MTProto సెషన్ అంటే ఏమిటి? ఇవి రెండు సంఖ్యలు session_id и seq_no ఈ సెషన్‌లోని సందేశాలు. బాగా, మరియు అంతర్లీన TCP కనెక్షన్, వాస్తవానికి. మా క్లయింట్‌కి ఇంకా చాలా పనులు ఎలా చేయాలో తెలియదని అనుకుందాం, అతను డిస్‌కనెక్ట్ చేసి మళ్లీ కనెక్ట్ అయ్యాడు. ఇది త్వరగా జరిగితే - పాత సెషన్ కొత్త TCP కనెక్షన్‌లో కొనసాగింది, పెంచండి seq_no మరింత. ఇది చాలా సమయం తీసుకుంటే, సర్వర్ దానిని తొలగించగలదు, ఎందుకంటే దాని వైపు అది కూడా క్యూ అని మేము కనుగొన్నాము.

అది ఎలా ఉండాలి seq_no? ఓహ్, అది ఒక గమ్మత్తైన ప్రశ్న. ఉద్దేశ్యాన్ని నిజాయితీగా అర్థం చేసుకోవడానికి ప్రయత్నించండి:

కంటెంట్-సంబంధిత సందేశం

స్పష్టమైన రసీదు అవసరమయ్యే సందేశం. వీటిలో అన్ని వినియోగదారు మరియు అనేక సేవా సందేశాలు ఉన్నాయి, వాస్తవంగా అన్నీ కంటైనర్‌లు మరియు రసీదులు మినహా.

మెసేజ్ సీక్వెన్స్ నంబర్ (msg_seqno)

32-బిట్ సంఖ్య "కంటెంట్-సంబంధిత" సందేశాల సంఖ్యకు రెండింతలు సమానం (రసీదు అవసరమయ్యేవి మరియు ప్రత్యేకించి కంటైనర్‌లు లేనివి) ఈ సందేశానికి ముందు పంపినవారు సృష్టించి, ఆపై ప్రస్తుత సందేశం అయితే ఒకటి ద్వారా పెంచబడుతుంది కంటెంట్-సంబంధిత సందేశం. ఒక కంటైనర్ ఎల్లప్పుడూ దాని మొత్తం కంటెంట్ తర్వాత ఉత్పత్తి చేయబడుతుంది; కాబట్టి, దాని సీక్వెన్స్ సంఖ్య దానిలో ఉన్న సందేశాల శ్రేణి సంఖ్యల కంటే ఎక్కువ లేదా సమానంగా ఉంటుంది.

1 ఇంక్రిమెంట్, ఆపై మరొకటి 2తో ఇది ఎలాంటి సర్కస్?.. మొదట్లో వారు “ACKకి అతి తక్కువ ముఖ్యమైన బిట్, మిగిలినది ఒక సంఖ్య” అని అర్థం చేసుకున్నారని నేను అనుమానిస్తున్నాను, కానీ ఫలితం అంతగా లేదు - ముఖ్యంగా, అది బయటకు వస్తుంది, పంపవచ్చు అనేక నిర్ధారణలు ఒకే విధంగా ఉంటాయి seq_no! ఎలా? ఉదాహరణకు, సర్వర్ మనకు ఏదైనా పంపుతుంది, దానిని పంపుతుంది మరియు మనం మౌనంగా ఉంటాము, దాని సందేశాల రసీదుని నిర్ధారించే సేవా సందేశాలతో మాత్రమే ప్రతిస్పందిస్తాము. ఈ సందర్భంలో, మా అవుట్‌గోయింగ్ నిర్ధారణలు ఒకే అవుట్‌గోయింగ్ నంబర్‌ను కలిగి ఉంటాయి. మీకు TCP గురించి బాగా తెలిసి ఉండి, ఇది ఏదో ఒకవిధంగా విపరీతంగా అనిపిస్తుందని అనుకుంటే, కానీ అది చాలా క్రూరంగా అనిపించదు, ఎందుకంటే TCPలో seq_no మారదు, కానీ నిర్ధారణకు వెళుతుంది seq_no మరోవైపు, నేను నిన్ను కలవరపెట్టడానికి తొందరపడతాను. MTProtoలో నిర్ధారణలు అందించబడ్డాయి NOT పై seq_no, TCP లో వలె, కానీ ద్వారా msg_id !

ఇది ఏమిటి msg_id, ఈ రంగాలలో అత్యంత ముఖ్యమైనవి? పేరు సూచించినట్లుగా ఒక ప్రత్యేక సందేశ ఐడెంటిఫైయర్. ఇది 64-బిట్ నంబర్‌గా నిర్వచించబడింది, వీటిలో అత్యల్ప బిట్‌లు మళ్లీ “సర్వర్-నాట్-సర్వర్” మ్యాజిక్‌ను కలిగి ఉంటాయి మరియు మిగిలినవి యునిక్స్ టైమ్‌స్టాంప్, పాక్షిక భాగంతో సహా, 32 బిట్‌లను ఎడమవైపుకి మార్చారు. ఆ. టైమ్‌స్టాంప్ పర్ సె (మరియు చాలా తేడా ఉన్న సమయాలతో సందేశాలు సర్వర్ ద్వారా తిరస్కరించబడతాయి). దీని నుండి సాధారణంగా ఇది క్లయింట్ కోసం గ్లోబల్ ఐడెంటిఫైయర్ అని తేలింది. ఇచ్చినది - గుర్తు చేసుకుందాం session_id - మేము హామీ ఇస్తున్నాము: ఎట్టి పరిస్థితుల్లోనూ ఒక సెషన్‌కు ఉద్దేశించిన సందేశాన్ని వేరే సెషన్‌కి పంపలేరు. అంటే, ఇది ఇప్పటికే ఉందని తేలింది మూడు స్థాయి - సెషన్, సెషన్ నంబర్, మెసేజ్ ఐడి. ఎందుకు అటువంటి ఓవర్ కాంప్లికేషన్, ఈ రహస్యం చాలా గొప్పది.

కాబట్టి, msg_id కోసం అవసరమైన...

RPC: అభ్యర్థనలు, ప్రతిస్పందనలు, లోపాలు. నిర్ధారణలు.

మీరు గమనించినట్లుగా, సమాధానాలు ఉన్నప్పటికీ, రేఖాచిత్రంలో ఎక్కడా ప్రత్యేకమైన "RPC అభ్యర్థన చేయండి" రకం లేదా ఫంక్షన్ లేదు. అన్నింటికంటే, మాకు కంటెంట్-సంబంధిత సందేశాలు ఉన్నాయి! అంటే, సందేశం ఒక అభ్యర్థన కావచ్చు! లేదా ఉండకూడదు. అన్ని తరువాత, ప్రతి ఉంది msg_id. కానీ సమాధానాలు ఉన్నాయి:

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

ఇక్కడే ఇది ఏ సందేశానికి ప్రతిస్పందన అని సూచించబడుతుంది. అందువల్ల, API యొక్క ఉన్నత స్థాయిలో, మీరు మీ అభ్యర్థన సంఖ్య ఏమిటో గుర్తుంచుకోవాలి - పని అసమకాలికమని వివరించాల్సిన అవసరం లేదని నేను భావిస్తున్నాను మరియు అదే సమయంలో అనేక అభ్యర్థనలు పురోగతిలో ఉండవచ్చు, ఏ క్రమంలో తిరిగి ఇవ్వగల సమాధానాలు? సూత్రప్రాయంగా, దీని నుండి మరియు వర్కర్లు లేరు వంటి దోష సందేశాల నుండి, దీని వెనుక ఉన్న నిర్మాణాన్ని గుర్తించవచ్చు: మీతో TCP కనెక్షన్‌ని నిర్వహించే సర్వర్ ఫ్రంట్-ఎండ్ బ్యాలెన్సర్, ఇది అభ్యర్థనలను బ్యాకెండ్‌లకు ఫార్వార్డ్ చేస్తుంది మరియు వాటి ద్వారా తిరిగి సేకరిస్తుంది message_id. ఇక్కడ ప్రతిదీ స్పష్టంగా, తార్కికంగా మరియు మంచిదని అనిపిస్తుంది.

అవునా?.. మరి ఆలోచిస్తే? అన్నింటికంటే, RPC ప్రతిస్పందన కూడా ఫీల్డ్‌ను కలిగి ఉంటుంది msg_id! “మీరు నా సమాధానానికి సమాధానం ఇవ్వడం లేదు!” అని మనం సర్వర్‌పై అరవాల్సిన అవసరం ఉందా? మరియు అవును, నిర్ధారణల గురించి ఏమి ఉంది? పేజీ గురించి సందేశాల గురించి సందేశాలు ఏమిటో మాకు చెబుతుంది

msgs_ack#62d6b459 msg_ids:Vector long = MsgsAck;

మరియు అది ప్రతి వైపు చేయాలి. కానీ ఎల్లప్పుడూ కాదు! మీరు RpcResultని స్వీకరించినట్లయితే, అది స్వయంగా నిర్ధారణగా పనిచేస్తుంది. అంటే, సర్వర్ మీ అభ్యర్థనకు MsgsAckతో ప్రతిస్పందించగలదు - "నేను దానిని స్వీకరించాను." RpcResult వెంటనే స్పందించవచ్చు. అది రెండూ కావచ్చు.

మరియు అవును, మీరు ఇంకా సమాధానం చెప్పాలి! నిర్ధారణ. లేకపోతే, సర్వర్ దానిని బట్వాడా చేయలేనిదిగా పరిగణించి, దాన్ని మీకు మళ్లీ పంపుతుంది. మళ్లీ కనెక్ట్ అయిన తర్వాత కూడా. కానీ ఇక్కడ, వాస్తవానికి, గడువు ముగిసే సమస్య తలెత్తుతుంది. వాటిని కొంచెం తర్వాత చూద్దాం.

ఈలోగా, సాధ్యమయ్యే ప్రశ్న అమలు లోపాలను చూద్దాం.

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

ఓహ్, ఎవరైనా ఆశ్చర్యపోతారు, ఇక్కడ మరింత మానవీయ ఆకృతి ఉంది - ఒక లైన్ ఉంది! మీకు కావలిసినంత సమయం తీసుకోండి. ఇక్కడ లోపాల జాబితా, కానీ పూర్తి కాదు. దాని నుండి మనకు కోడ్ అని తెలుసు అలాంటిదే HTTP లోపాలు (అలాగే, ప్రతిస్పందనల సెమాంటిక్స్ గౌరవించబడవు, కొన్ని ప్రదేశాలలో అవి కోడ్‌ల మధ్య యాదృచ్ఛికంగా పంపిణీ చేయబడతాయి), మరియు లైన్ ఇలా కనిపిస్తుంది CAPITAL_LETTERS_AND_NUMBERS. ఉదాహరణకు, PHONE_NUMBER_OCCUPIED లేదా FILE_PART_Х_MISSING. బాగా, అంటే, మీకు ఇంకా ఈ లైన్ అవసరం అన్వయించు. ఉదాహరణకు FLOOD_WAIT_3600 మీరు ఒక గంట వేచి ఉండాలి అని అర్థం, మరియు PHONE_MIGRATE_5, ఈ ఉపసర్గతో కూడిన టెలిఫోన్ నంబర్ తప్పనిసరిగా 5వ DCలో నమోదు చేయబడాలి. మాకు టైప్ లాంగ్వేజ్ ఉంది, సరియైనదా? మాకు స్ట్రింగ్ నుండి వాదన అవసరం లేదు, సాధారణ వాటిని చేస్తుంది, సరే.

మళ్ళీ, ఇది సేవా సందేశాల పేజీలో లేదు, కానీ, ఈ ప్రాజెక్ట్‌తో ఇప్పటికే సాధారణంగా ఉన్నట్లుగా, సమాచారాన్ని కనుగొనవచ్చు మరొక డాక్యుమెంటేషన్ పేజీలో. లేదా అనుమానం కలిగింది. ముందుగా, చూడండి, టైపింగ్/లేయర్ ఉల్లంఘన - RpcError లో గూడు కట్టుకోవచ్చు RpcResult. బయట ఎందుకు కాదు? ఏం లెక్కలోకి తీసుకోలేదు?.. దాని ప్రకారం ఆ హామీ ఎక్కడిది RpcError లో పొందుపరచబడకపోవచ్చు RpcResult, కానీ నేరుగా లేదా మరొక రకంలో గూడు కట్టుకున్నారా?.. మరియు అది చేయలేకపోతే, అది ఎందుకు ఉన్నత స్థాయిలో లేదు, అనగా. అది లేదు req_msg_id ? ..

అయితే సేవా సందేశాల గురించి కొనసాగిద్దాం. సర్వర్ చాలా కాలంగా ఆలోచిస్తున్నట్లు క్లయింట్ అనుకోవచ్చు మరియు అటువంటి అద్భుతమైన అభ్యర్థనను చేయవచ్చు:

rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;

ఈ ప్రశ్నకు మూడు సాధ్యమైన సమాధానాలు ఉన్నాయి, అవి ఎలా ఉండాలో అర్థం చేసుకోవడానికి ప్రయత్నిస్తూ (మరియు నిర్ధారణ అవసరం లేని రకాల సాధారణ జాబితా) రీడర్‌కు హోమ్‌వర్క్‌గా వదిలివేయబడుతుంది (గమనిక: దీనిలోని సమాచారం; టెలిగ్రామ్ డెస్క్‌టాప్ సోర్స్ కోడ్ పూర్తి కాలేదు).

మాదకద్రవ్య వ్యసనం: సందేశ స్థితిగతులు

సాధారణంగా, TL, MTProto మరియు టెలిగ్రామ్‌లోని అనేక ప్రదేశాలు సాధారణంగా మొండితనం యొక్క అనుభూతిని కలిగిస్తాయి, కానీ మర్యాద, వ్యూహం మరియు ఇతరుల నుండి మృదువైన నైపుణ్యాలు మేము దాని గురించి మర్యాదగా మౌనంగా ఉండి, డైలాగ్‌లలోని అసభ్యతలను సెన్సార్ చేసాము. అయితే, ఈ స్థలంОపేజీలో ఎక్కువ భాగం గురించి ఉంది సందేశాల గురించి సందేశాలు చాలా కాలంగా నెట్‌వర్క్ ప్రోటోకాల్‌లతో పని చేస్తున్న మరియు వివిధ స్థాయిల వంకర సైకిళ్లను చూసిన నాకు కూడా ఇది షాకింగ్‌గా ఉంది.

ఇది ధృవీకరణలతో హానికరంగా ప్రారంభమవుతుంది. తదుపరి వారు మాకు గురించి చెబుతారు

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

సరే, MTProtoతో పని చేయడం ప్రారంభించిన ప్రతి ఒక్కరూ "సరిదిద్దబడిన - పునఃసంకలనం చేయబడిన - ప్రారంభించబడిన" సైకిల్‌లో వాటిని ఎదుర్కోవలసి ఉంటుంది, సవరణల సమయంలో తప్పుగా మారిన సంఖ్య లోపాలు లేదా ఉప్పును పొందడం అనేది సాధారణ విషయం. అయితే, ఇక్కడ రెండు పాయింట్లు ఉన్నాయి:

  1. దీని అర్థం అసలు సందేశం పోయింది. మేము కొన్ని క్యూలను సృష్టించాలి, మేము దానిని తర్వాత చూద్దాం.
  2. ఈ వింత దోష సంఖ్యలు ఏమిటి? 16, 17, 18, 19, 20, 32, 33, 34, 35, 48, 64... ఇతర సంఖ్యలు ఎక్కడ ఉన్నాయి, టామీ?

డాక్యుమెంటేషన్ ఇలా పేర్కొంది:

ఉద్దేశ్యం ఏమిటంటే ఎర్రర్_కోడ్ విలువలు సమూహం చేయబడ్డాయి (error_code >> 4): ఉదాహరణకు, 0x40 — 0x4f కోడ్‌లు కంటైనర్ కుళ్ళిపోవడంలో లోపాలకు అనుగుణంగా ఉంటాయి.

కానీ, మొదట, ఇతర దిశలో మార్పు, మరియు రెండవది, ఇది పట్టింపు లేదు, ఇతర కోడ్‌లు ఎక్కడ ఉన్నాయి? రచయిత తలలో?.. అయితే, ఇవి చిన్నవిషయాలు.

సందేశ స్థితిగతులు మరియు సందేశ కాపీల గురించి సందేశాలలో వ్యసనం ప్రారంభమవుతుంది:

  • సందేశ స్థితి సమాచారం కోసం అభ్యర్థన
    ఏ పక్షం అయినా దాని అవుట్‌గోయింగ్ సందేశాల స్థితిపై కొంతకాలం సమాచారం అందకపోతే, అది ఇతర పక్షం నుండి దానిని స్పష్టంగా అభ్యర్థించవచ్చు:
    msgs_state_req#da69fb52 msg_ids:Vector long = MsgsStateReq;
  • సందేశాల స్థితికి సంబంధించిన సమాచార సందేశం
    msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
    ఇక్కడ, info ఇన్‌కమింగ్ msg_idల జాబితా నుండి ప్రతి సందేశానికి సరిగ్గా ఒక బైట్ సందేశ స్థితిని కలిగి ఉండే స్ట్రింగ్:

    • 1 = సందేశం గురించి ఏమీ తెలియదు (msg_id చాలా తక్కువ, ఇతర పక్షం దానిని మరచిపోయి ఉండవచ్చు)
    • 2 = సందేశం అందలేదు (msg_id నిల్వ చేయబడిన ఐడెంటిఫైయర్‌ల పరిధిలోకి వస్తుంది; అయితే, ఇతర పక్షం ఖచ్చితంగా అలాంటి సందేశాన్ని స్వీకరించలేదు)
    • 3 = సందేశం అందలేదు (msg_id చాలా ఎక్కువ; అయినప్పటికీ, అవతలి పక్షం ఖచ్చితంగా దాన్ని ఇంకా స్వీకరించలేదు)
    • 4 = సందేశం స్వీకరించబడింది (ఈ ప్రతిస్పందన అదే సమయంలో రసీదు రసీదు అని గమనించండి)
    • +8 = సందేశం ఇప్పటికే అంగీకరించబడింది
    • +16 = రసీదు అవసరం లేని సందేశం
    • +32 = మెసేజ్‌లో ఉన్న RPC ప్రశ్న ప్రాసెస్ చేయబడుతోంది లేదా ప్రాసెస్ చేయడం ఇప్పటికే పూర్తయింది
    • +64 = ఇప్పటికే రూపొందించబడిన సందేశానికి కంటెంట్-సంబంధిత ప్రతిస్పందన
    • +128 = సందేశం ఇప్పటికే అందిందని ఇతర పార్టీకి తెలుసు
      ఈ ప్రతిస్పందనకు రసీదు అవసరం లేదు. ఇది సంబంధిత msgs_state_req యొక్క రసీదు, మరియు దానికదే.
      అవతలి పక్షానికి పంపినట్లుగా కనిపించే సందేశం లేదని అకస్మాత్తుగా తేలితే, సందేశాన్ని మళ్లీ పంపవచ్చని గమనించండి. అదే సమయంలో ఇతర పక్షం సందేశం యొక్క రెండు కాపీలను స్వీకరించినప్పటికీ, నకిలీ విస్మరించబడుతుంది. (చాలా సమయం గడిచిపోయి, అసలు msg_id చెల్లుబాటు కాకపోతే, సందేశం msg_copyతో చుట్టబడుతుంది).
  • సందేశాల స్థితి యొక్క స్వచ్ఛంద కమ్యూనికేషన్
    ఏ పార్టీ అయినా ఇతర పార్టీ ద్వారా ప్రసారం చేయబడిన సందేశాల స్థితిని స్వచ్ఛందంగా ఇతర పార్టీకి తెలియజేయవచ్చు.
    msgs_all_info#8cc0d131 msg_ids:Vector long info:string = MsgsAllInfo
  • ఒక సందేశం యొక్క స్థితి యొక్క విస్తరించిన స్వచ్ఛంద కమ్యూనికేషన్
    ...
    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;
  • సందేశాలను మళ్లీ పంపడానికి స్పష్టమైన అభ్యర్థన
    msg_resend_req#7d861a08 msg_ids:Vector long = MsgResendReq;
    అభ్యర్థించిన సందేశాలను మళ్లీ పంపడం ద్వారా రిమోట్ పార్టీ వెంటనే ప్రతిస్పందిస్తుంది […]
  • సమాధానాలను మళ్లీ పంపాలని స్పష్టమైన అభ్యర్థన
    msg_resend_ans_req#8610baeb msg_ids:Vector long = MsgResendReq;
    రిమోట్ పార్టీ వెంటనే మళ్లీ పంపడం ద్వారా ప్రతిస్పందిస్తుంది సమాధానాలు అభ్యర్థించిన సందేశాలకు […]
  • సందేశ కాపీలు
    కొన్ని సందర్భాల్లో, చెల్లుబాటు కాని msg_idతో పాత సందేశాన్ని మళ్లీ పంపాల్సిన అవసరం ఉంది. అప్పుడు, అది కాపీ కంటైనర్‌లో చుట్టబడుతుంది:
    msg_copy#e06046b2 orig_message:Message = MessageCopy;
    అందుకున్న తర్వాత, సందేశం రేపర్ లేనట్లుగా ప్రాసెస్ చేయబడుతుంది. అయినప్పటికీ, orig_message.msg_id సందేశం అందిందని ఖచ్చితంగా తెలిస్తే, కొత్త సందేశం ప్రాసెస్ చేయబడదు (అదే సమయంలో, అది మరియు orig_message.msg_id గుర్తించబడతాయి). orig_message.msg_id విలువ తప్పనిసరిగా కంటైనర్ msg_id కంటే తక్కువగా ఉండాలి.

దేని గురించి కూడా మౌనంగా ఉండుదాం msgs_state_info మళ్లీ అసంపూర్తిగా ఉన్న TL యొక్క చెవులు బయటకు అంటుకున్నాయి (మాకు బైట్‌ల వెక్టర్ అవసరం, మరియు దిగువ రెండు బిట్‌లలో ఒక enum ఉంది మరియు ఎగువ రెండు బిట్‌లలో ఫ్లాగ్‌లు ఉన్నాయి). పాయింట్ వేరే ఉంది. ఇదంతా ఎందుకు ఆచరణలో ఉందో ఎవరికైనా అర్థమైందా? నిజమైన క్లయింట్‌లో అవసరం? కానీ ఇక్కడ అభ్యర్థనలు వివరించబడ్డాయి రౌండ్ ట్రిప్.

ప్రతి పక్షం సందేశాలను ఎన్‌క్రిప్ట్ చేసి పంపడమే కాకుండా తమ గురించి, వాటికి ప్రతిస్పందనల గురించి తెలియని సమయం వరకు డేటాను కూడా నిల్వ చేయాలి. డాక్యుమెంటేషన్ సమయాలను లేదా ఈ లక్షణాల యొక్క ఆచరణాత్మక అన్వయాన్ని వివరించలేదు. మార్గం లేదు. అత్యంత అద్భుతమైన విషయం ఏమిటంటే అవి అధికారిక క్లయింట్‌ల కోడ్‌లో ఉపయోగించబడతాయి! పబ్లిక్ డాక్యుమెంటేషన్‌లో చేర్చని విషయం వారికి చెప్పబడింది. కోడ్ నుండి అర్థం చేసుకోండి ఎందుకు, ఇకపై TL విషయంలో అంత సులభం కాదు - ఇది (సాపేక్షంగా) తార్కికంగా వివిక్త భాగం కాదు, కానీ అప్లికేషన్ ఆర్కిటెక్చర్‌తో ముడిపడి ఉన్న భాగం, అనగా. అప్లికేషన్ కోడ్‌ని అర్థం చేసుకోవడానికి మరింత సమయం పడుతుంది.

పింగ్‌లు మరియు సమయాలు. క్యూలు.

అన్నింటి నుండి, మేము సర్వర్ ఆర్కిటెక్చర్ (బ్యాకెండ్‌లలో అభ్యర్థనల పంపిణీ) గురించిన అంచనాలను గుర్తుంచుకుంటే, చాలా విచారకరమైన విషయం అనుసరిస్తుంది - TCPలో అన్ని డెలివరీ హామీలు ఉన్నప్పటికీ (డేటా డెలివరీ చేయబడింది లేదా మీకు గ్యాప్ గురించి తెలియజేయబడుతుంది, కానీ సమస్య సంభవించే ముందు డేటా బట్వాడా చేయబడుతుంది), MTProto లోనే ఆ నిర్ధారణలు - హామీలు లేవు. సర్వర్ మీ సందేశాన్ని సులభంగా కోల్పోవచ్చు లేదా విసిరివేయవచ్చు మరియు దాని గురించి ఏమీ చేయలేము, వివిధ రకాల క్రచెస్‌లను ఉపయోగించండి.

మరియు అన్నింటిలో మొదటిది - సందేశ క్యూలు. సరే, ఒక విషయంతో మొదటి నుండి ప్రతిదీ స్పష్టంగా ఉంది - ధృవీకరించబడని సందేశాన్ని తప్పనిసరిగా నిల్వ చేయాలి మరియు మళ్లీ పంపాలి. ఇంక ఎంత సేపు పడుతుంది? మరియు హాస్యాస్పదుడు అతనికి తెలుసు. బహుశా ఆ బానిస సేవా సందేశాలు క్రచెస్‌తో ఈ సమస్యను ఎలాగైనా పరిష్కరిస్తాయి, చెప్పండి, టెలిగ్రామ్ డెస్క్‌టాప్‌లో వాటికి అనుగుణంగా సుమారు 4 క్యూలు ఉన్నాయి (బహుశా మరింత, ఇప్పటికే చెప్పినట్లుగా, దీని కోసం మీరు దాని కోడ్ మరియు ఆర్కిటెక్చర్‌ను మరింత తీవ్రంగా పరిశోధించాలి; అదే సమయంలో సమయం, ఇది MTProto పథకం నుండి నిర్దిష్ట సంఖ్యలో ఉపయోగించబడదని మాకు తెలుసు;

ఇలా ఎందుకు జరుగుతోంది? బహుశా, సర్వర్ ప్రోగ్రామర్లు క్లస్టర్‌లో విశ్వసనీయతను నిర్ధారించలేకపోయారు, లేదా ముందు బ్యాలన్సర్‌పై బఫరింగ్ చేయడం మరియు ఈ సమస్యను క్లయింట్‌కు బదిలీ చేయడం జరిగింది. నిరాశతో, వాసిలీ ప్రత్యామ్నాయ ఎంపికను అమలు చేయడానికి ప్రయత్నించాడు, కేవలం రెండు క్యూలతో, TCP నుండి అల్గోరిథంలను ఉపయోగించి - సర్వర్‌కు RTTని కొలవడం మరియు ధృవీకరించని అభ్యర్థనల సంఖ్యను బట్టి “విండో” (సందేశాలలో) పరిమాణాన్ని సర్దుబాటు చేయడం. అంటే, సర్వర్ యొక్క లోడ్‌ను అంచనా వేయడానికి ఇంత కఠినమైన హ్యూరిస్టిక్ అంటే, అది మన అభ్యర్థనలలో ఎన్నింటిని ఒకే సమయంలో నమలవచ్చు మరియు కోల్పోదు.

బాగా, అంటే, మీరు అర్థం చేసుకున్నారు, సరియైనదా? మీరు TCPపై నడుస్తున్న ప్రోటోకాల్ పైన మళ్లీ TCPని అమలు చేయవలసి వస్తే, ఇది చాలా పేలవంగా రూపొందించబడిన ప్రోటోకాల్‌ను సూచిస్తుంది.

అయ్యో, మీకు ఒకటి కంటే ఎక్కువ క్యూలు ఎందుకు అవసరం మరియు ఉన్నత స్థాయి APIతో పని చేసే వ్యక్తికి దీని అర్థం ఏమిటి? చూడండి, మీరు ఒక అభ్యర్థన చేస్తారు, దానిని సీరియల్ చేయండి, కానీ తరచుగా మీరు దానిని వెంటనే పంపలేరు. ఎందుకు? ఎందుకంటే సమాధానం ఉంటుంది msg_id, ఇది తాత్కాలికమైనదిаనేను ఒక లేబుల్‌ని, అసైన్‌మెంట్ వీలైనంత ఆలస్యంగా వాయిదా వేయబడుతుంది - ఒక వేళ సర్వర్ మాకు మరియు అతనికి మధ్య సమయం సరిపోకపోవడం వల్ల దానిని తిరస్కరించినట్లయితే (అయితే, మన సమయాన్ని వర్తమానం నుండి మార్చే క్రచ్‌ను మనం తయారు చేసుకోవచ్చు సర్వర్ ప్రతిస్పందనల నుండి లెక్కించబడిన డెల్టాను జోడించడం ద్వారా సర్వర్‌కు - అధికారిక క్లయింట్లు దీన్ని చేస్తారు, కానీ బఫరింగ్ కారణంగా ఇది ముడి మరియు సరికాదు). కాబట్టి, మీరు లైబ్రరీ నుండి స్థానిక ఫంక్షన్ కాల్‌తో అభ్యర్థన చేసినప్పుడు, సందేశం క్రింది దశల ద్వారా వెళుతుంది:

  1. ఇది ఒక క్యూలో ఉంది మరియు ఎన్‌క్రిప్షన్ కోసం వేచి ఉంది.
  2. నియమితులయ్యారు msg_id మరియు సందేశం మరొక క్యూకి వెళ్ళింది - ఫార్వార్డింగ్ సాధ్యం; సాకెట్కు పంపండి.
  3. ఎ) సర్వర్ MsgsAckకు ప్రతిస్పందించింది - సందేశం పంపిణీ చేయబడింది, మేము దానిని "ఇతర క్యూ" నుండి తొలగిస్తాము.
    బి) లేదా వైస్ వెర్సా, అతను ఏదో ఇష్టపడలేదు, అతను బ్యాడ్మ్స్‌జికి సమాధానం ఇచ్చాడు - “మరొక క్యూ” నుండి తిరిగి పంపు
    c) ఏమీ తెలియదు, సందేశాన్ని మరొక క్యూ నుండి మళ్లీ పంపాలి - కానీ అది ఎప్పుడు అనేది ఖచ్చితంగా తెలియదు.
  4. సర్వర్ చివరకు స్పందించింది RpcResult - వాస్తవ ప్రతిస్పందన (లేదా లోపం) - డెలివరీ చేయడమే కాదు, ప్రాసెస్ చేయబడింది కూడా.

బహుశా, కంటైనర్ల వాడకం సమస్యను పాక్షికంగా పరిష్కరించగలదు. ఇలాంటప్పుడు కొన్ని సందేశాలు ఒకటిగా ప్యాక్ చేయబడి ఉంటాయి మరియు సర్వర్ వాటన్నింటికీ ఒకేసారి నిర్ధారణతో ప్రతిస్పందించింది. msg_id. కానీ ఏదైనా తప్పు జరిగితే, అతను ఈ ప్యాక్‌ని పూర్తిగా తిరస్కరిస్తాడు.

మరియు ఈ సమయంలో నాన్-టెక్నికల్ పరిగణనలు అమలులోకి వస్తాయి. అనుభవం నుండి, మేము చాలా ఊతకర్రలను చూశాము మరియు అదనంగా, మేము ఇప్పుడు చెడు సలహా మరియు వాస్తుశిల్పం యొక్క మరిన్ని ఉదాహరణలను చూస్తాము - అటువంటి పరిస్థితులలో, విశ్వసించడం మరియు అలాంటి నిర్ణయాలు తీసుకోవడం విలువైనదేనా? ప్రశ్న అలంకారికమైనది (కోర్సు కాదు).

మనం దేని గురించి మాట్లాడుతున్నాం? ఒకవేళ “మెసేజ్‌ల గురించి డ్రగ్ మెసేజ్‌లు” అనే అంశంపై మీరు ఇప్పటికీ “మీరు తెలివితక్కువవారు, మా అద్భుతమైన ప్రణాళికను అర్థం చేసుకోలేదు!” వంటి అభ్యంతరాలతో ఊహించవచ్చు. (కాబట్టి ముందుగా డాక్యుమెంటేషన్‌ను వ్రాయండి, సాధారణ వ్యక్తులు, హేతుబద్ధత మరియు ప్యాకెట్ మార్పిడికి ఉదాహరణలతో, ఆపై మేము మాట్లాడుతాము), ఆపై సమయాలు/సమయ ముగింపులు పూర్తిగా ఆచరణాత్మక మరియు నిర్దిష్ట ప్రశ్న, ఇక్కడ ప్రతిదీ చాలా కాలంగా తెలుసు. గడువు ముగింపుల గురించి డాక్యుమెంటేషన్ మాకు ఏమి చెబుతుంది?

సర్వర్ సాధారణంగా RPC ప్రతిస్పందనను ఉపయోగించి క్లయింట్ (సాధారణంగా, RPC ప్రశ్న) నుండి సందేశం అందినట్లు గుర్తిస్తుంది. ప్రతిస్పందన రావడానికి చాలా సమయం ఉంటే, సర్వర్ మొదట రసీదు రసీదుని పంపవచ్చు మరియు కొంత సమయం తరువాత, RPC ప్రతిస్పందనను పంపవచ్చు.

క్లయింట్ సాధారణంగా సర్వర్ (సాధారణంగా, RPC ప్రతిస్పందన) నుండి వచ్చిన సందేశాన్ని చాలా ఆలస్యంగా ప్రసారం చేయకుంటే తదుపరి RPC ప్రశ్నకు రసీదుని జోడించడం ద్వారా అంగీకరిస్తాడు (అది రూపొందించబడితే, రసీదు తర్వాత 60-120 సెకన్ల తర్వాత చెప్పండి. సర్వర్ నుండి సందేశం). అయితే, ఎక్కువ కాలం పాటు సర్వర్‌కు సందేశాలను పంపడానికి ఎటువంటి కారణం లేకుంటే లేదా సర్వర్ నుండి పెద్ద సంఖ్యలో గుర్తించబడని సందేశాలు ఉంటే (చెప్పండి, 16 కంటే ఎక్కువ), క్లయింట్ స్టాండ్-అలోన్ రసీదుని పంపుతుంది.

... నేను అనువదిస్తాను: మనకు అది ఎంత మరియు ఎలా అవసరమో మనకు తెలియదు, కాబట్టి ఇది ఇలా ఉండనివ్వండి.

మరియు పింగ్స్ గురించి:

పింగ్ సందేశాలు (పింగ్/పాంగ్)

ping#7abe77ec ping_id:long = Pong;

ప్రతిస్పందన సాధారణంగా అదే కనెక్షన్‌కు తిరిగి ఇవ్వబడుతుంది:

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

ఈ సందేశాలకు రసీదులు అవసరం లేదు. ఒక పాంగ్ పింగ్‌కు ప్రతిస్పందనగా మాత్రమే ప్రసారం చేయబడుతుంది, అయితే పింగ్‌ను ఇరువైపులా ప్రారంభించవచ్చు.

వాయిదాపడిన కనెక్షన్ మూసివేత + PING

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

పింగ్ లాగా పనిచేస్తుంది. అదనంగా, ఇది స్వీకరించబడిన తర్వాత, సర్వర్ టైమర్‌ను ప్రారంభిస్తుంది, ఇది మునుపటి అన్ని టైమర్‌లను స్వయంచాలకంగా రీసెట్ చేసే అదే రకమైన కొత్త సందేశాన్ని అందుకోకపోతే ప్రస్తుత కనెక్షన్ disconnect_delay సెకన్ల తర్వాత మూసివేయబడుతుంది. క్లయింట్ ప్రతి 60 సెకన్లకు ఒకసారి ఈ పింగ్‌లను పంపితే, ఉదాహరణకు, అది disconnect_delayని 75 సెకన్లకు సమానంగా సెట్ చేయవచ్చు.

నేకేమన్న పిచ్చి పట్టిందా?! 60 సెకన్లలో, రైలు స్టేషన్‌లోకి ప్రవేశించి, ప్రయాణికులను దించి, ఎక్కించుకుని, మళ్లీ సొరంగంలో సంబంధాన్ని కోల్పోతుంది. 120 సెకన్లలో, మీరు దానిని వింటున్నప్పుడు, అది మరొకదానికి చేరుకుంటుంది మరియు కనెక్షన్ చాలావరకు విరిగిపోతుంది. బాగా, కాళ్ళు ఎక్కడ నుండి వస్తున్నాయో స్పష్టంగా ఉంది - "నాకు రింగింగ్ వినిపించింది, కానీ అది ఎక్కడ ఉందో తెలియదు", ఇంటరాక్టివ్ పని కోసం ఉద్దేశించిన నాగ్ల్ యొక్క అల్గోరిథం మరియు TCP_NODELAY ఎంపిక ఉంది. కానీ, క్షమించండి, దాని డిఫాల్ట్ విలువ - 200ని పట్టుకోండి మిల్లీసెకన్లు మీరు నిజంగా ఇలాంటివి చిత్రీకరించి, కొన్ని ప్యాకెట్‌లలో సేవ్ చేయాలనుకుంటే, దాన్ని 5 సెకన్ల పాటు నిలిపివేయండి లేదా “వినియోగదారుడు టైప్ చేస్తున్నారు...” సందేశం గడువు ముగిసింది. కానీ ఇక లేదు.

చివరకు, పింగ్స్. అంటే, TCP కనెక్షన్ యొక్క ప్రత్యక్షతను తనిఖీ చేయడం. ఇది హాస్యాస్పదంగా ఉంది, కానీ సుమారు 10 సంవత్సరాల క్రితం నేను మా ఫ్యాకల్టీ డార్మ్ యొక్క మెసెంజర్ గురించి ఒక క్లిష్టమైన వచనాన్ని వ్రాసాను - అక్కడ ఉన్న రచయితలు క్లయింట్ నుండి సర్వర్‌ను కూడా పింగ్ చేసారు మరియు దీనికి విరుద్ధంగా కాదు. కానీ 3 వ సంవత్సరం విద్యార్థులు ఒక విషయం, మరియు అంతర్జాతీయ కార్యాలయం మరొకటి, సరియైనదా?

మొదట, ఒక చిన్న విద్యా కార్యక్రమం. TCP కనెక్షన్, ప్యాకెట్ మార్పిడి లేనప్పుడు, వారాలపాటు జీవించగలదు. ఇది ప్రయోజనాన్ని బట్టి మంచి మరియు చెడు రెండూ. మీరు సర్వర్‌కు SSH కనెక్షన్ తెరిచి ఉంటే మంచిది, మీరు కంప్యూటర్ నుండి లేచి, రూటర్‌ను రీబూట్ చేసి, మీ స్థానానికి తిరిగి వచ్చారు - ఈ సర్వర్ ద్వారా సెషన్ చిరిగిపోలేదు (మీరు ఏమీ టైప్ చేయలేదు, ప్యాకెట్లు లేవు) , ఇది సౌకర్యవంతంగా ఉంటుంది. సర్వర్‌లో వేలకొద్దీ క్లయింట్లు ఉంటే, ప్రతి ఒక్కరూ రిసోర్స్‌లను (హలో, పోస్ట్‌గ్రెస్!) తీసుకుంటే అది చెడ్డది మరియు క్లయింట్ హోస్ట్ చాలా కాలం క్రితం రీబూట్ చేసి ఉండవచ్చు - కానీ దాని గురించి మాకు తెలియదు.

చాట్/IM సిస్టమ్‌లు ఒక అదనపు కారణంతో రెండవ సందర్భంలో వస్తాయి - ఆన్‌లైన్ స్థితిగతులు. వినియోగదారు “పడిపోతే”, మీరు దీని గురించి అతని సంభాషణకర్తలకు తెలియజేయాలి. లేకపోతే, మీరు జబ్బర్ సృష్టికర్తలు చేసిన పొరపాటుతో ముగుస్తుంది (మరియు 20 సంవత్సరాలు సరిదిద్దబడింది) - వినియోగదారు డిస్‌కనెక్ట్ చేసారు, కానీ అతను ఆన్‌లైన్‌లో ఉన్నాడని నమ్మి వారు అతనికి సందేశాలు రాయడం కొనసాగిస్తున్నారు (వీటిలో కూడా పూర్తిగా కోల్పోయారు డిస్‌కనెక్ట్ కనుగొనబడటానికి కొన్ని నిమిషాల ముందు). లేదు, TCP_KEEPALIVE ఎంపిక, TCP టైమర్‌లు ఎలా పనిచేస్తాయో అర్థం కాని వ్యక్తులు యాదృచ్ఛికంగా (పది సెకన్లు వంటి వైల్డ్ విలువలను సెట్ చేయడం ద్వారా) విసిరివేస్తారు - మీరు OS కెర్నల్ మాత్రమే కాకుండా చూసుకోవాలి వినియోగదారు యొక్క యంత్రం సజీవంగా ఉంది, కానీ సాధారణంగా పని చేస్తుంది, ప్రతిస్పందించగలదు మరియు అప్లికేషన్ కూడా (ఇది స్తంభింపజేయలేదని మీరు అనుకుంటున్నారా? ఉబుంటు 18.04లోని టెలిగ్రామ్ డెస్క్‌టాప్ నా కోసం ఒకటి కంటే ఎక్కువసార్లు స్తంభింపజేసింది).

అందుకే పింగ్ చేయాలి సర్వర్ క్లయింట్, మరియు వైస్ వెర్సా కాదు - క్లయింట్ ఇలా చేస్తే, కనెక్షన్ విచ్ఛిన్నమైతే, పింగ్ పంపిణీ చేయబడదు, లక్ష్యం సాధించబడదు.

టెలిగ్రామ్‌లో మనం ఏమి చూస్తాము? ఇది సరిగ్గా వ్యతిరేకం! బాగా, అంటే. అధికారికంగా, రెండు వైపులా పరస్పరం పింగ్ చేయవచ్చు. ఆచరణలో, క్లయింట్లు ఒక ఊతకర్రను ఉపయోగిస్తారు ping_delay_disconnect, ఇది సర్వర్‌లో టైమర్‌ను సెట్ చేస్తుంది. సరే, నన్ను క్షమించండి, క్లయింట్ పింగ్ లేకుండా ఎంతకాలం అక్కడ నివసించాలనుకుంటున్నారో నిర్ణయించుకునే హక్కు లేదు. సర్వర్, దాని లోడ్ ఆధారంగా, బాగా తెలుసు. కానీ, వాస్తవానికి, మీరు వనరులను పట్టించుకోకపోతే, మీరు మీ స్వంత దుష్ట పినోచియో అవుతారు మరియు ఊతకర్ర చేస్తుంది...

దీన్ని ఎలా డిజైన్ చేసి ఉండాలి?

టెలిగ్రామ్/VKontakte బృందం కంప్యూటర్ నెట్‌వర్క్‌ల యొక్క రవాణా (మరియు తక్కువ) స్థాయి మరియు సంబంధిత విషయాలలో వారి తక్కువ అర్హతలలో చాలా సమర్థంగా లేదని పై వాస్తవాలు స్పష్టంగా సూచిస్తున్నాయని నేను నమ్ముతున్నాను.

ఇది ఎందుకు చాలా క్లిష్టంగా మారింది మరియు టెలిగ్రామ్ వాస్తుశిల్పులు ఎలా అభ్యంతరం చెప్పడానికి ప్రయత్నించవచ్చు? TCP కనెక్షన్‌ని బ్రతికించే సెషన్‌ను రూపొందించడానికి వారు ప్రయత్నించిన వాస్తవం, అంటే, ఇప్పుడు డెలివరీ చేయనిది, మేము తర్వాత బట్వాడా చేస్తాము. వారు బహుశా UDP రవాణా చేయడానికి కూడా ప్రయత్నించారు, కానీ వారు ఇబ్బందులను ఎదుర్కొన్నారు మరియు దానిని విడిచిపెట్టారు (అందుకే డాక్యుమెంటేషన్ ఖాళీగా ఉంది - గొప్పగా చెప్పుకోవడానికి ఏమీ లేదు). కానీ సాధారణంగా నెట్‌వర్క్‌లు మరియు నిర్దిష్టంగా TCP ఎలా పని చేస్తాయి, మీరు దానిపై ఎక్కడ ఆధారపడవచ్చు మరియు మీరు దీన్ని ఎక్కడ చేయాలి (మరియు ఎలా) మరియు దీన్ని క్రిప్టోగ్రఫీతో కలపడానికి ప్రయత్నించడం వల్ల “రెండు పక్షులు ఒకే రాయి”, ఇది ఫలితం.

అది ఎలా అవసరమైంది? అనే వాస్తవం ఆధారంగా msg_id రీప్లే దాడులను నిరోధించడానికి క్రిప్టోగ్రాఫిక్ కోణం నుండి అవసరమైన టైమ్‌స్టాంప్, దానికి ప్రత్యేకమైన ఐడెంటిఫైయర్ ఫంక్షన్‌ను జోడించడం పొరపాటు. అందువల్ల, ప్రస్తుత నిర్మాణాన్ని ప్రాథమికంగా మార్చకుండా (నవీకరణల స్ట్రీమ్ రూపొందించబడినప్పుడు, ఈ పోస్ట్‌ల శ్రేణిలో మరొక భాగానికి ఇది ఉన్నత-స్థాయి API అంశం), ఒకరు వీటిని చేయాల్సి ఉంటుంది:

  1. క్లయింట్‌కు TCP కనెక్షన్‌ని కలిగి ఉన్న సర్వర్ బాధ్యత వహిస్తుంది - అది సాకెట్ నుండి చదివి ఉంటే, దయచేసి లోపాన్ని గుర్తించండి, ప్రాసెస్ చేయండి లేదా తిరిగి ఇవ్వండి, నష్టాలు లేవు. అప్పుడు నిర్ధారణ అనేది idల వెక్టర్ కాదు, కానీ కేవలం “చివరిగా స్వీకరించినది seq_no” - TCP (రెండు సంఖ్యలు - మీ seq మరియు ధృవీకరించబడినది) వలె కేవలం ఒక సంఖ్య. మేము ఎల్లప్పుడూ సెషన్‌లో ఉంటాము, కాదా?
  2. రీప్లే దాడులను నిరోధించే టైమ్‌స్టాంప్ ప్రత్యేక ఫీల్డ్, లా నాన్స్ అవుతుంది. ఇది తనిఖీ చేయబడింది, కానీ మరేదైనా ప్రభావితం చేయదు. తగినంత మరియు uint32 - మన ఉప్పు కనీసం ప్రతి సగం రోజుకి మారితే, మేము 16 బిట్‌లను ప్రస్తుత సమయం యొక్క పూర్ణాంకం యొక్క తక్కువ-ఆర్డర్ బిట్‌లకు కేటాయించవచ్చు, మిగిలినవి - సెకనులో కొంత భాగానికి (ఇప్పుడు వలె).
  3. తీసివేయబడింది msg_id అస్సలు - బ్యాకెండ్‌లపై అభ్యర్థనలను వేరు చేసే కోణం నుండి, మొదట, క్లయింట్ ఐడి మరియు రెండవది, సెషన్ ఐడి, వాటిని కలపడం. దీని ప్రకారం, అభ్యర్థన ఐడెంటిఫైయర్‌గా ఒక విషయం మాత్రమే సరిపోతుంది seq_no.

ఇది కూడా అత్యంత విజయవంతమైన ఎంపిక కాదు; పూర్తి యాదృచ్ఛిక ఐడెంటిఫైయర్‌గా ఉపయోగపడుతుంది - సందేశాన్ని పంపేటప్పుడు ఇది ఇప్పటికే అధిక-స్థాయి APIలో చేయబడుతుంది. ఆర్కిటెక్చర్‌ను సాపేక్షం నుండి సంపూర్ణంగా పూర్తిగా రీమేక్ చేయడం మంచిది, అయితే ఇది మరొక భాగానికి సంబంధించిన అంశం, ఈ పోస్ట్ కాదు.

API?

తా-దామ్! కాబట్టి, నొప్పి మరియు ఊతకర్రలతో నిండిన మార్గంలో కష్టపడి, చివరకు మేము సర్వర్‌కు ఏవైనా అభ్యర్థనలను పంపగలిగాము మరియు వాటికి ఏవైనా సమాధానాలను స్వీకరించగలిగాము, అలాగే సర్వర్ నుండి నవీకరణలను స్వీకరించగలిగాము (అభ్యర్థనకు ప్రతిస్పందనగా కాదు, కానీ అది స్వయంగా మాకు పంపుతుంది, పుష్ వంటి, ఎవరైనా ఆ విధంగా స్పష్టంగా ఉంటే).

శ్రద్ధ, ఇప్పుడు వ్యాసంలో పెర్ల్‌లో ఒకే ఉదాహరణ ఉంటుంది! (సింటాక్స్ గురించి తెలియని వారికి, బ్లెస్ యొక్క మొదటి వాదన వస్తువు యొక్క డేటా నిర్మాణం, రెండవది దాని తరగతి):

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

అవును, ఉద్దేశపూర్వకంగా స్పాయిలర్ కాదు - మీరు ఇంకా చదవకపోతే, ముందుకు సాగండి మరియు దీన్ని చేయండి!

ఓహ్, వై~~... ఇది ఎలా ఉంది? ఏదో బాగా తెలిసిన విషయం... బహుశా ఇది JSONలోని ఒక సాధారణ వెబ్ API యొక్క డేటా స్ట్రక్చర్ అయి ఉండవచ్చు, ఆబ్జెక్ట్‌లకు తరగతులు కూడా జోడించబడి ఉండవచ్చా?..

కాబట్టి ఇది ఇలా మారుతుంది... కామ్రేడ్స్, దాని గురించి ఏమిటి? ఇప్పుడే ప్రారంభం?.. HTTPS ద్వారా కేవలం JSON మాత్రమే సులభం కాదా?! బదులుగా మనం ఏమి పొందాము? ఆ ప్రయత్నం విలువైనదేనా?

TL+MTPproto మాకు ఏమి అందించిందో మరియు ఏ ప్రత్యామ్నాయాలు సాధ్యమో విశ్లేషించండి. సరే, అభ్యర్థన-ప్రతిస్పందన మోడల్‌పై దృష్టి సారించే HTTP, సరిగ్గా సరిపోతుందా, అయితే కనీసం TLS పైన ఏదైనా ఉందా?

కాంపాక్ట్ సీరియలైజేషన్. JSON మాదిరిగానే ఈ డేటా నిర్మాణాన్ని చూసినప్పుడు, దాని బైనరీ వెర్షన్‌లు ఉన్నాయని నాకు గుర్తుంది. MsgPackను తగినంతగా పొడిగించలేనిదిగా గుర్తు పెట్టుకుందాం, కానీ ఉదాహరణకు, CBOR - ఒక ప్రమాణం వివరించబడింది RFC 7049. ఇది నిర్వచించిన వాస్తవం కోసం ఇది గుర్తించదగినది టాగ్లు, విస్తరణ యంత్రాంగంగా మరియు మధ్య ఇప్పటికే ప్రమాణీకరించబడింది అందుబాటులో:

  • 25 + 256 - పంక్తి సంఖ్యకు సూచనతో పునరావృతమయ్యే పంక్తులను భర్తీ చేయడం, అటువంటి చౌకైన కుదింపు పద్ధతి
  • 26 - తరగతి పేరు మరియు కన్స్ట్రక్టర్ ఆర్గ్యుమెంట్‌లతో క్రమీకరించబడిన పెర్ల్ ఆబ్జెక్ట్
  • 27 - రకం పేరు మరియు కన్స్ట్రక్టర్ ఆర్గ్యుమెంట్‌లతో సీరియలైజ్ చేయబడిన భాష-స్వతంత్ర వస్తువు

సరే, నేను TLలో మరియు CBORలో స్ట్రింగ్ మరియు ఆబ్జెక్ట్ ప్యాకింగ్ ప్రారంభించబడిన అదే డేటాను సీరియల్ చేయడానికి ప్రయత్నించాను. ఫలితం మెగాబైట్ నుండి ఎక్కడో CBORకి అనుకూలంగా మారడం ప్రారంభించింది:

cborlen=1039673 tl_len=1095092

కాబట్టి, నిర్ధారణకు: పోల్చదగిన సామర్థ్యంతో సమకాలీకరణ వైఫల్యం లేదా తెలియని ఐడెంటిఫైయర్ సమస్యకు లోబడి ఉండని గణనీయంగా సరళమైన ఫార్మాట్‌లు ఉన్నాయి.

వేగవంతమైన కనెక్షన్ ఏర్పాటు. దీని అర్థం రీకనెక్షన్ తర్వాత సున్నా RTT (కీ ఇప్పటికే ఒకసారి రూపొందించబడినప్పుడు) - మొదటి MTProto సందేశం నుండి వర్తిస్తుంది, కానీ కొన్ని రిజర్వేషన్‌లతో - అదే ఉప్పును కొట్టండి, సెషన్ కుళ్ళిపోదు, మొదలైనవి. బదులుగా TLS మాకు ఏమి అందిస్తుంది? అంశంపై కోట్:

TLS, TLS సెషన్ టిక్కెట్‌లలో PFSని ఉపయోగిస్తున్నప్పుడు (RFC 5077) కీలను తిరిగి చర్చలు చేయకుండా మరియు సర్వర్‌లో కీలక సమాచారాన్ని నిల్వ చేయకుండా ఎన్‌క్రిప్టెడ్ సెషన్‌ను తిరిగి ప్రారంభించడానికి. మొదటి కనెక్షన్‌ని తెరిచి, కీలను సృష్టించేటప్పుడు, సర్వర్ కనెక్షన్ స్థితిని గుప్తీకరిస్తుంది మరియు దానిని క్లయింట్‌కు (సెషన్ టిక్కెట్ రూపంలో) ప్రసారం చేస్తుంది. దీని ప్రకారం, కనెక్షన్ పునఃప్రారంభించబడినప్పుడు, క్లయింట్ సెషన్ కీతో సహా సెషన్ టిక్కెట్‌ను తిరిగి సర్వర్‌కు పంపుతుంది. టిక్కెట్ కూడా తాత్కాలిక కీ (సెషన్ టికెట్ కీ)తో గుప్తీకరించబడింది, ఇది సర్వర్‌లో నిల్వ చేయబడుతుంది మరియు క్లస్టర్డ్ సొల్యూషన్స్‌లో SSLని ప్రాసెస్ చేసే అన్ని ఫ్రంటెండ్ సర్వర్‌లలో పంపిణీ చేయాలి.[10]. అందువల్ల, తాత్కాలిక సర్వర్ కీలు రాజీపడినట్లయితే, సెషన్ టికెట్ పరిచయం PFSని ఉల్లంఘించవచ్చు, ఉదాహరణకు, అవి ఎక్కువ కాలం నిల్వ చేయబడినప్పుడు (OpenSSL, nginx, Apache ప్రోగ్రామ్ యొక్క మొత్తం వ్యవధిలో వాటిని డిఫాల్ట్‌గా నిల్వ చేస్తుంది; ప్రసిద్ధ సైట్‌లు ఉపయోగిస్తాయి చాలా గంటలు, రోజుల వరకు కీ).

ఇక్కడ RTT సున్నా కాదు, మీరు కనీసం ClientHello మరియు ServerHelloని మార్పిడి చేసుకోవాలి, ఆ తర్వాత క్లయింట్ పూర్తయిన దానితో పాటు డేటాను పంపవచ్చు. కానీ ఇక్కడ మనం గుర్తుంచుకోవాలి, కొత్తగా తెరిచిన కనెక్షన్‌ల సమూహంతో మనకు వెబ్ లేదు, కానీ ఒక మెసెంజర్, దీని కనెక్షన్ తరచుగా ఒకటి మరియు ఎక్కువ లేదా తక్కువ దీర్ఘకాలం ఉంటుంది, వెబ్ పేజీలకు సాపేక్షంగా తక్కువ అభ్యర్థనలు - ప్రతిదీ మల్టీప్లెక్స్ చేయబడింది. అంతర్గతంగా. అంటే, మేము నిజంగా చెడ్డ సబ్‌వే విభాగాన్ని చూడకపోతే ఇది చాలా ఆమోదయోగ్యమైనది.

ఇంకేమైనా మర్చిపోయారా? వ్యాఖ్యలలో వ్రాయండి.

కొనసాగించటానికి!

ఈ పోస్ట్‌ల శ్రేణి యొక్క రెండవ భాగంలో మేము సాంకేతికత కాదు, సంస్థాగత సమస్యలను పరిశీలిస్తాము - విధానాలు, భావజాలం, ఇంటర్‌ఫేస్, వినియోగదారుల పట్ల వైఖరి మొదలైనవి. అయితే, ఇక్కడ అందించిన సాంకేతిక సమాచారం ఆధారంగా.

మూడవ భాగం సాంకేతిక భాగం / అభివృద్ధి అనుభవాన్ని విశ్లేషించడం కొనసాగుతుంది. మీరు నేర్చుకుంటారు, ముఖ్యంగా:

  • వివిధ రకాల TL రకాలతో కోలాహలం యొక్క కొనసాగింపు
  • ఛానెల్‌లు మరియు సూపర్‌గ్రూప్‌ల గురించి తెలియని విషయాలు
  • డైలాగ్‌లు రోస్టర్ కంటే ఎందుకు అధ్వాన్నంగా ఉన్నాయి
  • సంపూర్ణ vs సాపేక్ష సందేశ చిరునామా గురించి
  • ఫోటో మరియు చిత్రం మధ్య తేడా ఏమిటి
  • ఇటాలిక్ టెక్స్ట్‌తో ఎమోజి ఎలా జోక్యం చేసుకుంటుంది

మరియు ఇతర ఊతకర్రలు! చూస్తూ ఉండండి!

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి