የቴሌግራም ፕሮቶኮል እና ድርጅታዊ አቀራረቦች ትችት። ክፍል 1, ቴክኒካል: ደንበኛን ከባዶ የመጻፍ ልምድ - TL, MT

በቅርብ ጊዜ፣ ቴሌግራም ምን ያህል ጥሩ እንደሆነ፣ የዱሮቭ ወንድሞች ምን ያህል ጎበዝ እና ልምድ ያላቸው የኔትወርክ ስርዓቶችን በመገንባት ላይ እንዳሉ ወዘተ የሚገልጹ ልጥፎች በሀበሬ ላይ ብዙ ጊዜ መታየት ጀምረዋል። በተመሳሳይ ጊዜ፣ በጣም ጥቂት ሰዎች እራሳቸውን በቴክኒካል መሳሪያው ውስጥ ያጠምቁታል - ቢበዛ በJSON ላይ የተመሰረተ ቀላል (እና ከ MTProto በጣም የተለየ) Bot API ይጠቀማሉ እና አብዛኛውን ጊዜ ይቀበላሉ በእምነት ላይ በመልእክተኛው ዙሪያ የሚሽከረከሩ ሁሉም ምስጋናዎች እና PR። ከአንድ ዓመት ተኩል ገደማ በፊት፣ የኤሼሎን መንግሥታዊ ያልሆነ ድርጅት ቫሲሊ (በአጋጣሚ ሆኖ፣ የሐበሬ መለያው ከረቂቁ ጋር ተሰርዟል) የሥራ ባልደረባዬ በፔርል ውስጥ የራሱን የቴሌግራም ደንበኛ ከባዶ መጻፍ ጀመረ፣ በኋላም የእነዚህ መስመሮች ደራሲ ተቀላቀለ። ለምን ፐርል, አንዳንዶች ወዲያውኑ ይጠይቃሉ? ምክንያቱም እንደዚህ ያሉ ፕሮጀክቶች ቀደም ሲል በሌሎች ቋንቋዎች አሉ.እንደ እውነቱ ከሆነ, ይህ አይደለም, ሌላ ቋንቋ የሌለበት ቋንቋ ሊኖር ይችላል. ዝግጁ ቤተ-መጽሐፍት, እና በዚህ መሠረት ደራሲው በሁሉም መንገድ መሄድ አለበት ከመነሻ. ከዚህም በላይ ክሪፕቶግራፊ የመተማመን ጉዳይ ነው, ግን ያረጋግጡ. ለደህንነት ላይ ያነጣጠረ ምርት በቀላሉ በአምራቹ በተሰራ ቤተ-መጽሐፍት ላይ መተማመን እና በጭፍን ማመን አይችሉም (ይሁን እንጂ ይህ የሁለተኛው ክፍል ርዕስ ነው)። በአሁኑ ጊዜ ቤተ መፃህፍቱ በ"አማካይ" ደረጃ በደንብ ይሰራል (ማንኛውንም የኤፒአይ ጥያቄዎችን እንዲያደርጉ ይፈቅድልዎታል)።

ሆኖም፣ በዚህ ተከታታይ ልጥፎች ውስጥ ብዙ ምስጠራ ወይም ሂሳብ አይኖርም። ነገር ግን ሌሎች ብዙ ቴክኒካዊ ዝርዝሮች እና የስነ-ህንፃ ክራንችዎች ይኖራሉ (ከባዶ የማይጽፉ, ግን በማንኛውም ቋንቋ ላይብረሪውን ለሚጠቀሙ ሰዎች ጠቃሚ ነው). ስለዚህ ዋናው ግብ ደንበኛው ከባዶ ተግባራዊ ለማድረግ መሞከር ነበር እንደ ኦፊሴላዊ ሰነዶች. ማለትም ፣የኦፊሴላዊ ደንበኞች ምንጭ ኮድ ተዘግቷል ብለን እናስብ (እንደገና በሁለተኛው ክፍል ይህ እውነት የመሆኑን እውነታ በዝርዝር እንሸፍናለን) ተፈጠረ ስለዚህ) ፣ ግን እንደ ድሮው ዘመን ፣ ለምሳሌ ፣ እንደ RFC ያለ መመዘኛ አለ - በዝርዝሩ ላይ ብቻ ደንበኛን መጻፍ ይቻል ይሆን ፣ “ሳይመለከቱ” ምንጭ ኮድ ፣ ኦፊሴላዊ (ቴሌግራም ዴስክቶፕ ፣ ሞባይል) ወይስ መደበኛ ያልሆነ ቴሌቶን?

ማስታወሻ፡

ሰነድ... አለ፣ አይደል? እውነት ነው?..

ለዚህ ጽሑፍ የማስታወሻ ቁርጥራጮች ባለፈው የበጋ ወቅት መሰብሰብ ጀመሩ. ይህ ሁሉ ጊዜ በይፋዊው ድር ጣቢያ ላይ https://core.telegram.org ሰነዱ እስከ ንብርብር 23 ድረስ ነበር፣ i.e. እ.ኤ.አ. በ 2014 የሆነ ቦታ ላይ ተጣብቋል (ያስታውሱ ፣ ያኔ ሰርጦች እንኳን አልነበሩም?) እርግጥ ነው, በንድፈ ሀሳብ, ይህ በ 2014 ውስጥ በዚያ ጊዜ ተግባራዊነት ያለው ደንበኛን እንድንተገብር መፍቀድ ነበረበት. ነገር ግን በዚህ ሁኔታ ውስጥ እንኳን, ሰነዱ በመጀመሪያ, ያልተሟላ, እና ሁለተኛ, በቦታዎች እራሱን ይቃረናል. ልክ ከአንድ ወር በፊት፣ በሴፕቴምበር 2019 ነበር። በድንገት ሙሉ ለሙሉ የቅርብ ጊዜ ንብርብር 105 በጣቢያው ላይ ትልቅ የሰነድ ማሻሻያ እንደነበረ ታወቀ ፣ አሁን ሁሉም ነገር እንደገና መነበብ እንዳለበት በማስታወሻ። በእርግጥ፣ ብዙ ጽሑፎች ተሻሽለዋል፣ ነገር ግን ብዙዎቹ አልተለወጡም። ስለዚህ, ስለ ሰነዱ ከዚህ በታች ያለውን ትችት ሲያነቡ, ከእነዚህ ነገሮች ውስጥ አንዳንዶቹ ከአሁን በኋላ ጠቃሚ እንዳልሆኑ ማስታወስ አለብዎት, ግን አንዳንዶቹ አሁንም በጣም ጥሩ ናቸው. ከሁሉም በላይ, በዘመናዊው ዓለም ውስጥ 5 አመታት ረጅም ጊዜ ብቻ አይደለም, ግን በጣም ብዙ ነገር. ከእነዚያ ጊዜያት ጀምሮ (በተለይ ከዚያን ጊዜ ጀምሮ የተጣሉ እና የተነቃቁ የጂኦቻት ጣቢያዎችን ከግምት ውስጥ ካላስገቡ) በእቅዱ ውስጥ ያሉት የኤፒአይ ዘዴዎች ብዛት ከመቶ ወደ ሁለት መቶ ሃምሳ በላይ አድጓል!

እንደ ወጣት ደራሲ የት መጀመር?

ከባዶ ቢጽፉም ሆነ ቢጠቀሙ ምንም ለውጥ አያመጣም ፣ ለምሳሌ ፣ ዝግጁ-የተሰሩ ቤተ-መጽሐፍትን ቴሌቶን ለፓይዘን ወይም ማደሊን ለ PHP, በማንኛውም ሁኔታ, መጀመሪያ ያስፈልግዎታል ማመልከቻዎን ያስመዝግቡ - መለኪያዎችን ያግኙ api_id и api_hash (ከ VKontakte ኤፒአይ ጋር የሰሩ ወዲያውኑ ይገነዘባሉ) አገልጋዩ መተግበሪያውን የሚለይበት። ይህ ማድረግ አለባቸው ለህጋዊ ምክንያቶች ያድርጉት፣ ግን ለምን የቤተ-መጻህፍት ደራሲዎች በሁለተኛው ክፍል ማተም እንደማይችሉ የበለጠ እንነጋገራለን። በሙከራ ዋጋዎች ሊረኩ ይችላሉ, ምንም እንኳን በጣም ውስን ቢሆኑም - እውነታው አሁን መመዝገብ ይችላሉ አንድ ብቻ መተግበሪያ፣ ስለዚህ ወደ እሱ በፍጥነት አይቸኩሉ።

አሁን ከቴክኒካል እይታ አንፃር ፣ ከተመዘገቡ በኋላ ስለ ሰነዶች ፣ ፕሮቶኮል ፣ ወዘተ ዝመናዎች ከቴሌግራም ማሳወቂያዎችን መቀበል እንዳለብን ትኩረት ሊሰጠን ይገባል ። ያም ማለት አንድ ሰው ከመርከቦቹ ጋር ያለው ቦታ በቀላሉ እንደተተወ እና ደንበኞችን ማፍራት ከጀመሩት ጋር በተለይም መስራቱን እንደቀጠለ መገመት ይችላል, ምክንያቱም ቀላል ነው። ግን አይሆንም, እንደዚህ አይነት ነገር አልታየም, ምንም መረጃ አልመጣም.

እና ከባዶ ከጻፉ ፣ ከዚያ የተገኙትን መለኪያዎች መጠቀም በእውነቱ በጣም ሩቅ ነው። ቢሆንም https://core.telegram.org/ እና ስለእነሱ በመጀመሪያ በመጀመር ላይ ያናግራቸዋል ፣ በእውነቱ ፣ መጀመሪያ መተግበር አለብዎት MTProto ፕሮቶኮል - ካመንክ ግን አቀማመጥ በ OSI ሞዴል መሰረት ለፕሮቶኮሉ አጠቃላይ መግለጫ በገጹ መጨረሻ ላይ ፣ ከዚያ ሙሉ በሙሉ ከንቱ ነው።

በእርግጥ፣ ከMTProto በፊትም ሆነ በኋላ፣ በአንድ ጊዜ በተለያዩ ደረጃዎች (በስርዓተ ክወናው ከርነል ውስጥ የሚሰሩ የውጭ ኔትወርኮች እንደሚሉት፣ የንብርብር መጣስ እንደሚሉት) ትልቅ፣ የሚያሰቃይ እና አስፈሪ ርዕስ እንቅፋት ይሆናል።

ሁለትዮሽ ተከታታይነት፡ TL (ቋንቋ ዓይነት) እና እቅዱ፣ እና ንብርብሮች፣ እና ሌሎች ብዙ አስፈሪ ቃላት

ይህ ርዕስ, በእውነቱ, የቴሌግራም ችግሮች ቁልፍ ነው. እና ወደ ውስጡ ለመግባት ከሞከሩ ብዙ አስፈሪ ቃላት ይኖራሉ.

ስለዚ፡ ስዕሉ ይኸውን። ይህ ቃል ወደ አእምሮህ ከመጣ እንዲህ በል። JSON እቅድ፣ በትክክል አስበሃል። ግቡ አንድ ነው፡ ሊተላለፍ የሚችል የውሂብ ስብስብን ለመግለጽ አንዳንድ ቋንቋ። መመሳሰል የሚያበቃው እዚህ ላይ ነው። ከገጹ ከሆነ MTProto ፕሮቶኮል, ወይም ከኦፊሴላዊው ደንበኛ ምንጭ ዛፍ, አንዳንድ ንድፎችን ለመክፈት እንሞክራለን, እንደ አንድ ነገር እናያለን:

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

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

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

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

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

---functions---

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

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

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

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

ይህንን ለመጀመሪያ ጊዜ ያየ ሰው የተጻፈውን የተወሰነውን ክፍል ብቻ ሊገነዘበው ይችላል - ደህና ፣ እነዚህ መዋቅሮች ናቸው (ምንም እንኳን ስሙ የት ፣ በግራ ወይም በቀኝ?) ፣ በእነሱ ውስጥ መስኮች አሉ ፣ ከዚህ በኋላ አንድ አይነት ከኮሎን በኋላ ይከተላል ... ምናልባት. እዚህ የማዕዘን ቅንፎች ውስጥ እንደ C++ ያሉ አብነቶች ሊኖሩ ይችላሉ (በእርግጥ፣ እውነታ አይደለም). እና ሁሉም ሌሎች ምልክቶች ማለት ምን ማለት ነው, የጥያቄ ምልክቶች, የቃለ አጋኖ ምልክቶች, መቶኛ, ሃሽ ምልክቶች (እና ግልጽ በሆነ መልኩ በተለያዩ ቦታዎች ላይ የተለያዩ ነገሮች ማለት ነው), አንዳንድ ጊዜ ይገኛሉ እና አንዳንድ ጊዜ አይደሉም, ሄክሳዴሲማል ቁጥሮች - እና ከሁሉም በላይ, ከዚህ እንዴት ማግኘት እንደሚቻል. ትክክለኛው (በአገልጋዩ ውድቅ የማይደረግ) ባይት ዥረት? ሰነዶቹን ማንበብ አለብዎት (አዎ፣ በአቅራቢያው ባለው JSON ስሪት ውስጥ የመርሃግብሩ አገናኞች አሉ - ግን ያ የበለጠ ግልፅ አያደርገውም).

ገጹን ይክፈቱ ሁለትዮሽ ውሂብ ተከታታይ እና በ 4 ኛው ዓመት ውስጥ እንደ ማታን ተመሳሳይ የሆነ ወደ እንጉዳይ እና ልዩ የሂሳብ ትምህርት አስማታዊ ዓለም ውስጥ ይግቡ። ፊደላት፣ ዓይነት፣ እሴት፣ አጣማሪ፣ ተግባራዊ አጣማሪ፣ መደበኛ ቅጽ፣ የተቀናጀ ዓይነት፣ ፖሊሞፈርፊክ ዓይነት... እና ያ ሁሉ የመጀመሪያው ገጽ ብቻ ነው! ቀጥሎ ይጠብቅዎታል የቲኤል ቋንቋምንም እንኳን ቀደም ሲል ቀላል ያልሆነ ጥያቄ እና ምላሽ ምሳሌ ቢይዝም ለተለመዱ ጉዳዮች በጭራሽ መልስ አይሰጥም ፣ ይህ ማለት በሌላ ስምንት ውስጥ ከሩሲያኛ ወደ እንግሊዘኛ የተተረጎመ የሂሳብ ትምህርት እንደገና ማለፍ ያስፈልግዎታል ማለት ነው ። ገጾች!

በተግባራዊ ቋንቋዎች እና አውቶማቲክ ዓይነት ግንዛቤን የሚያውቁ አንባቢዎች በዚህ ቋንቋ ውስጥ ያለውን መግለጫ ቋንቋ ፣ ከምሳሌው ላይ እንኳን ፣ የበለጠ እንደተለመደው ያዩታል ፣ እና ይህ በመሠረቱ በመሠረቱ መጥፎ አይደለም ማለት ይችላሉ። በዚህ ላይ የሚነሱት ተቃውሞዎች፡-

  • አዎ, targetላማ ጥሩ ይመስላል, ግን ወዮላት, እሷ አልተሳካም
  • በሩሲያ ዩኒቨርሲቲዎች ውስጥ ያለው ትምህርት በአይቲ ስፔሻሊስቶች መካከል እንኳን ይለያያል - ሁሉም ሰው ተጓዳኝ ኮርሱን አልወሰደም
  • በመጨረሻም, እንደምናየው, በተግባር ነው አያስፈልግምየተገለፀው የቲኤል እንኳን የተወሰነ ክፍል ብቻ ጥቅም ላይ ስለሚውል ነው።

እንደተባለው ሊዮኔርድ በሰርጡ ላይ #perl ከቴሌግራም ወደ ማትሪክስ በር ለመተግበር የሞከረው በFreeNode IRC አውታረመረብ ውስጥ (የጥቅሱ ትርጉም ከማስታወስ አንጻር ትክክል አይደለም)

አንድ ሰው ለመጀመሪያ ጊዜ ቲዎሪ ለመተየብ የተዋወቀው፣ የተደሰተ እና ከእሱ ጋር ለመጫወት መሞከር የጀመረ ይመስላል፣ በተግባር ያስፈልግ ስለመሆኑ ግድ የለውም።

የአንደኛ ደረጃ ነገር ጥያቄዎችን የማያነሳ ከሆነ ባዶ ዓይነቶችን (int ፣ ረጅም ፣ ወዘተ.) አስፈላጊነት እራስዎን ይመልከቱ - በመጨረሻም በእጅ መተግበር አለባቸው - ለምሳሌ ፣ ከእነሱ ለማግኘት እንሞክር ። ቬክተር. ይኸውም እንደውም ድርድር, የተገኙትን ነገሮች በትክክለኛ ስማቸው ከጠሩ.

ግን በፊት

ኦፊሴላዊውን ሰነድ ለማያነቡ የቲኤል አገባብ ንዑስ ስብስብ አጭር መግለጫ

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++፣ በቲኤልኤል ውስጥ አልተሰጡም።

OOP ካልሆነ ለምን "ገንቢ" እና "ፖሊሞርፊክ"? ደህና ፣ በእውነቱ ፣ አንድ ሰው ስለዚህ ጉዳይ በ OOP ቃላት ማሰብ ቀላል ይሆንለታል - ፖሊሞርፊክ ዓይነት እንደ ረቂቅ ክፍል ፣ እና ገንቢዎች የእሱ ቀጥተኛ የዘር ክፍሎች ናቸው ፣ እና final በበርካታ ቋንቋዎች የቃላት አገባብ. በእርግጥ, በእርግጥ, እዚህ ብቻ ተመሳሳይነት በ OO ፕሮግራሚንግ ቋንቋዎች ከእውነተኛ ከመጠን በላይ ከተጫኑ የግንባታ ዘዴዎች ጋር። እዚህ የመረጃ አወቃቀሮች ብቻ ስለሆኑ ምንም ዘዴዎች የሉም (ምንም እንኳን የተግባሮች እና ዘዴዎች ገለፃ በጭንቅላቱ ላይ ውዥንብር መፍጠር ቢችሉም ፣ ግን ይህ የተለየ ጉዳይ ነው) - ገንቢውን እንደ ዋጋ ማሰብ ይችላሉ ። የትኛው እየተገነባ ነው። የባይት ዥረት ሲያነቡ ይተይቡ።

ይህ እንዴት ይሆናል? ሁልጊዜ 4 ባይት የሚያነብ ዲሴሪያላይዘር እሴቱን ይመለከታል 0xcrc32 - እና ቀጥሎ ምን እንደሚሆን ይገነዘባል field1 ከዓይነት ጋር int፣ ማለትም እ.ኤ.አ. በትክክል 4 ባይት ያነባል, በዚህ ላይ ከመጠን በላይ የሆነ መስክ ከአይነቱ ጋር PolymorType አንብብ። ይመለከታል 0x2crc32 እና ሁለት ተጨማሪ መስኮች እንዳሉ ይገነዘባል, በመጀመሪያ long8 ባይት እናነባለን ማለት ነው። እና ከዚያ እንደገና የተወሳሰበ ዓይነት ፣ እሱም በተመሳሳይ መንገድ የተበላሸ ነው። ለምሳሌ, Type3 እንደ ቅደም ተከተላቸው ሁለት ገንቢዎች በወረዳው ውስጥ ሊገለጹ ይችላሉ ፣ ከዚያ ሁለቱንም መገናኘት አለባቸው 0x12abcd34, ከዚያ በኋላ 4 ተጨማሪ ባይት ማንበብ ያስፈልግዎታል int, ወይም 0x6789cdef, ከዚያ በኋላ ምንም ነገር አይኖርም. ሌላ ማንኛውም ነገር - የተለየ መጣል ያስፈልግዎታል. ለማንኛውም ከዚህ በኋላ 4 ባይት ወደ ማንበብ እንመለሳለን። int ኅዳጎች field_c в constructorTwo በዚህም የኛን አንብበን እንጨርሳለን። PolymorType.

በመጨረሻም, ከተያዙ 0xdeadcrc ለ constructorThree, ከዚያ ሁሉም ነገር ይበልጥ የተወሳሰበ ይሆናል. የመጀመሪያው ሜዳችን ነው። bit_flags_of_what_really_present ከዓይነት ጋር # - በእውነቱ, ይህ ለዓይነቱ ተለዋጭ ስም ብቻ ነው nat"የተፈጥሮ ቁጥር" ማለት ነው። ያም ማለት በእውነቱ, ያልተፈረመ int, በነገራችን ላይ, በእውነተኛ ወረዳዎች ውስጥ ያልተፈረሙ ቁጥሮች ሲከሰቱ ብቸኛው ሁኔታ ነው. ስለዚህ, የሚቀጥለው የጥያቄ ምልክት ያለው ግንባታ ነው, ይህ መስክ ማለት ነው - በሽቦው ላይ የሚኖረው ተጓዳኝ ቢት በተጠቀሰው መስክ ላይ ከተቀመጠ ብቻ ነው (በግምት እንደ ተርነሪ ኦፕሬተር). እንግዲያው, ይህ ትንሽ እንደ ተዘጋጀ እናስብ, ይህም ማለት የበለጠ እንደ መስክ ማንበብ ያስፈልገናል Type, በእኛ ምሳሌ ውስጥ 2 ገንቢዎች አሉት. አንዱ ባዶ ነው (መለያውን ብቻ ያካትታል) ሌላኛው መስክ አለው። ids ከዓይነት ጋር ids:Vector<long>.

ሁለቱም አብነቶች እና አጠቃላይ መግለጫዎች በፕሮስ ወይም ጃቫ ውስጥ ናቸው ብለው ያስቡ ይሆናል። ግን አይደለም. ማለት ይቻላል። ይህ ብቸኛው በእውነተኛ ወረዳዎች ውስጥ የማዕዘን ቅንፎችን የመጠቀም ጉዳይ ፣ እና ለቬክተር ብቻ ጥቅም ላይ ይውላል። በባይት ዥረት ውስጥ, እነዚህ ለቬክተር አይነት እራሱ 4 CRC32 ባይት, ሁልጊዜ ተመሳሳይ, ከዚያም 4 ባይት - የድርድር አካላት ብዛት, እና ከዚያም እነዚህ ንጥረ ነገሮች እራሳቸው ይሆናሉ.

በዚህ እውነታ ላይ ተከታታይነት ሁልጊዜ በ 4 ባይት ቃላት ውስጥ ይከሰታል, ሁሉም ዓይነቶች ብዙ ናቸው - አብሮገነብ ዓይነቶችም ተገልጸዋል. bytes и string ርዝመቱን በእጅ ተከታታይ በማድረግ እና ይህ አሰላለፍ በ 4 - ደህና ፣ መደበኛ እና በአንጻራዊነት ውጤታማ ይመስላል? ምንም እንኳን TL ውጤታማ ሁለትዮሽ ተከታታይ ነው ቢባልም ፣ ግን ከእነሱ ጋር ወደ ገሃነም ፣ ምንም እንኳን ስለማንኛውም ነገር ፣ የቡሊያን እሴቶች እና ነጠላ-ቁምፊ ሕብረቁምፊዎች እንኳን ወደ 4 ባይት ፣ JSON አሁንም የበለጠ ወፍራም ይሆናል? ተመልከት ፣ አላስፈላጊ መስኮች እንኳን በትንሽ ባንዲራዎች ሊዘለሉ ይችላሉ ፣ ሁሉም ነገር በጣም ጥሩ ነው ፣ እና ለወደፊቱም ሊገለጽ ይችላል ፣ ታዲያ ለምን አዲስ አማራጭ መስኮችን በኋላ ላይ ለምን አትጨምሩም?

ግን አይሆንም, የእኔን አጭር መግለጫ ሳይሆን ሙሉውን ሰነድ ካነበቡ እና ስለ አተገባበሩ ያስቡ. በመጀመሪያ ፣ የገንቢው CRC32 የሚሰላው በእቅዱ የጽሑፍ መግለጫው መደበኛ መስመር መሠረት ነው (ተጨማሪ ነጭ ቦታን ያስወግዱ ፣ ወዘተ) - ስለዚህ አዲስ መስክ ከጨመረ ፣ የዓይነት መግለጫው መስመር ይለወጣል ፣ እና ስለሆነም የእሱ CRC32 እና , በዚህም ምክንያት, ተከታታይነት. እና አሮጌው ደንበኛ አዲስ ባንዲራዎች የተቀመጡበት መስክ ከተቀበለ እና ቀጥሎ ምን ማድረግ እንዳለበት አያውቅም?

በሁለተኛ ደረጃ, እናስታውስ CRC32, እሱም እዚህ ላይ በመሠረቱ እንደ የሃሽ ተግባራት ምን አይነት (de) ተከታታይ እየተደረገ እንዳለ በልዩ ሁኔታ ለመወሰን። እዚህ የግጭት ችግር አጋጥሞናል - እና አይሆንም, ዕድሉ በ 232 ውስጥ አንድ አይደለም, ግን በጣም ትልቅ ነው. CRC32 በመገናኛ ቻናል ውስጥ ያሉ ስህተቶችን ለመለየት (እና ለማረም) የተነደፈ እና በዚህ መሰረት ሌሎችን የሚጎዱ ንብረቶችን እንደሚያሻሽል ማን ያስታውሳል? ለምሳሌ ፣ ባይት እንደገና ስለማደራጀት ግድ የለውም፡ CRC32 ን ከሁለት መስመር ካሰሉ በሁለተኛው ውስጥ የመጀመሪያውን 4 ባይት በሚቀጥሉት 4 ባይት ይቀያይራሉ - ተመሳሳይ ይሆናል። የእኛ ግብዓት ከላቲን ፊደላት (እና ትንሽ ሥርዓተ-ነጥብ) የጽሑፍ ሕብረቁምፊዎች ሲሆኑ እና እነዚህ ስሞች በተለይ በዘፈቀደ ካልሆኑ ፣ እንደገና የማደራጀት እድሉ በጣም ይጨምራል።

በነገራችን ላይ እዚያ ያለውን ማን ፈትሸው? በእውነት። CRC32? ከመጀመሪያዎቹ የምንጭ ኮዶች አንዱ (ከዋልትማን በፊትም ቢሆን) እያንዳንዱን ገጸ ባህሪ በቁጥር 239 የሚያባዛ የሃሽ ተግባር ነበረው፣ በነዚህ ሰዎች በጣም የተወደደ፣ ha ha!

በመጨረሻም፣ እሺ፣ የመስክ አይነት ያላቸው ግንበኞች እንዳሉ ተገነዘብን። Vector<int> и Vector<PolymorType> የተለየ CRC32 ይኖረዋል። ስለ የመስመር ላይ አፈጻጸምስ? እና በንድፈ-ሀሳባዊ እይታ ፣ ይህ የዓይነቱ አካል ይሆናል?? የአስር ሺህ ቁጥሮችን አደራደር አሳልፈናል እንበል፣ በደንብ Vector<int> ሁሉም ነገር ግልጽ ነው, ርዝመቱ እና ሌላ 40000 ባይት. ይህ ቢሆንስ? Vector<Type2>, እሱም አንድ መስክ ብቻ ያካትታል int እና በአይነቱ ብቻ ነው - 10000xabcdef0 34 ጊዜ እና ከዚያ 4 ባይት መድገም አለብን? intወይም ቋንቋው ከግንባታው ነፃ ሊያደርገን ይችላል። fixedVec እና ከ 80000 ባይት ይልቅ እንደገና 40000 ብቻ ያስተላልፉ?

ይህ በጭራሽ ስራ ፈት ቲዎሬቲካል ጥያቄ አይደለም - የቡድን ተጠቃሚዎችን ዝርዝር እንደሚቀበሉ አስቡት ፣ እያንዳንዳቸው መታወቂያ ፣ የመጀመሪያ ስም ፣ የአያት ስም - በተንቀሳቃሽ ስልክ ግንኙነት ላይ የተላለፈው የውሂብ መጠን ልዩነት ከፍተኛ ሊሆን ይችላል። ለእኛ ማስታወቂያ የተደረገው የቴሌግራም ተከታታይነት ውጤታማነት በትክክል ነው።

ስለዚህ…

ቬክተር, እሱም ፈጽሞ ያልተለቀቀ

የማጣመጃዎች መግለጫ ገጾችን እና ሌሎችን ለማለፍ ከሞከሩ ፣ ቬክተር (እና ማትሪክስ እንኳን) በመደበኛነት በበርካታ ሉሆች ውስጥ ለማውጣት እየሞከረ መሆኑን ያያሉ። ነገር ግን በመጨረሻ ይረሳሉ, የመጨረሻው ደረጃ ተዘልሏል, እና የቬክተር ፍቺ በቀላሉ ተሰጥቷል, ይህም ገና ከአንድ ዓይነት ጋር ያልታሰረ ነው. ምንድነው ችግሩ? በቋንቋዎች ፕሮግራሚንግ, በተለይም ተግባራዊ, አወቃቀሩን በተደጋጋሚ መግለጽ የተለመደ ነው - ሰነፍ ግምገማ ያለው አዘጋጅ ሁሉንም ነገር ተረድቶ ይሠራል. በቋንቋ የውሂብ ተከታታይነት የሚያስፈልገው ቅልጥፍና ነው፡ በቀላሉ ለመግለጽ በቂ ነው። ዝርዝር፣ ማለትም እ.ኤ.አ. የሁለት አካላት አወቃቀር - የመጀመሪያው የውሂብ አካል ነው ፣ ሁለተኛው ራሱ ተመሳሳይ መዋቅር ወይም ለጅራት ባዶ ቦታ ነው (ጥቅል (cons) በሊፕፕ). ግን ይህ በግልጽ ይጠይቃል እያንዳንዳቸው ኤለመንቱ አይነቱን ለመግለጽ ተጨማሪ 4 ባይት (CRC32 በ TL) ያወጣል። ድርድር እንዲሁ በቀላሉ ሊገለጽ ይችላል። ቋሚ መጠን, ነገር ግን አስቀድሞ ያልታወቀ ርዝመት ያለውን ድርድር ሁኔታ ውስጥ, እኛ እንሰብራለን.

ስለዚህ ቲኤል ቬክተር ማውጣትን ስለማይፈቅድ በጎን በኩል መጨመር ነበረበት. በመጨረሻም ሰነዱ እንዲህ ይላል:

ተከታታይነት ሁልጊዜ ተመሳሳይ ገንቢ "ቬክተር" ይጠቀማል (const 0x1cb5c415 = crc32 ("vector t:Type # [t] = ቬክተር t") በተለዋዋጭ አይነት t ላይ የተመሰረተ አይደለም.

የአማራጭ መለኪያ t ዋጋ ከውጤት አይነት የተገኘ ስለሆነ (ሁልጊዜ ከመጥፋቱ በፊት ይታወቃል) በተከታታይ ውስጥ አልተሳተፈም.

ቀረብ ብለው ይመልከቱ፡- vector {t:Type} # [ t ] = Vector t - ግን የትኛውም ቦታ ይህ ፍቺ ራሱ የመጀመሪያው ቁጥር ከቬክተሩ ርዝመት ጋር እኩል መሆን አለበት አይልም! እና ከየትም አይመጣም. ይህ ሊታወስ የሚገባው እና በእጆችዎ መተግበር ያለበት የተሰጠ ነው። በሌላ ቦታ፣ ሰነዱ ይህ ዓይነቱ እውነት እንዳልሆነ በሐቀኝነት ይጠቅሳል፡-

የቬክተር ቲ ፖሊሞርፊክ pseudotype “አይነት” ነው ፣ እሴቱ የማንኛውም ዓይነት እሴት ቅደም ተከተል ነው ፣ በቦክስ ወይም ባዶ።

... ግን በእሱ ላይ አያተኩርም. በሂሳብ መወጠር (ምናልባትም ከዩኒቨርሲቲ ኮርስ ታውቀዋለህ) መሮጥ ሰልችቶህ ተስፋ ለመቁረጥ ስትወስን እና በተግባር ከሱ ጋር እንዴት መስራት እንደምትችል ስትመለከት በጭንቅላትህ ውስጥ ያለው ስሜት ይህ ከባድ ነው የሚል ነው። በዋናው ላይ የሂሳብ ትምህርት ፣ እሱ በግልፅ የተፈጠረው በቀዝቃዛ ሰዎች (ሁለት የሂሳብ ሊቃውንት - ኤሲኤም አሸናፊ) እንጂ ማንም አይደለም። ግቡ - ለማሳየት - ተሳክቷል.

በነገራችን ላይ ስለ ቁጥሩ. ያንን እናስታውስህ # ተመሳሳይ ቃል ነው። natየተፈጥሮ ቁጥር፡-

ዓይነት መግለጫዎች አሉ (አይነት-ኤክስፕር) እና የቁጥር መግለጫዎች (nat-ኤክስፕር). ሆኖም, እነሱ በተመሳሳይ መንገድ ይገለጻሉ.

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

ነገር ግን በሰዋስው ውስጥ እነሱ በተመሳሳይ መንገድ ተገልጸዋል, ማለትም. ይህ ልዩነት እንደገና መታወስ እና በእጅ መተግበር አለበት።

ደህና፣ አዎ፣ የአብነት ዓይነቶች (vector<int>, vector<User>የጋራ መለያ አላቸው (#1cb5c415), ማለትም እ.ኤ.አ. ጥሪው እንደተገለጸ ካወቁ

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

ከዚያ እርስዎ የሚጠብቁት ቬክተር ብቻ ሳይሆን የተጠቃሚዎችን ቬክተር ነው። የበለጠ በትክክል ፣ ቢቻል ይጠብቁ - በእውነተኛ ኮድ ፣ እያንዳንዱ አካል ፣ ባዶ ዓይነት ካልሆነ ፣ ግንበኛ ይኖረዋል ፣ እና በጥሩ ሁኔታ በትግበራ ​​​​መፈተሽ አስፈላጊ ይሆናል - ግን በዚህ የቬክተር እያንዳንዱ አካል ውስጥ በትክክል ተልከናል። ያንን ዓይነት? አንድ ድርድር በተለያዩ ንጥረ ነገሮች ውስጥ የተለያዩ ዓይነቶችን ሊይዝ የሚችልበት አንዳንድ ዓይነት ፒኤችፒ ቢሆንስ?

በዚህ ጊዜ ማሰብ ይጀምራሉ - እንዲህ ዓይነቱ ቲኤል አስፈላጊ ነው? ምናልባት ለጋሪው የሰው ተከታታይ ፣ ቀድሞውንም በዚያን ጊዜ የነበረውን ፕሮቶቡፍ መጠቀም ይቻል ይሆን? ንድፈ ሃሳቡ ነበር፣ ልምምድን እንመልከት።

በኮድ ውስጥ ያሉ የቲኤል ትግበራዎች

TL የተወለደው ከዱሮቭ ድርሻ ሽያጭ ጋር ከታዋቂ ክስተቶች በፊት እንኳን በ VKontakte ጥልቀት ውስጥ ተወለደ እና (በእርግጥ), የቴሌግራም እድገት ከመጀመሩ በፊት እንኳን. እና በክፍት ምንጭ የመጀመሪያው ትግበራ ምንጭ ኮድ ብዙ አስቂኝ ክራንች ማግኘት ይችላሉ. እና ቋንቋው አሁን በቴሌግራም ውስጥ ካለው የበለጠ ሙሉ በሙሉ እዚያ ተተግብሯል። ለምሳሌ, hashes በእቅዱ ውስጥ ምንም ጥቅም ላይ አይውሉም (ማለትም አብሮ የተሰራ pseudotype (እንደ ቬክተር) የተዛባ ባህሪ ያለው ማለት ነው). ወይም

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

ነገር ግን ለሙላት ስንል የግዙፉን የሃሳብ ዝግመተ ለውጥ ለመከታተል እናስብ።

#define ZHUKOV_BYTES_HACK

#ifdef ZHUKOV_BYTES_HACK

/* dirty hack for Zhukov request */

ወይም ይህ ቆንጆ:

    static const char *reserved_words_polymorhic[] = {

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

      };

ይህ ቁራጭ ስለ እነዚህ አብነቶች ነው፡-

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

ይህ የሃሽማፕ አብነት አይነት ፍቺ እንደ ቬክተር ኦፍ int - አይነት ጥንዶች ነው። በ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 ኮድ

እርግጥ ነው፣ አልጎሪዝም እና ሂሳብን ከሚያውቁ ሰዎች፣ አሆ፣ ኡልማን እንዳነበቡ እና የዲኤስኤል አቀናባሪዎቻቸውን ለመፃፍ ላለፉት አሥርተ ዓመታት በኢንዱስትሪው ውስጥ ተጨባጭ ደረጃ ያላቸውን መሳሪያዎች ያውቃሉ ብለን መጠበቅ እንችላለን፣ አይደል?...

በ ቴሌግራም-ክሊ ቪታሊ ቫልትማን ነው፣ የቲኤልኦ ቅርጸት ከሱ (ክሊ) ወሰኖች ውጭ ካለው ክስተት ለመረዳት እንደሚቻለው የቡድኑ አባል - አሁን ለቲኤል ትንታኔ ቤተ-መጽሐፍት ተመድቧል ለየብቻ።, የእሷ ስሜት ምንድን ነው የቲኤል ተንታኝ? ..

16.12 04:18 ቫሲሊ፡ አንድ ሰው ሌክስ+ያክን ያልተማረ ይመስለኛል።
16.12 04:18 ቫሲሊ: በሌላ መንገድ ልገልጸው አልችልም።
16.12 04:18 ቫሲሊ: ደህና፣ ወይም የተከፈሉት በቪኬ ውስጥ ላለው የመስመሮች ብዛት ነው።
16.12 04:19 Vasily: 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+ መስመሮች፣ ሁለት መደበኛ አገላለጾች + እንደ ቬክተር ያሉ ልዩ ጉዳዮች፣ በእርግጥ በቲኤል አገባብ መሰረት መሆን እንዳለበት በመርሃግብሩ ውስጥ የተገለጸ ቢሆንም እሱን ለመተንተን በዚህ አገባብ ላይ ተመርኩዘዋል... ጥያቄው የሚነሳው ለምንድነው ይህ ሁሉ ተአምር የሆነው?иለማንኛውም በሰነዱ መሰረት ማንም የማይተነተን ከሆነ የበለጠ ተደራራቢ ነው?!

በነገራችን ላይ... ስለ CRC32 ቼክ እንደተነጋገርን አስታውስ? ስለዚህ ፣ በቴሌግራም ዴስክቶፕ ኮድ ጄኔሬተር ውስጥ የተሰላ CRC32 ለእነዚያ ዓይነቶች የማይካተቱ ዝርዝር አለ ። አይመሳሰልም በሥዕላዊ መግለጫው ላይ ከተጠቀሰው ጋር!

ቫሲሊ፣ [18.12/22 49:XNUMX] እና እዚህ እንደዚህ አይነት ቲኤል ያስፈልግ እንደሆነ አስባለሁ።
ከተለዋጭ አተገባበር ጋር መበላሸት ከፈለግኩ የመስመር መግቻዎችን ማስገባት እጀምራለሁ ፣ ከጠቋሚዎቹ ውስጥ ግማሹ ባለብዙ መስመር ትርጓሜዎችን ይሰብራሉ
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

እንደገና, ጥያቄው ስለ% ይቀራል. አልተገለጸም።

Vadim Goncharov, [22.06.18 19:22] እና በ tdesktop ውስጥ?

ቫሲሊ፣ [22.06.18 19:23] ነገር ግን በመደበኛ ሞተሮች ላይ ያለው የቲኤል ተንታኝ ይህንንም አይበሉም።

// parsed manually

TL ውብ ረቂቅ ነው, ማንም ሙሉ በሙሉ አይተገበርም

እና % በእቅዱ ሥሪት ውስጥ የለም።

ግን እዚህ ሰነዱ እራሱን ይቃረናል, ስለዚህ idk

በሰዋስው ውስጥ ተገኝቷል, የፍቺን ቃላትን ለመግለጽ በቀላሉ ሊረሱ ይችላሉ

ሰነዱን በቲኤል ላይ አይተዋል, ያለ ግማሽ ሊትር ሊያውቁት አይችሉም

ሌላ አንባቢ “እሺ እንበል፣ አንድ ነገር ትተቸዋለህ፣ ስለዚህ እንዴት መደረግ እንዳለበት አሳየኝ” ይላል።

ቫሲሊ እንዲህ ስትል መለሰች፡- “ተንታኙን በተመለከተ፣ እኔ እንደዚህ ያሉትን ነገሮች እወዳለሁ።

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

እነዚያ። ቀለል ባለ መንገድ ማስቀመጥ ነው።

በአጠቃላይ፣ በውጤቱም፣ በትክክል ጥቅም ላይ የዋለው የቲኤል ስብስብ ተንታኝ እና ኮድ ጄኔሬተር በግምት ወደ 100 የሰዋስው መስመሮች እና ~ 300 የጄነሬተር መስመሮች ጋር ይጣጣማሉ (ሁሉንም በመቁጠር)። print's የመነጨ ኮድ)፣ በእያንዳንዱ ክፍል ውስጥ ለውስጠ-ግምት አይነት የመረጃ መጋገሪያዎችን ጨምሮ። እያንዳንዱ ፖሊሞፈርፊክ ዓይነት ወደ ባዶ ረቂቅ የመሠረት ክፍል ይቀየራል ፣ እና ገንቢዎች ከእሱ ይወርሳሉ እና የመለያየት እና የማስወገድ ዘዴዎች አሏቸው።

በአይነት ቋንቋ ዓይነቶች እጥረት

ጠንካራ መተየብ ጥሩ ነገር ነው አይደል? አይ፣ ይህ ሆሊቫር አይደለም (ምንም እንኳን ተለዋዋጭ ቋንቋዎችን እመርጣለሁ)፣ ነገር ግን በቲኤል ማዕቀፍ ውስጥ ያለ ልጥፍ ነው። በእሱ ላይ በመመስረት ቋንቋው ሁሉንም ዓይነት ቼኮች ሊሰጠን ይገባል. ደህና ፣ እሺ ፣ ምናልባት እሱ ራሱ አይደለም ፣ ግን አተገባበሩ ፣ ግን ቢያንስ እነሱን መግለጽ አለበት። እና ምን አይነት እድሎች እንፈልጋለን?

በመጀመሪያ ደረጃ, ገደቦች. ፋይሎችን ለመስቀል በሰነዱ ውስጥ እናያለን፡-

የፋይሉ ሁለትዮሽ ይዘት ወደ ክፍሎች ይከፈላል. ሁሉም ክፍሎች ተመሳሳይ መጠን ሊኖራቸው ይገባል ( ክፍል_መጠን ) እና የሚከተሉት ሁኔታዎች መሟላት አለባቸው:

  • part_size % 1024 = 0 (በ1 ኪባ የሚከፋፈል)
  • 524288 % part_size = 0 (512KB በክፍል_መጠን እኩል መከፋፈል አለበት)

የመጨረሻው ክፍል እነዚህን ሁኔታዎች ማሟላት የለበትም፣ መጠኑ ከፓርት_መጠን ያነሰ ከሆነ።

እያንዳንዱ ክፍል ተከታታይ ቁጥር ሊኖረው ይገባል. ፋይል_ክፍል, ከ 0 እስከ 2,999 ባለው ዋጋ.

ፋይሉ ከተከፋፈለ በኋላ በአገልጋዩ ላይ ለማስቀመጥ ዘዴ መምረጥ ያስፈልግዎታል. ተጠቀም upload.saveBigFilePart የፋይሉ ሙሉ መጠን ከ 10 ሜባ በላይ ከሆነ እና upload.saveFilePart ለአነስተኛ ፋይሎች.
ከሚከተሉት የውሂብ ግቤት ስህተቶች ውስጥ አንዱ ሊመለስ ይችላል፡-

  • FILE_PARTS_INVALID - ልክ ያልሆነ የክፍሎች ብዛት። እሴቱ በመካከል አይደለም 1..3000

በሥዕላዊ መግለጫው ውስጥ ይህ አለ? ይህ በሆነ መንገድ TLን በመጠቀም ይገለጻል? አይ. ግን ይቅርታ አድርግልኝ፣ የአያት ቱርቦ ፓስካል እንኳን የተገለጹትን አይነቶችን መግለጽ ችሏል። ክልሎች. እና አንድ ተጨማሪ ነገር ያውቅ ነበር, አሁን በተሻለ ሁኔታ ይታወቃል enum - ቋሚ (ትንሽ) የእሴቶች ብዛት መቁጠርን ያካተተ ዓይነት። እንደ C - ቁጥራዊ ባሉ ቋንቋዎች ፣ እስካሁን የተነጋገርነው ስለ ዓይነቶች ብቻ መሆኑን ልብ ይበሉ ቁጥሮች. ግን ደግሞ ድርድር፣ ሕብረቁምፊዎችም አሉ... ለምሳሌ፣ ይህ ሕብረቁምፊ ስልክ ቁጥር ብቻ ሊይዝ እንደሚችል ቢገልጽ ጥሩ ይሆናል፣ አይደል?

ከእነዚህ ውስጥ አንዳቸውም በቲኤልኤል ውስጥ የሉም። ግን ለምሳሌ በJSON Schema ውስጥ አለ። እና ሌላ ሰው ስለ 512 ኪባ መከፋፈል ሊከራከር ከቻለ ፣ ይህ አሁንም በኮድ ውስጥ መፈተሽ አለበት ፣ ከዚያ ደንበኛው በቀላሉ ያረጋግጡ ። አልቻለም ቁጥር ከክልል ውጪ ላክ 1..3000 (እና ተጓዳኝ ስህተቱ ሊነሳ አይችልም) ይቻል ነበር ፣ ትክክል? ..

በነገራችን ላይ ስለ ስህተቶች እና የመመለሻ ዋጋዎች. ከቲኤልኤል ጋር የሰሩትም እንኳ ዓይኖቻቸውን ያደበዝዛሉ - ወዲያውኑ ለእኛ አልገባንም። አያንዳንዱ በቲኤል ውስጥ ያለ ተግባር የተገለጸውን የመመለሻ አይነት ብቻ ሳይሆን ስህተትንም ሊመልስ ይችላል። ነገር ግን ይህ በምንም መልኩ 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 አይነት ያስፈልግዎታል. ጥምር ፍንዳታ. ስለዚህ፣ የቲኤል ቲዎሪ ክሪስታል ንፅህና እንደገና በሲሪያላይዜሽን ከባድ እውነታ በተጣለ ብረት አህያ ላይ ተሰበረ።

በተጨማሪም በአንዳንድ ቦታዎች እነዚህ ሰዎች ራሳቸው የየራሳቸውን የአጻጻፍ ስልት ይጥሳሉ. ለምሳሌ, በ 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 ነው። ሰነዱ ስለ ልዩ የቲኤል ባህሪ ይነግረናል፡-

ደንበኛ ንብርብር 2ን የሚደግፍ ከሆነ የሚከተለው ገንቢ ጥቅም ላይ መዋል አለበት፡-

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

በተግባር ይህ ማለት ከእያንዳንዱ የኤፒአይ ጥሪ በፊት ኢንቲ ከዋጋው ጋር ማለት ነው። 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 ውስጥ መጠቅለል አለባቸው። አገልጋዩ ዝመናዎችን አያጠቃልልም፤ ምላሾችን እና ዝመናዎችን ለመጠቅለል ምንም መዋቅር የለም።

እነዚያ። ደንበኛው ማሻሻያዎችን የሚፈልግበትን ንብርብር መግለጽ አይችልም

Vadim Goncharov, [16.07.18 14:02] InvokeWithLayer በመርህ ደረጃ ክራንች አይደለም?

Vasily, [16.07.18 14:02] ይህ ብቸኛው መንገድ ነው

Vadim Goncharov, [16.07.18 14:02] ይህም በመሠረቱ በክፍለ ጊዜው መጀመሪያ ላይ በንብርብሩ ላይ መስማማት አለበት.

በነገራችን ላይ የደንበኛ ማሽቆልቆል አልተሰጠም

ዝማኔዎች፣ ማለትም ዓይነት Updates በእቅዱ ውስጥ ፣ ይህ አገልጋዩ ለደንበኛው የሚልከው ለኤፒአይ ጥያቄ ምላሽ ሳይሆን ፣ አንድ ክስተት ሲከሰት ለብቻው ነው። ይህ በሌላ ጽሑፍ ውስጥ የሚብራራ ውስብስብ ርዕስ ነው, አሁን ግን ደንበኛው ከመስመር ውጭ ቢሆንም አገልጋዩ ዝመናዎችን እንደሚያስቀምጥ ማወቅ አስፈላጊ ነው.

ስለዚህ, ለመጠቅለል ፈቃደኛ ካልሆኑ እያንዳንዳቸው እሽግ ስሪቱን ለማመልከት ፣ ይህ ምክንያታዊ በሆነ መንገድ ወደሚከተሉት ሊሆኑ የሚችሉ ችግሮች ይመራል ።

  • ደንበኛው የትኛውን ስሪት እንደሚደግፍ ከማሳወቁ በፊት አገልጋዩ ማሻሻያዎችን ለደንበኛው ይልካል
  • ደንበኛውን ካሻሻልኩ በኋላ ምን ማድረግ አለብኝ?
  • ማን ዋስትናዎችበሂደቱ ወቅት አገልጋዩ ሾለ ንብርብር ቁጥር ያለው አስተያየት አይቀየርም?

ይህ በንድፈ ሃሳባዊ መላምት ብቻ ነው ብለው ያስባሉ ፣ እና በተግባር ይህ ሊሆን አይችልም ፣ ምክንያቱም አገልጋዩ በትክክል ስለተጻፈ (ቢያንስ በጥሩ ሁኔታ የተሞከረ ነው)? ሃ! ምንም ቢሆን!

በነሀሴ ወር የገባንበት ሁኔታ ይህ ነው። በነሀሴ 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 (በበርካታ ሊኑክስ ስርጭቶች የሚቀርብ ስሪት) እናስጀምረዋለን፣ ወደ ልዩ መዝገብ ይጽፋል፡ MTP ያልተጠበቀ አይነት መታወቂያ #b5223b0f በMTMessageMedia ውስጥ ይነበባል…

የቴሌግራም ፕሮቶኮል እና ድርጅታዊ አቀራረቦች ትችት። ክፍል 1, ቴክኒካል: ደንበኛን ከባዶ የመጻፍ ልምድ - TL, MT

ጎግል ቀደም ሲል ይፋ ካልሆኑ ደንበኞች በአንዱ ላይ ተመሳሳይ ችግር እንደተፈጠረ አሳይቷል ፣ ግን ከዚያ የስሪት ቁጥሮች እና ፣ በዚህ መሠረት ፣ ግምቶቹ የተለያዩ ነበሩ…

ታዲያ ምን እናድርግ? እኔ እና ቫሲሊ ተለያየን: ወረዳውን ወደ 91 ለማዘመን ሞክሯል, ጥቂት ቀናትን ለመጠበቅ እና በ 73 ላይ ለመሞከር ወሰንኩኝ. ሁለቱም ዘዴዎች ሠርተዋል, ነገር ግን ተጨባጭ ስለሆኑ ምን ያህል ወደ ላይ ወይም ወደ ታች እንደሚፈልጉ ምንም ግንዛቤ የለም. ለመዝለል ወይም ለምን ያህል ጊዜ መጠበቅ አለብዎት.

በኋላ ሁኔታውን እንደገና ማባዛት ቻልኩ-ደንበኛውን አስጀምረናል, አጥፋው, ወረዳውን ወደ ሌላ ንብርብር እንሰበስባለን, እንደገና አስጀምር, ችግሩን እንደገና ያዝ, ወደ ቀዳሚው ተመለስ - ኦፕ, ምንም አይነት የወረዳ መቀያየር እና ደንበኛው እንደገና ይጀምራል. ጥቂት ደቂቃዎች ይረዳሉ. ከተለያዩ ንብርብሮች የተዋሃዱ የውሂብ አወቃቀሮችን ይቀበላሉ.

ማብራሪያ? ከተለያዩ የተዘዋዋሪ ምልክቶች እንደሚገምቱት አገልጋዩ በተለያዩ ማሽኖች ላይ የተለያዩ አይነት ብዙ ሂደቶችን ያቀፈ ነው። ምናልባትም ለ“ማቋረጫ” ተጠያቂ የሆነው አገልጋይ አለቆቹ የሰጡትን ወረፋ ውስጥ አስገብተው በትውልዱ ጊዜ በነበረው እቅድ ውስጥ ሰጡት። እናም ይህ ወረፋ "የበሰበሰ" እስኪሆን ድረስ ምንም ማድረግ አይቻልም.

ምናልባት ... ግን ይህ በጣም አስፈሪ ክራንች ነው?!.. አይደለም, ስለ እብድ ሀሳቦች ከማሰብዎ በፊት, ኦፊሴላዊ ደንበኞችን ኮድ እንይ. በአንድሮይድ ስሪት ውስጥ ምንም አይነት የቲኤል ተንታኝ አላገኘንም፣ ነገር ግን ከባድ ፋይል (ጂትህብ ሊነካው ፈቃደኛ አይደለም) በ(de) ተከታታይነት አግኝተናል። የኮድ ቅንጥቦች እነኚሁና፡

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;

ይህ አስተያየት “በእጅ የተፈጠረ” የዚህ ፋይል ክፍል ብቻ በእጅ የተጻፈ መሆኑን ይጠቁማል (ሙሉውን የጥገና ቅዠት መገመት ትችላላችሁ?)፣ የተቀረው ደግሞ በማሽን የተፈጠረ ነው። ሆኖም ግን, ከዚያ ሌላ ጥያቄ ይነሳል - ምንጮቹ ይገኛሉ ሙሉ በሙሉ አይደለም (a la GPL blobs በሊኑክስ ከርነል)፣ ግን ይህ አስቀድሞ የሁለተኛው ክፍል ርዕስ ነው።

ግን በቂ ነው። ይህ ሁሉ ተከታታይነት ወደ ሚሰራበት ፕሮቶኮል እንሂድ።

ኤምቲፒሮቶ

ስለዚህ እንክፈተው አጠቃላይ መግለጫ и የፕሮቶኮሉ ዝርዝር መግለጫ እና የምንሰናከልበት የመጀመሪያው ነገር የቃላት አገባብ ነው. እና በሁሉም ነገር በብዛት። በአጠቃላይ ይህ የቴሌግራም የባለቤትነት ባህሪ ይመስላል - ነገሮችን በተለያየ ቦታ መጥራት ወይም የተለያዩ ነገሮችን በአንድ ቃል መጥራት ወይም በተቃራኒው (ለምሳሌ በከፍተኛ ደረጃ ኤፒአይ ውስጥ ተለጣፊ ጥቅል ካዩ ይህ አይደለም) ምን አሰብክ)።

ለምሳሌ፣ “መልእክት” እና “ክፍለ-ጊዜ” ማለት እዚህ ከተለመደው የቴሌግራም ደንበኛ በይነገጽ የተለየ ነገር ነው። ደህና ፣ በመልእክቱ ሁሉም ነገር ግልፅ ነው ፣ በ OOP ቃላት ሊተረጎም ይችላል ፣ ወይም በቀላሉ “ፓኬት” የሚለው ቃል ተብሎ ሊጠራ ይችላል - ይህ ዝቅተኛ ፣ የትራንስፖርት ደረጃ ነው ፣ በይነገጽ ውስጥ ተመሳሳይ መልዕክቶች የሉም ፣ ብዙ የአገልግሎት መልእክቶች አሉ። . ግን ክፍለ-ጊዜው ... ግን መጀመሪያ ነገሮች መጀመሪያ።

የማጓጓዣ ንብርብር

የመጀመሪያው ነገር መጓጓዣ ነው. ስለ 5 አማራጮች ይነግሩናል፡-

  • TCP
  • ዌብሶኬት
  • Websocket በ HTTPS ላይ
  • HTTP
  • ኤችቲቲፒኤስ

ቫሲሊ፣ [15.06.18 15:04] የዩዲፒ ትራንስፖርትም አለ፣ ግን አልተመዘገበም

እና TCP በሦስት ተለዋጮች

የመጀመሪያው በ TCP ላይ ከ UDP ጋር ተመሳሳይ ነው, እያንዳንዱ እሽግ ተከታታይ ቁጥር እና ክሬዲት ያካትታል
በጋሪ ላይ ሰነዶችን ማንበብ ለምን ያማል?

ደህና, አሁን አለ TCP ቀድሞውኑ በ 4 ተለዋጮች ውስጥ:

  • ታግ .ል
  • መካከለኛ
  • የታሸገ መካከለኛ
  • ሙሉ

ደህና፣ እሺ፣ የታሸገ መካከለኛ ለ MTProxy፣ ይህ ከጊዜ በኋላ በታዋቂ ክስተቶች ምክንያት ታክሏል። ግን ለምን ሁለት ተጨማሪ ስሪቶች (በአጠቃላይ ሶስት) በአንድ ማግኘት ሲችሉ? አራቱም የሚለያዩት የዋናውን MTProto ርዝማኔ እና ጭነት እንዴት ማቀናበር እንደሚቻል ብቻ ነው፣ ይህም የበለጠ ይብራራል፡

  • በአብሪጅድ ውስጥ 1 ወይም 4 ባይት ነው ፣ ግን 0xef አይደለም ፣ ከዚያ አካል
  • በመካከለኛው ይህ 4 ባይት ርዝመት እና መስክ ነው, እና ደንበኛው ለመጀመሪያ ጊዜ መላክ አለበት 0xeeeeeeee መካከለኛ መሆኑን ለማመልከት
  • ሙሉ በጣም ሹሾ የሚያስይዝ፣ ከኔትወርክ ሰሪ እይታ አንጻር፡ ርዝመት፣ ተከታታይ ቁጥር እና ዋናው MTProto፣ አካል፣ CRC32 አይደለም። አዎ፣ ይህ ሁሉ በTCP አናት ላይ ነው። ተከታታይ ባይት ዥረት በሚመስል መልኩ አስተማማኝ መጓጓዣን ይሰጠናል፤ ምንም አይነት ቅደም ተከተሎች አያስፈልጉም በተለይም ቼኮች። እሺ፣ አሁን አንድ ሰው TCP ባለ 16-ቢት ቼክሰም እንዳለው ይቃወመኛል፣ ስለዚህ የውሂብ መበላሸት ይከሰታል። በጣም ጥሩ፣ ነገር ግን ከ16 ባይት በላይ የሆነ ሃሽ ያለው ክሪፕቶግራፊክ ፕሮቶኮል አለን፣ እነዚህ ሁሉ ስህተቶች - እና የበለጠ - በከፍተኛ ደረጃ በSHA አለመመጣጠን ይያዛሉ። በዚህ ላይ በCRC32 ምንም ነጥብ የለም።

አንድ ባይት ርዝማኔ የሚቻልበትን አብሪድድ ከ Intermediate ጋር እናወዳድር፣ ይህም “ባለ 4-ባይት ዳታ አሰላለፍ ቢያስፈልግ” ከንቱ ነው። ምን፣ የቴሌግራም ፕሮግራም አድራጊዎች ብቃት የሌላቸው ከመሆናቸው የተነሳ መረጃን ከሶኬት ወደ aligned buffer ማንበብ አይችሉም ተብሎ ይታመናል? አሁንም ይህንን ማድረግ አለቦት, ምክንያቱም ማንበብ ማንኛውንም የባይት ቁጥር ሊመልስልዎ ይችላል (እንዲሁም ፕሮክሲ ሰርቨሮችም አሉ, ለምሳሌ ...). ወይም በሌላ በኩል፣ አሁንም በ16 ባይት ላይ ጠንካራ ንጣፍ ከያዝን አብሪጅድን ለምን እንዘጋዋለን - 3 ባይት ይቆጥቡ። አንዳንድ ጊዜ ?

አንድ ሰው ኒኮላይ ዱሮቭ የኔትወርክ ፕሮቶኮሎችን ጨምሮ ጎማዎችን እንደገና መፈልሰፍ እንደሚወድ ይሰማዋል ፣ ያለ ምንም እውነተኛ ተግባራዊ ፍላጎት።

ሌሎች የመጓጓዣ አማራጮች, ጨምሮ. ዌብ እና MTProxy፣ ጥያቄ ካለ፣ ምናልባት በሌላ ልኡክ ጽሁፍ ላይ አሁን አንመለከትም። ስለዚሁ MTProxy፣ አሁን ብቻ እናስታውስ በ2018 ከተለቀቀ በኋላ አቅራቢዎች በፍጥነት እሱን ማገድ እንደተማሩ፣ ማለፊያ ማገድ, በርቷል የጥቅል መጠን! እና ደግሞ በC ውስጥ የተጻፈው MTProxy አገልጋይ (በድጋሚ በዋልትማን) ከሊኑክስ ዝርዝሮች ጋር ከመጠን በላይ የተሳሰረ መሆኑ ምንም እንኳን ይህ በጭራሽ አያስፈልግም (ፊል ኩሊን ያረጋግጣል) እና በ Go ወይም Node.js ውስጥ ያለው ተመሳሳይ አገልጋይ ከመቶ ባነሰ መስመሮች ውስጥ ተስማሚ።

ነገር ግን ሌሎች ጉዳዮችን ከግምት ውስጥ ካስገባን በኋላ ስለ እነዚህ ሰዎች ቴክኒካዊ እውቀት በክፍል መጨረሻ ላይ መደምደሚያ ላይ እናደርሳለን. ለአሁን፣ ወደ OSI ንብርብር 5 እንሂድ፣ ክፍለ ጊዜ - MTProto ክፍለ ጊዜን ያደረጉበት።

ቁልፎች፣ መልዕክቶች፣ ክፍለ-ጊዜዎች፣ Diffie-Hellman

ሙሉ በሙሉ በትክክል አይደለም እዚያ አስቀምጠውታል... አንድ ክፍለ ጊዜ በንቁ ክፍለ ጊዜዎች ውስጥ በበይነገጹ ላይ ከሚታየው ተመሳሳይ ክፍለ ጊዜ አይደለም። ግን በቅደም ተከተል።

የቴሌግራም ፕሮቶኮል እና ድርጅታዊ አቀራረቦች ትችት። ክፍል 1, ቴክኒካል: ደንበኛን ከባዶ የመጻፍ ልምድ - TL, MT

ስለዚህ ከማጓጓዣው ንብርብር የሚታወቅ ርዝመት ያለው ባይት ሕብረቁምፊ ተቀበልን። ይህ ወይ የተመሰጠረ መልእክት ወይም ግልጽ ጽሑፍ ነው - አሁንም በቁልፍ ስምምነት ደረጃ ላይ ከሆንን እና እያደረግነው ከሆነ። "ቁልፍ" ከሚባሉት ጽንሰ-ሐሳቦች መካከል ስለ የትኛው ነው እየተነጋገርን ያለነው? ይህንን ጉዳይ ለቴሌግራም ቡድን እራሱ እናብራራ (ከጠዋቱ 4 ሰአት ላይ የራሴን ሰነድ ከእንግሊዘኛ በደከመ አእምሮ ስለተረጎምኩ ይቅርታ እጠይቃለሁ ፣ አንዳንድ ሀረጎችን እንደነሱ መተው ቀላል ነበር)

የሚባሉት ሁለት አካላት አሉ። ክፍለ ጊዜ - እያንዳንዱ ክፍለ ጊዜ ከመላው መሣሪያ / ስርዓተ ክወና ጋር በሚመሳሰልበት “በአሁኑ ክፍለ-ጊዜዎች” ስር ባለው ኦፊሴላዊ ደንበኞች UI ውስጥ አንዱ።
ሁለተኛ - MTProto ክፍለ ጊዜ, በውስጡም የመልእክቱ ተከታታይ ቁጥር ያለው (በዝቅተኛ ደረጃ) እና የትኛው ነው በተለያዩ የ TCP ግንኙነቶች መካከል ሊቆይ ይችላል. ብዙ MTProto ክፍለ ጊዜዎችን በተመሳሳይ ጊዜ መጫን ይቻላል, ለምሳሌ, ፋይል ማውረድ ለማፋጠን.

በእነዚህ በሁለቱ መካከል ክፍለ- ጽንሰ-ሐሳብ አለ ፈቃድ. በተበላሸ ሁኔታ, እኛ ማለት እንችላለን የዩአይ ክፍለ ጊዜ ጋር ተመሳሳይ ነው ፈቃድ, ግን ወዮ, ሁሉም ነገር የተወሳሰበ ነው. እስቲ እንመልከት፡-

  • በአዲሱ መሣሪያ ላይ ያለው ተጠቃሚ በመጀመሪያ ያመነጫል auth_key እና ከሂሳቡ ጋር ያገናኘዋል, ለምሳሌ በኤስኤምኤስ - ለዚህ ነው ፈቃድ
  • በመጀመርያው ውስጥ ተከሰተ MTProto ክፍለ ጊዜያለው session_id በራስህ ውስጥ ።
  • በዚህ ደረጃ, ጥምረት ፈቃድ и session_id ተብሎ ሊጠራ ይችላል። ሥልጣን - ይህ ቃል በአንዳንድ ደንበኞች ሰነዶች እና ኮድ ውስጥ ይታያል
  • ከዚያ ደንበኛው መክፈት ይችላል። ብዙ የMTProto ክፍለ-ጊዜዎች በተመሳሳይ ሾር auth_key - ወደ ተመሳሳይ ዲሲ.
  • ከዚያ አንድ ቀን ደንበኛው ፋይሉን ከጥያቄው መጠየቅ ይኖርበታል ሌላ ዲሲ - እና ለዚህ ዲሲ አዲስ ይፈጠራል auth_key !
  • ስርዓቱ አዲስ ተጠቃሚ አለመሆኑን ለማሳወቅ, ግን ተመሳሳይ ነው ፈቃድ (የዩአይ ክፍለ ጊዜ), ደንበኛው የኤፒአይ ጥሪዎችን ይጠቀማል auth.exportAuthorization በቤት ዲሲ auth.importAuthorization በአዲሱ ዲሲ.
  • ሁሉም ነገር አንድ ነው, ብዙዎቹ ክፍት ሊሆኑ ይችላሉ የMTProto ክፍለ-ጊዜዎች (እያንዳንዳቸው ከራሳቸው ጋር session_id) ወደዚህ አዲስ ዲሲ፣ ሾር የእርሱ auth_key.
  • በመጨረሻም፣ ደንበኛው ፍፁም የሆነ ወደፊት ሚስጥራዊነትን ሊፈልግ ይችላል። እያንዳንዱ auth_key ነበር ቋሚ ቁልፍ - በዲሲ - እና ደንበኛው መደወል ይችላል። auth.bindTempAuthKey ለመጠቀም ጊዜያዊ auth_key - እና እንደገና, አንድ ብቻ temp_auth_key በዲሲ፣ ለሁሉም የተለመደ የMTProto ክፍለ-ጊዜዎች ወደዚህ ዲ.ሲ.

ልብ ይበሉ ጨው (እና የወደፊት ጨዎችን) እንዲሁ አንድ ነው auth_key እነዚያ። በሁሉም ሰው መካከል የተጋራ የMTProto ክፍለ-ጊዜዎች ወደ ተመሳሳይ ዲሲ.

"በተለያዩ የTCP ግንኙነቶች" መካከል ምን ማለት ነው? ስለዚህ ይህ ማለት ነው። ልክ እንደዛ አይነት የፍቃድ ኩኪ በድር ጣቢያ ላይ - ከተሰጠ አገልጋይ ጋር ብዙ የ TCP ግንኙነቶችን ይቀጥላል (ይተርፋል)፣ ግን አንድ ቀን መጥፎ ይሆናል። ከኤችቲቲፒ በተለየ መልኩ በMTProto ውስጥ ያሉ መልእክቶች በቅደም ተከተል ተቆጥረው የተረጋገጡ ናቸው፤ ወደ ዋሻው ውስጥ ከገቡ ግንኙነቱ ተቋረጠ - አዲስ ግንኙነት ከፈጠረ በኋላ አገልጋዩ በቀድሞው በዚህ ክፍለ ጊዜ ያላደረሰውን ሁሉ በአክብሮት ይልካል TCP ግንኙነት.

ይሁን እንጂ ከላይ ያለው መረጃ ከብዙ ወራት ምርመራ በኋላ ተጠቃሏል. እስከዚያው ድረስ ደንበኞቻችንን ከባዶ እየተተገበርን ነው? - ወደ መጀመሪያው እንመለስ.

ስለዚህ እናመነጭ auth_key ላይ Diffie-Hellman ስሪቶች ከቴሌግራም. ሰነዶቹን ለመረዳት እንሞክር…

Vasily, [19.06.18 20:05] data_with_hash: = SHA1 (ዳታ) + ዳታ + (ማንኛውም የዘፈቀደ ባይት); ርዝመቱ 255 ባይት እኩል ነው;
ኢንክሪፕትድ_ዳታ፡= RSA(ዳታ_ጋር_ሃሽ፣ አገልጋይ_public_key); ባለ 255 ባይት ረጅም ቁጥር (ትልቅ ኢንዲያን) በሚፈለገው ሞጁል ላይ ወደሚፈለገው ኃይል ይነሳል፣ ውጤቱም እንደ 256-ባይት ቁጥር ተቀምጧል።

አንዳንድ ዶፔ ዲኤች አላቸው

የጤነኛ ሰው ዲኤች አይመስልም።
በ dx ውስጥ ሁለት የህዝብ ቁልፎች የሉም

ደህና ፣ በመጨረሻ ይህ ተስተካክሏል ፣ ግን ቀሪዎች ቀርተዋል - የሥራ ማረጋገጫው በደንበኛው ቁጥሩን ለመለካት ችሏል ። ከ DoS ጥቃቶች የመከላከያ አይነት. እና የ RSA ቁልፍ በአንድ አቅጣጫ አንድ ጊዜ ብቻ ጥቅም ላይ ይውላል, በመሠረቱ ለማመስጠር new_nonce. ነገር ግን ይህ ቀላል የሚመስለው ቀዶ ጥገና ቢሳካም ምን ሊያጋጥሙዎት ይችላሉ?

ቫሲሊ፣ [20.06.18/00/26 XNUMX:XNUMX] እስካሁን የመተግበሪያው ጥያቄ አላገኘሁም

ይህንን ጥያቄ ለDH

እና በትራንስፖርት መትከያው ውስጥ በ 4 ባይት የስህተት ኮድ ምላሽ መስጠት እንደሚችል ይናገራል። ይኼው ነው

ደህና ፣ ነገረኝ -404 ፣ ታዲያ ምን?

እናም እንዲህ አልኩት፡ “በዚህ አይነት የጣት አሻራ በአገልጋይ ቁልፍ ኢንክሪፕት የተደረገውን ቡልሺትህን ያዝ፣ ዲ ኤች እፈልጋለው” እና በጅል 404 መለሰ።

ስለዚህ የአገልጋይ ምላሽ ምን ያስባሉ? ምን ለማድረግ? የሚጠይቅ የለም (በሁለተኛው ክፍል ላይ ግን የበለጠ)።

እዚህ ሁሉም ፍላጎት በመትከያው ላይ ይከናወናል

ሌላ የማደርገው ነገር የለኝም፣ ቁጥሮችን ወደ ፊት እና ወደ ፊት የመቀየር ህልም ነበረኝ።

ሁለት 32 ቢት ቁጥሮች። እንደሌላው ሰው ሸክኳቸው

ግን አይሆንም፣ እነዚህ ሁለቱ እንደ BE መጀመሪያ ወደ መስመር መጨመር አለባቸው

Vadim Goncharov, [20.06.18 15:49] እና በዚህ 404 ምክንያት?

ቫሲሊ፣ [20.06.18 15:49] አዎ!

Vadim Goncharov, [20.06.18 15:50] "ያላገኘው" ምን እንደሆነ አልገባኝም.

ቫሲሊ፣ [20.06.18 15:50] በግምት

እንዲህ ዓይነቱን መበስበስ ወደ ዋና ምክንያቶች ማግኘት አልቻልኩም%)

ስህተት ሪፖርት ማድረግን እንኳን አላቀናበርንም።

Vasily, [20.06.18 20:18] ኦህ፣ MD5ም አለ። አስቀድሞ ሦስት የተለያዩ hashes

የቁልፍ አሻራው በሚከተለው መልኩ ይሰላል፡-

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

SHA1 እና sha2

ስለዚህ እናስቀምጠው auth_key Diffie-Hellmanን በመጠቀም 2048 ቢት መጠን ተቀብለናል። ቀጥሎ ምን አለ? በመቀጠል የዚህ ቁልፍ የታችኛው 1024 ቢት በምንም መንገድ ጥቅም ላይ እንደማይውል እናስተውላለን ... ግን ለአሁኑ ስለዚህ ጉዳይ እናስብ። በዚህ ደረጃ ከአገልጋዩ ጋር የተጋራ ሚስጥር አለን። የቲኤልኤስ ክፍለ ጊዜ አናሎግ ተመስርቷል, ይህም በጣም ውድ የሆነ አሰራር ነው. ግን አገልጋዩ አሁንም ስለማንነታችን ምንም የሚያውቀው ነገር የለም! ገና አይደለም፣ በእውነቱ። ፈቃድ መስጠት. እነዚያ። በአንድ ወቅት በ ICQ እንዳደረጉት ወይም ቢያንስ “መግቢያ-ቁልፍ” እንደ ኤስኤስኤች (ለምሳሌ በአንዳንድ gitlab/github) በ “መግቢያ-ይለፍ ቃል” ካሰቡ። ማንነቱ ያልታወቀ ሰው ደረሰን። አገልጋዩ "እነዚህ ስልክ ቁጥሮች በሌላ ዲሲ አገልግሎት ይሰጣሉ" ቢለንስ? ወይም ደግሞ "ስልክ ቁጥርህ ታግዷል"? እኛ ማድረግ የምንችለው ጥሩው ቁልፉ ጠቃሚ እንደሚሆን እና በዚያን ጊዜ እንደማይበሰብስ ተስፋ በማድረግ ነው.

በነገራችን ላይ, በተያዙ ቦታዎች "ተቀበልነው". ለምሳሌ አገልጋዩን እናምናለን? የውሸት ከሆነስ? ክሪፕቶግራፊክ ፍተሻዎች ያስፈልጉ ነበር፡-

Vasily, [21.06.18 17:53] የሞባይል ደንበኞችን ለቀዳሚነት 2kbit ቁጥር ለማረጋገጥ ይሰጣሉ%)

ግን በጭራሽ ግልጽ አይደለም, nafeijoa

Vasily, [21.06.18 18:02] ሰነዱ ቀላል ካልሆነ ምን ማድረግ እንዳለበት አይገልጽም.

አልተባለም። በዚህ ጉዳይ ላይ ኦፊሴላዊው የአንድሮይድ ደንበኛ ምን እንደሚሰራ እንይ? ሀ ያ ነው። (እና አዎ ፣ ሙሉው ፋይል አስደሳች ነው) - እነሱ እንደሚሉት ፣ ይህንን እዚህ ብቻ እተወዋለሁ።

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

አይ፣ በእርግጥ አሁንም እዚያ አለ። አንዳንድ። የቁጥር ቀዳሚነት ፈተናዎች አሉ፣ ግን በግሌ ከአሁን በኋላ በቂ የሂሳብ እውቀት የለኝም።

እሺ፣ ዋና ቁልፍ አግኝተናል። ለመግባት፣ ማለትም እ.ኤ.አ. ጥያቄዎችን ይላኩ ፣ AES ን በመጠቀም ተጨማሪ ምስጠራን ማከናወን ያስፈልግዎታል።

የመልእክት ቁልፉ እንደ SHA128 የመልእክት አካል 256 መካከለኛ ቢትስ (የክፍለ ጊዜ፣ የመልዕክት መታወቂያ፣ ወዘተ. ጨምሮ)፣ የመጠቅለያ ባይት ጨምሮ፣ ከፍቃድ ቁልፉ በተወሰደ 32 ባይት ተዘጋጅቷል።

ቫሲሊ፣ [22.06.18 14:08] አማካኝ፣ ሴት ዉሻ፣ ቢት

ደረሰ auth_key. ሁሉም። ከነሱ ባሻገር... ከሰነዱ ግልፅ አይደለም። የክፍት ምንጭ ኮድ ለማጥናት ነፃነት ይሰማህ።

MTProto 2.0 ከ12 እስከ 1024 ባይት ፓዲንግ እንደሚያስፈልገው ልብ ይበሉ፣ አሁንም ውጤቱ የመልእክት ርዝመት በ16 ባይት ሊካፈል በሚችል ሁኔታ ላይ ነው።

ስለዚህ ምን ያህል ንጣፍ መጨመር አለብዎት?

እና አዎ፣ ስህተት ከተፈጠረ 404ም አለ።

ማንም ሰው የሰነዶቹን ንድፍ እና ጽሁፍ በጥንቃቄ ካጠና, እዚያ ምንም MAC እንደሌለ አስተውለዋል. እና ያ AES በሌላ በማንኛውም ቦታ ጥቅም ላይ በማይውል በተወሰነ የ IGE ሁነታ ጥቅም ላይ ይውላል. እነሱ በእርግጥ ስለዚህ ጉዳይ በጥያቄዎቻቸው ውስጥ ይጽፋሉ ... እዚህ ፣ ልክ ፣ የመልእክቱ ቁልፍ ራሱ እንዲሁ ዲክሪፕት የተደረገው ዳታ 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 ባሉ ሁነታዎች ተጠናቋል።

እና አሁን ክርክሮቹ ከጋሪው ጎን:

በኒኮላይ ዱሮቭ የሚመራው ከቴሌግራም ጀርባ ያለው ቡድን ስድስት የኤሲኤም ሻምፒዮናዎችን ያቀፈ ሲሆን ግማሾቹ በሒሳብ ፒኤችዲዎች ናቸው። የአሁኑን የMTProto ስሪት ለመልቀቅ ሁለት ዓመት ገደማ ፈጅቷቸዋል።

ያ አስቂኝ ነው። በዝቅተኛ ደረጃ ላይ ሁለት ዓመታት

ወይም tls ብቻ መውሰድ ይችላሉ።

እሺ፣ ምስጠራውን እና ሌሎች ጥቃቅን ነገሮችን ሠርተናል እንበል። በመጨረሻ በቲኤል ውስጥ ተከታታይ ጥያቄዎችን መላክ እና ምላሾቹን ማሰናከል ይቻላል? ስለዚህ ምን እና እንዴት መላክ አለብዎት? እዚህ, ዘዴው እንበል init ግንኙነትምናልባት ይህ ነው?

Vasily, [25.06.18 18:46] ግንኙነት ይጀምራል እና በተጠቃሚው መሳሪያ እና መተግበሪያ ላይ መረጃን ያስቀምጣል።

app_id፣ device_model፣ system_version፣ app_version እና lang_code ይቀበላል።

እና አንዳንድ ጥያቄ

ሰነዶች እንደ ሁልጊዜ. ክፍት ምንጭን ለማጥናት ነፃነት ይሰማህ

በ invokeWithLayer ሁሉም ነገር በግምት ግልጽ ከሆነ ታዲያ እዚህ ምን ችግር አለ? ተለወጠ ፣ አለን እንበል - ደንበኛው ቀድሞውኑ ስለ አገልጋዩ የሚጠይቅ ነገር ነበረው - እኛ ለመላክ የፈለግነው ጥያቄ አለ።

Vasily, [25.06.18 19:13] በኮዱ መሠረት, የመጀመሪያው ጥሪ በዚህ ቆሻሻ ተጠቅልሎበታል, እና ክራፕ እራሱ በ invokewithlayer ተጠቅልሏል.

ለምንድነው initConnection የተለየ ጥሪ ሊሆን ያልቻለው ነገር ግን መጠቅለያ መሆን አለበት? አዎ ፣ እንደ ተለወጠ ፣ በእያንዳንዱ ክፍለ ጊዜ መጀመሪያ ላይ ሁል ጊዜ መደረግ አለበት ፣ እና አንድ ጊዜ አይደለም ፣ እንደ ዋናው ቁልፍ። ግን! ባልተፈቀደ ተጠቃሚ ሊጠራ አይችልም! አሁን ተግባራዊ የሚሆንበት ደረጃ ላይ ደርሰናል። ይሄኛው የሰነድ ገጽ - እና ይነግረናል ...

ከኤፒአይ ዘዴዎች ውስጥ ትንሽ ክፍል ብቻ ላልተፈቀደላቸው ተጠቃሚዎች ይገኛሉ፡-

  • auth.send ኮድ
  • auth.resend ኮድ
  • account.getPassword
  • auth.checkPassword
  • auth.checkPhone
  • auth.ምዝገባ
  • auth.signIn
  • auth.import ፍቃድ
  • help.getConfig
  • help.getNearestDc
  • help.getAppUpdate
  • help.getCdnConfig
  • langpack.getLangPack
  • langpack.getStrings
  • langpack.getDifference
  • langpack.getLanguages
  • langpack.getLanguage

ከእነርሱም የመጀመሪያው፣ auth.sendCodeእና አፒ_ኢድ እና አፒ_ሃሽ የምንልክበት እና ከዚያ በኋላ ኮድ የያዘ ኤስ ኤም ኤስ የምንቀበልበት የመጀመሪያ ጥያቄ አለ። እና እኛ በተሳሳተ ዲሲ ውስጥ ከሆንን (በዚህ ሀገር ውስጥ ያሉ የስልክ ቁጥሮች በሌላ አገልግሎት ይሰጣሉ, ለምሳሌ), ከዚያም የምንፈልገውን የዲሲ ቁጥር ስህተት ይደርስብናል. የትኛውን የአይ ፒ አድራሻ በዲሲ ቁጥር ማገናኘት እንዳለቦት ለማወቅ እርዳን help.getConfig. በአንድ ወቅት 5 ግቤቶች ብቻ ነበሩ, ነገር ግን ከ 2018 ታዋቂ ክስተቶች በኋላ ቁጥሩ በከፍተኛ ሁኔታ ጨምሯል.

አሁን እዚህ ደረጃ ላይ እንደደረስን እናስታውስ በአገልጋዩ ላይ ማንነታቸው ሳይታወቅ። አይፒ አድራሻ ብቻ ማግኘት በጣም ውድ አይደለም? ለምን ይህን እና ሌሎች ክዋኔዎችን ባልተመሰጠረ የ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 ንድፍ ውስጥ ሦስተኛው እሴት ነው

አዎ፣ ከዚያን ጊዜ ጀምሮ፣ በእርግጥ፣ ሰነዱ ተዘምኗል። ምንም እንኳን ብዙም ሳይቆይ እንደገና አግባብነት የሌለው ሊሆን ይችላል. ጀማሪ ገንቢ እንዴት ማወቅ አለበት? ምናልባት ማመልከቻዎን ካስመዘገቡ, ያሳውቁዎታል? ቫሲሊ ይህን አደረገ, ግን ወዮ, ምንም ነገር አልላኩትም (እንደገና, በሁለተኛው ክፍል ውስጥ ስለዚህ ጉዳይ እንነጋገራለን).

... አስቀድመን እንደምንም ወደ ኤፒአይ እንደተንቀሳቀስን አስተውለሃል፣ ማለትም. ወደሚቀጥለው ደረጃ፣ እና በMTProto ርዕስ ውስጥ የሆነ ነገር አምልጦሃል? ምንም አያስደንቅም፡-

ቫሲሊ፣ [28.06.18 02:04] ሚሜ፣ በ e2e ላይ አንዳንድ ስልተ ቀመሮችን እያራገቡ ነው።

Mtproto ለሁለቱም ጎራዎች የምስጠራ ስልተ ቀመሮችን እና ቁልፎችን እንዲሁም ትንሽ የመጠቅለያ መዋቅርን ይገልጻል

ነገር ግን የተለያዩ የቁልል ደረጃዎችን ያለማቋረጥ ያቀላቅላሉ፣ ስለዚህ mtproto የት እንዳበቃ እና ቀጣዩ ደረጃ የጀመረው ሁልጊዜ ግልጽ አይደለም

እንዴት ይደባለቃሉ? ደህና, ለ PFS ተመሳሳይ ጊዜያዊ ቁልፍ ይኸውና, ለምሳሌ (በነገራችን ላይ ቴሌግራም ዴስክቶፕ ይህን ማድረግ አይችልም). የሚከናወነው በኤፒአይ ጥያቄ ነው። auth.bindTempAuthKey፣ ማለትም እ.ኤ.አ. ከላይኛው ደረጃ. ግን በተመሳሳይ ጊዜ በዝቅተኛ ደረጃ ምስጠራ ላይ ጣልቃ ይገባል - ከእሱ በኋላ ፣ ለምሳሌ ፣ እንደገና ማድረግ ያስፈልግዎታል initConnection ወዘተ, ይህ አይደለም እሺ መደበኛ ጥያቄ. ልዩ የሆነው ግን ሜዳው ቢሆንም በዲሲ አንድ ጊዜያዊ ቁልፍ ብቻ ሊኖርዎት ይችላል። auth_key_id በእያንዳንዱ መልእክት ውስጥ ቁልፉን ቢያንስ እያንዳንዱን መልእክት እንዲቀይሩ ይፈቅድልዎታል ፣ እና አገልጋዩ በማንኛውም ጊዜ ጊዜያዊ ቁልፍን “የመርሳት” መብት አለው - ሰነዱ በዚህ ጉዳይ ላይ ምን ማድረግ እንዳለበት አይናገርም… ጥሩ ፣ ለምን አልተቻለም ለወደፊቱ የጨው ስብስብ ብዙ ቁልፎች የሉዎትም እና?

ስለ MTProto ጭብጥ ልብ ሊባል የሚገባው ሌሎች ጥቂት ነገሮች አሉ።

የመልእክት መልእክቶች፣ msg_id፣ msg_seqno፣ ማረጋገጫዎች፣ ፒንግ ወደ ተሳሳተ አቅጣጫ እና ሌሎች ፈሊጣዊ አመለካከቶች

ስለእነሱ ማወቅ ለምን አስፈለገ? ምክንያቱም እነሱ ወደ ከፍተኛ ደረጃ "ይፈሳሉ" እና ከኤፒአይ ጋር ሲሰሩ እነሱን ማወቅ አለብዎት. የ msg_key ፍላጎት የለንም ብለን እናስብ፤ የታችኛው ደረጃ ሁሉንም ነገር ዲክሪፕት አድርጎልናል። ነገር ግን ዲክሪፕት በተደረገው ውሂቡ ውስጥ የሚከተሉት መስኮች አሉን (እንዲሁም የመረጃው ርዝመት ፣ ስለዚህ መከለያው የት እንዳለ እናውቃለን ፣ ግን ያ አስፈላጊ አይደለም)

  • ጨው - int64
  • session_id - int64
  • message_id - int64
  • seq_no - int32

ለመላው ዲሲ አንድ ጨው ብቻ እንዳለ እናስታውስህ። ስለ እሷ ለምን ታውቃለህ? ጥያቄ ስላለ ብቻ አይደለም። get_future_salts, የትኞቹ ክፍተቶች ትክክለኛ እንደሆኑ ይነግርዎታል, ነገር ግን ጨውዎ "የበሰበሰ" ከሆነ, ከዚያም መልእክቱ (ጥያቄ) በቀላሉ ይጠፋል. አገልጋዩ በእርግጥ አዲሱን ጨው በማውጣት ሪፖርት ያደርጋል new_session_created - ግን ከአሮጌው ጋር ፣ ለምሳሌ በሆነ መንገድ እንደገና መላክ አለብዎት። እና ይህ ጉዳይ የመተግበሪያውን አርክቴክቸር ይነካል.

አገልጋዩ ክፍለ ጊዜዎችን ሙሉ በሙሉ እንዲጥል እና በብዙ ምክንያቶች በዚህ መንገድ ምላሽ እንዲሰጥ ተፈቅዶለታል። በእውነቱ፣ ከደንበኛው ወገን የMTProto ክፍለ ጊዜ ምንድነው? እነዚህ ሁለት ቁጥሮች ናቸው session_id и seq_no በዚህ ክፍለ ጊዜ ውስጥ መልዕክቶች. ደህና ፣ እና ዋናው የ TCP ግንኙነት ፣ በእርግጥ። ደንበኛው አሁንም ብዙ ነገሮችን እንዴት እንደሚሰራ አያውቅም እንበል, ግንኙነቱን አቋርጦ እንደገና ተገናኘ. ይህ በፍጥነት ከተከሰተ - የድሮው ክፍለ ጊዜ በአዲሱ TCP ግንኙነት ውስጥ ቀጥሏል, ይጨምሩ seq_no ተጨማሪ. ረዘም ያለ ጊዜ ከወሰደ አገልጋዩ ሊሰርዘው ይችላል, ምክንያቱም በእሱ በኩል ደግሞ ወረፋ ነው, እንዳወቅነው.

ምን መሆን አለበት seq_no? ኦህ ፣ ያ አስቸጋሪ ጥያቄ ነው። ምን ማለት እንደሆነ በትክክል ለመረዳት ሞክር፡-

ከይዘት ጋር የተያያዘ መልእክት

ግልጽ እውቅና የሚያስፈልገው መልእክት። እነዚህ ከኮንቴይነሮች እና ምስጋናዎች በስተቀር ሁሉንም የተጠቃሚ እና ብዙ የአገልግሎት መልዕክቶችን ያካትታሉ።

የመልእክት ቅደም ተከተል ቁጥር (msg_seqno)

ከዚህ መልእክት በፊት በላኪው የተፈጠረ “ከይዘት ጋር የተገናኙ” መልእክቶች በእጥፍ እኩል የሆነ ባለ 32 ቢት ቁጥር እና በመቀጠልም አሁን ያለው መልእክት ከይዘት ጋር የተያያዘ መልእክት. አንድ መያዣ ሁልጊዜ ከጠቅላላው ይዘቱ በኋላ ይፈጠራል; ስለዚህ, የእሱ ተከታታይ ቁጥሩ በውስጡ ካሉት የመልእክቶች ተከታታይ ቁጥሮች ይበልጣል ወይም እኩል ነው.

ይህ ምን ዓይነት ሰርከስ ነው በ 1 ፣ ከዚያም ሌላ በ 2 ጭማሪ?... መጀመሪያ ላይ “ትንሹ ለኤሲኬ በጣም አስፈላጊው ትንሽ ፣ የተቀረው ቁጥር ነው” ማለታቸው እንደሆነ እገምታለሁ ፣ ግን ውጤቱ ተመሳሳይ አይደለም - በተለይም ይወጣል, ሊላክ ይችላል ብዙ ማረጋገጫዎች ተመሳሳይ ናቸው seq_no! እንዴት? ደህና ፣ ለምሳሌ ፣ አገልጋዩ የሆነ ነገር ይልክልናል ፣ ይልካል ፣ እና እኛ እራሳችን ዝም እንላለን ፣ መልዕክቶችን መቀበሉን በሚያረጋግጡ የአገልግሎት መልእክቶች ምላሽ እንሰጣለን ። በዚህ አጋጣሚ፣ የወጪ ማረጋገጫዎቻችን ተመሳሳይ የወጪ ቁጥር ይኖራቸዋል። ከ TCP ጋር በደንብ የሚያውቁ ከሆነ እና ይህ በሆነ መንገድ የዱር ይመስላል ብለው ካሰቡ ፣ ግን በጣም ዱር አይመስልም ፣ ምክንያቱም በ TCP ውስጥ። seq_no አይለወጥም, ግን ማረጋገጫው ይሄዳል seq_no በሌላ በኩል ላስከፋህ እቸኩላለሁ። ማረጋገጫዎች በMTProto ውስጥ ቀርበዋል አይደለም ላይ seq_no, እንደ TCP, ግን በ msg_id !

ምንድነው ይሄ msg_idከእነዚህ መስኮች ውስጥ በጣም አስፈላጊው? ስሙ እንደሚያመለክተው ልዩ መልእክት ለዪ። እሱ እንደ 64-ቢት ቁጥር ይገለጻል ፣ ዝቅተኛዎቹ ቢት እንደገና “አገልጋይ-አገልጋይ አይደለም” አስማት አላቸው ፣ የተቀረው ክፍልፋይ ክፍልን ጨምሮ የዩኒክስ የጊዜ ማህተም ነው ፣ 32 ቢት ወደ ግራ ተለወጠ። እነዚያ። timestamp በሴ (እና በጣም ብዙ ጊዜ ያላቸው መልዕክቶች በአገልጋዩ ውድቅ ይደረጋሉ)። ከዚህ በመነሳት በአጠቃላይ ይህ ለደንበኛው ዓለም አቀፋዊ የሆነ መለያ ነው. ከተሰጠው - እናስታውስ session_id - እኛ ዋስትና ተሰጥቶናል; በምንም አይነት ሁኔታ ለአንድ ክፍለ ጊዜ የታሰበ መልእክት ወደ ሌላ ክፍለ ጊዜ መላክ አይቻልም. ያም ማለት ቀድሞውኑ መኖሩን ያሳያል ሶስት ደረጃ - ክፍለ ጊዜ ፣ ​​የክፍለ-ጊዜ ቁጥር ፣ የመልእክት መታወቂያ። ለምን እንደዚህ አይነት ውስብስብነት, ይህ ምስጢር በጣም ትልቅ ነው.

እና ስለዚህ, msg_id ያስፈልጋል ለ...

RPC: ጥያቄዎች, ምላሾች, ስህተቶች. ማረጋገጫዎች።

እርስዎ እንዳስተዋሉት፣ ምንም እንኳን ምላሾች ቢኖሩትም በሥዕላዊ መግለጫው ውስጥ የትኛውም ልዩ “የ RPC ጥያቄ አድርግ” ዓይነት ወይም ተግባር የለም። ደግሞም ከይዘት ጋር የተያያዙ መልዕክቶች አሉን! ያውና, ማንኛውም መልእክቱ ጥያቄ ሊሆን ይችላል! ወይም ላለመሆን። ከሁሉም በኋላ, እያንዳንዳቸው ናት msg_id. ግን መልሶች አሉ፡-

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

ይህ ለየትኛው መልእክት ምላሽ እንደሆነ የተገለጸው እዚህ ላይ ነው። ስለዚህ ፣ በኤፒአይ ከፍተኛ ደረጃ ፣ የጥያቄዎ ቁጥር ምን እንደነበረ ማስታወስ አለብዎት - ሥራው የማይመሳሰል መሆኑን ማስረዳት አያስፈልግም ፣ እና በተመሳሳይ ጊዜ በሂደት ላይ ያሉ ብዙ ጥያቄዎች ሊኖሩ ይችላሉ ፣ በማንኛውም ቅደም ተከተል መመለስ የሚችሉት መልሶች? በመርህ ደረጃ፣ ከዚህ እና እንደ ሰራተኛ የመሰሉ የስህተት መልእክቶች፣ ከዚህ በስተጀርባ ያለው የስነ-ህንፃ ስራ ሊታወቅ ይችላል፡ ከእርስዎ ጋር የ 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;

ኦህ ፣ አንድ ሰው ይጮኻል ፣ የበለጠ ሰብአዊነት ያለው ቅርጸት እዚህ አለ - መስመር አለ! ጊዜህን ውሰድ. እዚህ የስህተት ዝርዝር, ግን በእርግጥ ሙሉ አይደለም. ከእሱ የምንማረው ኮድ መሆኑን ነው ልክ እንደዛ አይነት የኤችቲቲፒ ስህተቶች (በእርግጥ ፣ የምላሾቹ ትርጓሜዎች አልተከበሩም ፣ በአንዳንድ ቦታዎች በኮዶች መካከል በዘፈቀደ ይሰራጫሉ) እና መስመሩ ይመስላል። CAPITAL_LETTERS_AND_NUMBERS. ለምሳሌ፣ PHONE_NUMBER_OCCUPIED ወይም FILE_PART_Х_MISSING። ደህና ፣ ማለትም ፣ አሁንም ይህንን መስመር ያስፈልግዎታል መተንተን. ለምሳሌ FLOOD_WAIT_3600 አንድ ሰዓት መጠበቅ አለብዎት ማለት ነው, እና PHONE_MIGRATE_5, ይህ ቅድመ ቅጥያ ያለው የስልክ ቁጥር በ 5 ኛው ዲሲ ውስጥ መመዝገብ አለበት. አይነት ቋንቋ አለን አይደል? ከሕብረቁምፊ ክርክር አንፈልግም ፣ መደበኛዎቹ ያደርጉታል ፣ እሺ።

በድጋሚ, ይህ በአገልግሎት መልእክቶች ገጽ ላይ አይደለም, ነገር ግን, በዚህ ፕሮጀክት እንደተለመደው, መረጃው ሊገኝ ይችላል በሌላ የሰነድ ገጽ ላይ. ወይም ጥርጣሬን መጣል. በመጀመሪያ፣ ተመልከት፣ መተየብ/ንብርብር መጣስ - RpcError ውስጥ መክተት ይችላል። RpcResult. ለምን ውጭ አይሆንም? ግምት ውስጥ ያላስገባን ነገር ምንድን ነው?... በዚህ መሠረት ዋስትናው የት አለ? RpcError ውስጥ ሊካተት አይችልም። RpcResult, ግን በቀጥታ ወይም በሌላ ዓይነት ውስጥ መክተት? ... እና ካልቻለ, ለምን በከፍተኛ ደረጃ ላይ አይደለም, ማለትም. ይጎድላል req_msg_id ? ..

ግን ስለ የአገልግሎት መልእክቶች እንቀጥል። ደንበኛው አገልጋዩ ለረጅም ጊዜ እያሰበ እንደሆነ ሊያስብ ይችላል እና ይህን ድንቅ ጥያቄ ያቀርባል፡-

rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;

ለዚህ ጥያቄ ሦስት ሊሆኑ የሚችሉ መልሶች አሉ ፣ እንደገና ከማረጋገጫ ዘዴው ጋር ይጣመራሉ ፣ ምን መሆን እንዳለባቸው ለመረዳት መሞከር (እና አጠቃላይ ማረጋገጫ የማያስፈልጋቸው ዓይነቶች ዝርዝር) ለአንባቢው እንደ የቤት ሥራ ተወስኗል (ማስታወሻ: በ ውስጥ ያለው መረጃ የቴሌግራም ዴስክቶፕ ምንጭ ኮድ አልተጠናቀቀም)።

የመድኃኒት ሱስ፡ የመልእክት ሁኔታዎች

በአጠቃላይ በቲኤል፣ ኤምቲፕሮቶ እና ቴሌግራም ውስጥ ያሉ ብዙ ቦታዎች የግትርነት ስሜት ይተዋሉ፣ ነገር ግን ከጨዋነት፣ በዘዴ እና ሌሎችም ለስላሳ ችሎታ በትህትና ዝም አልነው፣ እናም በውይይቶቹ ውስጥ ያሉትን ጸያፍ ድርጊቶች ሳንሱር አደረግን። ሆኖም, ይህ ቦታОአብዛኛው ገጽ ስለ ነው። ስለ መልዕክቶች መልዕክቶች ከኔትወርክ ፕሮቶኮሎች ጋር ለረጅም ጊዜ ሲሰራ የቆየው እና የተለያየ ደረጃ ያላቸው ብስክሌቶችን በማየቴ ለእኔ እንኳን አስደንጋጭ ነው።

ያለምንም ጉዳት ይጀምራል፣ በማረጋገጫዎች። በመቀጠልም ይነግሩናል።

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... ሌሎች ቁጥሮች የት አሉ ቶሚ?

ሰነዱ እንዲህ ይላል፡-

ዓላማው የስህተት_ኮድ እሴቶች ተቧድነው (ስህተት_ኮድ >> 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_ids ዝርዝር ውስጥ ለእያንዳንዱ መልእክት በትክክል አንድ ባይት የመልእክት ሁኔታን የያዘ ሕብረቁምፊ ነው።

    • 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 መድረሱን በእርግጠኝነት የሚታወቅ ከሆነ፣ አዲሱ መልእክት አልተሰራም (በተመሳሳይ ጊዜ፣ it and orig_message.msg_id እውቅና ያገኙ)። የorig_message.msg_id ዋጋ ከመያዣው የመልዕክት_መታወቂያ ያነሰ መሆን አለበት።

ምን ብለን እንኳን ዝም እንበል msgs_state_info እንደገና ያልተጠናቀቀው ቲኤል ጆሮዎች ተጣብቀዋል (የባይት ቬክተር እንፈልጋለን ፣ እና በታችኛው ሁለት ቢት ውስጥ አንድ ኢንም ነበር ፣ እና በላያቸው ሁለት ቢት ባንዲራዎች ነበሩ)። ነጥቡ የተለየ ነው። ይህ ሁሉ ለምን በተግባር ላይ እንዳለ የሚረዳ አለ? በእውነተኛ ደንበኛ ውስጥ አስፈላጊ? .. በችግር, ነገር ግን አንድ ሰው በማረም ላይ ከተሳተፈ አንዳንድ ጥቅሞችን መገመት ይችላል, እና በይነተገናኝ ሁነታ - አገልጋዩን ምን እና እንዴት እንደሆነ ይጠይቁ. ግን እዚህ ጥያቄዎቹ ተገልጸዋል ደርሶ መልስ.

ስለዚህ እያንዳንዱ አካል መልእክቶችን ማመስጠር እና መላክ ብቻ ሳይሆን ስለራሳቸው ፣ስለሚሰጣቸው ምላሾች ፣ለማይታወቅ ጊዜ መረጃ ማከማቸት አለባቸው። ሰነዱ የእነዚህን ባህሪያት ጊዜ ወይም ተግባራዊነት አይገልጽም። አይደለም. በጣም የሚያስደንቀው ግን በኦፊሴላዊ ደንበኞች ኮድ ውስጥ መጠቀማቸው ነው! በግልጽ እንደሚታየው በህዝባዊ ሰነዶች ውስጥ ያልተካተተ ነገር ተነገራቸው። ከኮዱ ተረዱ ለምን, ከአሁን በኋላ እንደ TL ሁኔታ ቀላል አይደለም - እሱ (በአንፃራዊነት) በምክንያታዊነት የተገለለ አካል አይደለም, ነገር ግን ከመተግበሪያው አርክቴክቸር ጋር የተያያዘ ቁራጭ, ማለትም. የመተግበሪያውን ኮድ ለመረዳት ጉልህ የሆነ ተጨማሪ ጊዜ ይፈልጋል።

ፒንግ እና ጊዜ. ወረፋዎች

ከሁሉም ነገር ፣ ስለ አገልጋዩ አርክቴክቸር (የጥያቄዎች ስርጭት በጀርባዎች ላይ) ግምቶችን ካስታወስን ፣ በጣም አሳዛኝ ነገር ይከተላል - በ TCP ውስጥ ሁሉም የመላኪያ ዋስትናዎች ቢኖሩም (መረጃው ተሰጥቷል ፣ ወይም ስለ ክፍተቱ ይነገራቸዋል ፣ ግን ችግሩ ከመከሰቱ በፊት መረጃው ይላካል) ፣ በ MTProto ውስጥ ያሉ ማረጋገጫዎች - ምንም ዋስትና የለም. አገልጋዩ በቀላሉ መልእክትዎን ሊያጣ ወይም ሊጥለው ይችላል, እና ምንም ማድረግ አይቻልም, የተለያዩ አይነት ክራንችዎችን ብቻ ይጠቀሙ.

እና በመጀመሪያ ደረጃ - የመልእክት ወረፋዎች. ደህና፣ በአንድ ነገር ሁሉም ነገር ገና ከመጀመሪያው ግልፅ ነበር - ያልተረጋገጠ መልእክት መቀመጥ እና መበሳጨት አለበት። እና ከየትኛው ሰዓት በኋላ? እና ጀስተር ያውቀዋል። ምናልባት እነዚያ ሱስ የተጠመዱ የአገልግሎት መልእክቶች ይህንን ችግር በክራንች ሊፈቱ ይችላሉ ፣ በቴሌግራም ዴስክቶፕ ውስጥ ከእነሱ ጋር የሚዛመዱ ወደ 4 የሚጠጉ ወረፋዎች አሉ (ምናልባት ቀደም ሲል እንደተጠቀሰው ፣ ለዚህም ወደ ኮዱ እና ሥነ ሕንፃው በጥልቀት መመርመር ያስፈልግዎታል ፣ በተመሳሳይም ጊዜ ፣ እንደ ናሙና ሊወሰድ እንደማይችል እናውቃለን ፣ ከ MTProto መርሃግብር የተወሰኑ ዓይነቶች ዓይነቶች በእሱ ውስጥ ጥቅም ላይ አይውሉም)።

ይህ ለምን እየሆነ ነው? ምናልባት፣ የአገልጋዩ ፕሮግራም አድራጊዎች በክላስተር ውስጥ ያለውን አስተማማኝነት ማረጋገጥ አልቻሉም፣ ወይም በፊተኛው ሚዛኑ ላይ ቋት ማድረግ እንኳን አልቻሉም፣ እና ይህን ችግር ለደንበኛው አስተላልፈዋል። ከተስፋ መቁረጥ የተነሣ ቫሲሊ አማራጭ አማራጭን ተግባራዊ ለማድረግ ሞክሯል፣ በሁለት ወረፋዎች ብቻ፣ ከTCP ስልተ ቀመሮችን በመጠቀም - RTT ን ወደ አገልጋዩ በመለካት እና የ"መስኮት" መጠንን (በመልእክቶች) በማስተካከል ያልተረጋገጡ ጥያቄዎች ብዛት። ማለትም፣ የአገልጋዩን ጭነት ለመገምገም እንደዚህ ያለ ከባድ ሂዩሪስቲክስ ስንት ጥያቄዎቻችን በአንድ ጊዜ ማኘክ እና እንደማይጠፋ ነው።

ደህና፣ ማለትም፣ ተረድተሃል፣ አይደል? በTCP ላይ በሚሰራ ፕሮቶኮል ላይ TCP ን እንደገና መተግበር ካለብህ፣ ይህ የሚያሳየው በጣም ደካማ ያልሆነ ፕሮቶኮልን ነው።

ኦህ አዎ፣ ለምን ከአንድ በላይ ወረፋ ያስፈልግሃል፣ እና ይህ ለማንኛውም ከከፍተኛ ደረጃ ኤፒአይ ጋር ለሚሰራ ሰው ምን ማለት ነው? ተመልከት፣ ጥያቄ አቅርበሃል፣ ተከታታይ አድርግ፣ ግን ብዙ ጊዜ ወዲያውኑ መላክ አትችልም። ለምን? ምክንያቱም መልሱ ይሆናል msg_id, ይህም ጊዜያዊ ነውаእኔ መለያ ነኝ ፣ ምደባው በተቻለ መጠን ዘግይቶ እንዲራዘም የተደረገው - በእኛ እና በእሱ መካከል ባለው የጊዜ አለመጣጣም ምክንያት አገልጋዩ ውድቅ ካደረገ (በእርግጥ ነው ፣ ጊዜያችንን ከአሁኑ የሚቀይር ክራንች እንሰራለን) ከአገልጋዩ ምላሾች የተሰላ ዴልታ በመጨመር ወደ አገልጋዩ - ኦፊሴላዊ ደንበኞች ይህንን ያደርጉታል ፣ ግን በማቋረጡ ምክንያት ደረቅ እና የተሳሳተ ነው)። ስለዚህ፣ ከቤተ-መጽሐፍት በአገር ውስጥ የተግባር ጥሪ ሲጠይቁ መልእክቱ በሚከተሉት ደረጃዎች ውስጥ ያልፋል።

  1. በአንድ ወረፋ ውስጥ ተኝቷል እና ምስጠራን ይጠብቃል።
  2. ተሾመ msg_id እና መልእክቱ ወደ ሌላ ወረፋ ሄዷል - የሚቻል ማስተላለፍ; ወደ ሶኬት ላክ.
  3. ሀ) አገልጋዩ ለ MsgsAck ምላሽ ሰጠ - መልእክቱ ደርሷል ፣ ከ “ሌላ ወረፋ” እንሰርዘዋለን።
    ለ) ወይም በተቃራኒው ፣ እሱ የሆነ ነገር አልወደደም ፣ ለ badmsg መለሰ - ከ “ሌላ ወረፋ” እንደገና ላክ
    ሐ) ምንም የሚታወቅ ነገር የለም፣ መልእክቱ ከሌላ ወረፋ መማረር አለበት - ግን መቼ እንደሆነ በትክክል አይታወቅም።
  4. አገልጋዩ በመጨረሻ ምላሽ ሰጠ RpcResult - ትክክለኛው ምላሽ (ወይም ስህተት) - ማድረስ ብቻ ሳይሆን ተስተካክሏል.

ምናልባት, ኮንቴይነሮችን መጠቀም ችግሩን በከፊል ሊፈታ ይችላል. በዚህ ጊዜ ብዙ መልእክቶች በአንድ ላይ ተጭነዋል እና አገልጋዩ ለሁሉም በአንድ ጊዜ ማረጋገጫ ሰጥቷል። msg_id. ነገር ግን አንድ ችግር ከተፈጠረ ሙሉ በሙሉ ይህንን ጥቅል ውድቅ ያደርጋል።

እና በዚህ ጊዜ ቴክኒካዊ ያልሆኑ ሀሳቦች ወደ ጨዋታ ይመጣሉ. ከተሞክሮ ፣ ብዙ ክራንች አይተናል ፣ እና በተጨማሪ ፣ አሁን ተጨማሪ የመጥፎ ምክሮችን እና የስነ-ህንፃ ምሳሌዎችን እናያለን - በእንደዚህ ያሉ ሁኔታዎች ውስጥ እንደዚህ ያሉ ውሳኔዎችን ማመን እና ማድረግ ጠቃሚ ነው? ጥያቄው የንግግር ነው (በእርግጥ አይደለም)።

ስለ ምን እያወራን ነው? “ስለ መልእክቶች የመድኃኒት መልእክቶች” በሚለው ርዕስ ላይ አሁንም እንደ “ሞኝ ነሽ ፣ አስደናቂ እቅዳችንን አልገባሽም!” ባሉ ተቃውሞዎች መገመት ትችላላችሁ። (ስለዚህ በመጀመሪያ ሰነዶቹን ይፃፉ ፣ እንደ መደበኛ ሰዎች ፣ በምክንያታዊነት እና በፓኬት ልውውጥ ምሳሌዎች ፣ ከዚያ እንነጋገራለን) ፣ ከዚያ ጊዜ / ጊዜ ማብቂያ ሙሉ በሙሉ ተግባራዊ እና የተለየ ጥያቄ ነው ፣ እዚህ ሁሉም ነገር ለረጅም ጊዜ ይታወቃል። ሰነዱ ስለ ጊዜ ማብቂያዎች ምን ይነግረናል?

አገልጋይ ብዙውን ጊዜ ከደንበኛ መልእክት መቀበሉን (በተለምዶ፣ የ RPC መጠይቅ) የ RPC ምላሽን በመጠቀም ይቀበላል። ምላሹ ብዙ ጊዜ ከመጣ፣ አገልጋዩ መጀመሪያ ደረሰኝ እውቅና ሊልክ ይችላል፣ እና ከተወሰነ ጊዜ በኋላ፣ የ RPC ምላሽ ራሱ።

ደንበኛ ብዙውን ጊዜ ከአገልጋዩ መልእክት መቀበሉን (በተለምዶ የ RPC ምላሽ) ለሚቀጥለው የ RPC መጠይቅ በጣም ዘግይቶ ካልተላለፈ (ከመነጨ ከ60-120 ሰከንድ ደረሰኙ በኋላ ከሆነ) እውቅና ይሰጣል። ከአገልጋዩ የተላከ መልእክት)። ይሁን እንጂ ለረጅም ጊዜ ወደ አገልጋዩ መልእክት ለመላክ ምንም ምክንያት ከሌለ ወይም ከአገልጋዩ ብዙ ያልተቀበሉ መልዕክቶች (ከ 16 በላይ) ካሉ ደንበኛው ራሱን የቻለ እውቅና ይሰጣል.

እኔ ተርጉሜያለሁ: እኛ እራሳችን ምን ያህል እና እንዴት እንደሚያስፈልገን አናውቅም, ስለዚህ እንደዚህ ይሁን ብለን እናስብ.

ስለ ፒንግስ፡-

ፒንግ መልዕክቶች (ፒንግ/PONG)

ping#7abe77ec ping_id:long = Pong;

ምላሽ ብዙውን ጊዜ ወደ ተመሳሳይ ግንኙነት ይመለሳል፡-

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

እነዚህ መልዕክቶች ምስጋና አያስፈልጋቸውም። ፖንግ የሚተላለፈው ለፒንግ ምላሽ ብቻ ሲሆን ፒንግ በሁለቱም በኩል ሊጀመር ይችላል.

የዘገየ የግንኙነት መዘጋት + ፒንግ

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

እንደ ፒንግ ይሰራል። በተጨማሪም ይህ ከደረሰ በኋላ አገልጋዩ የሰዓት ቆጣሪ ይጀምራል ይህም ግንኙነት ዘግይቷል ከሴኮንዶች በኋላ ተመሳሳይ አይነት አዲስ መልእክት ካልደረሰው በስተቀር ሁሉንም የቀድሞ ቆጣሪዎችን በራስ-ሰር ዳግም ያስጀምራል። ደንበኛው እነዚህን ፒንግ በ60 ሰከንድ አንድ ጊዜ ከላከ፣ ለምሳሌ፣ የግንኙነት_delayን ከ75 ሰከንድ ጋር እኩል ሊያቀናብር ይችላል።

አብደሃል?! በ60 ሰከንድ ባቡሩ ወደ ጣቢያው ገብቶ ተሳፋሪዎችን ይወርዳል እና እንደገና በዋሻው ውስጥ ያለው ግንኙነት ይጠፋል። በ 120 ሰከንድ ውስጥ, ሲሰሙት, ወደ ሌላ ይደርሳል, እና ግንኙነቱ ሊቋረጥ ይችላል. ደህና ፣ እግሮቹ ከየት እንደመጡ ግልፅ ነው - “መደወል ሰማሁ ፣ ግን የት እንዳለ አላውቅም” ፣ የናግል አልጎሪዝም እና ለይነተገናኝ ሥራ የታሰበ የ TCP_NODELAY አማራጭ አለ። ግን ፣ ይቅርታ ፣ ነባሪ እሴቱን ያዙ - 200 ሚሊሰከንዶች ተመሳሳይ የሆነ ነገር ለማሳየት እና በተቻለ ጥንድ ፓኬቶች ላይ ለማስቀመጥ ከፈለጉ ለ 5 ሰከንድ ያጥፉት ወይም "ተጠቃሚው እየፃፈ ነው..." የመልእክት ጊዜ ያለፈበት አሁን ነው። ግን ከዚህ በላይ የለም።

እና በመጨረሻም ፒንግ. ማለትም የTCP ግንኙነትን መኖር መፈተሽ ነው። በጣም አስቂኝ ነው ፣ ግን ከ 10 ዓመታት በፊት ስለ ፋኩልቲያችን ዶርም መልእክተኛ አንድ ወሳኝ ጽሑፍ ጻፍኩ - እዚያ ያሉት ደራሲዎች አገልጋዩን ከደንበኛው ወረወሩት ፣ እና በተቃራኒው አይደለም። ግን የ3ኛ አመት ተማሪዎች አንድ ነገር ናቸው አለም አቀፍ ቢሮ ደግሞ ሌላ ነው አይደል?...

በመጀመሪያ, ትንሽ ትምህርታዊ ፕሮግራም. የ TCP ግንኙነት፣ የፓኬት ልውውጥ በሌለበት፣ ለሳምንታት መኖር ይችላል። ይህ እንደ አላማው ጥሩም መጥፎም ነው። ለአገልጋዩ የኤስኤስኤች ግንኙነት ከተከፈተ ጥሩ ነው ከኮምፒዩተር ተነስተህ ራውተርን ዳግም አስነሳው ወደ ቦታህ ብትመለስ - በዚህ አገልጋይ በኩል ያለው ክፍለ ጊዜ አልተቀደደም (ምንም አትተይብም ምንም እሽጎች የሉም) ፣ ምቹ ነው። በአገልጋዩ ላይ በሺዎች የሚቆጠሩ ደንበኞች ካሉ ፣እያንዳንዳቸው ሀብቶችን የሚወስዱ ከሆነ መጥፎ ነው (ሄሎ ፣ ፖስትግሬስ!) ፣ እና የደንበኛው አስተናጋጅ ከረጅም ጊዜ በፊት ዳግም አስነሳ ሊሆን ይችላል - ግን ስለእሱ አናውቅም።

የቻት/IM ሲስተሞች በአንድ ተጨማሪ ምክንያት በሁለተኛው ጉዳይ ውስጥ ይወድቃሉ - የመስመር ላይ ሁኔታዎች። ተጠቃሚው "ከወደቀ" ስለዚህ ጉዳይ ለቃለ-መጠይቁ ማሳወቅ አለብዎት. ያለበለዚያ የጃበር ፈጣሪዎች የሰሩትን ስህተት (እና ለ 20 ዓመታት ያርሙ) ይጨርሳሉ - ተጠቃሚው ግንኙነቱን ተቋረጠ ፣ ግን እሱ መስመር ላይ መሆኑን በማመን ወደ እሱ መልእክት መፃፍ ቀጠለ (ይህም በእነዚህ ውስጥ ሙሉ በሙሉ ጠፍተዋል) ግንኙነቱ ከመጥፋቱ ጥቂት ደቂቃዎች በፊት). አይ፣ TCP_KEEPALIVE አማራጭ፣ ብዙ ሰዎች TCP ቆጣሪዎች እንዴት እንደሚሠሩ ያልተረዱ በዘፈቀደ የሚጥሉት (እንደ አስር ሰኮንዶች ያሉ የዱር እሴቶችን በማዘጋጀት) እዚህ አይጠቅምም - የስርዓተ ክወና ከርነል ብቻ አለመሆኑን ማረጋገጥ አለብዎት። የተጠቃሚው ማሽን ህያው ነው፣ ነገር ግን በመደበኛነት ይሰራል፣ ምላሽ ለመስጠት ይችላል፣ እና አፕሊኬሽኑ ራሱ (መቀዝቀዝ የማይችል ይመስልዎታል? ቴሌግራም ዴስክቶፕ በኡቡንቱ 18.04 ላይ ከአንድ ጊዜ በላይ ቀዘቀዘልኝ)።

ለዚህም ነው ፒንግ ማድረግ ያለብዎት አገልጋይ ደንበኛ, እና በተቃራኒው አይደለም - ደንበኛው ይህን ካደረገ, ግንኙነቱ ከተሰበረ, ፒንግ አይቀርብም, ግቡ አይሳካም.

በቴሌግራም ምን እናያለን? በትክክል ተቃራኒ ነው! እንግዲህ፣ ያ ነው። በመደበኛነት, ሁለቱም ወገኖች እርስ በእርሳቸው ሊጣበቁ ይችላሉ. በተግባር, ደንበኞች ክራንች ይጠቀማሉ ping_delay_disconnect, ይህም የሰዓት ቆጣሪውን በአገልጋዩ ላይ ያዘጋጃል. ደህና, ይቅርታ አድርግልኝ, ያለ ፒንግ ለምን ያህል ጊዜ መኖር እንደሚፈልግ ለመወሰን ደንበኛው የሚወስነው አይደለም. አገልጋዩ በጭነቱ ላይ ተመስርቶ የተሻለ ያውቃል። ግን ፣ በእርግጥ ፣ ሀብቱን ካላስቸገሩ ፣ ከዚያ እርስዎ የእራስዎ ክፉ ፒኖቺዮ ይሆናሉ ፣ እና ክራንች ያደርጋል ...

እንዴትስ መንደፍ ነበረበት?

ከላይ ያሉት እውነታዎች የቴሌግራም/VKontakte ቡድን በኮምፒዩተር ኔትወርኮች ትራንስፖርት (እና ዝቅተኛ) ደረጃ ላይ በጣም ብቃት እንደሌለው እና በሚመለከታቸው ጉዳዮች ላይ ያላቸውን ዝቅተኛ መመዘኛዎች በግልፅ ያሳያሉ ብዬ አምናለሁ።

ለምን በጣም የተወሳሰበ ሆነ እና የቴሌግራም አርክቴክቶች ለመቃወም እንዴት ሊሞክሩ ይችላሉ? ከTCP ግንኙነት የሚተርፍ ክፍለ ጊዜ ለማድረግ መሞከራቸው፣ ማለትም፣ አሁን ያልደረሰው፣ በኋላ እናደርሳለን። ምናልባት የ UDP ትራንስፖርት ለመሥራት ሞክረው ይሆናል፣ ነገር ግን ችግሮች አጋጥሟቸው እና ትተውት (ለዚህም ነው ሰነዱ ባዶ የሆነው - የሚኩራራበት ነገር አልነበረም)። ግን በአጠቃላይ ኔትወርኮች እና በተለይም TCP እንዴት እንደሚሠሩ ፣ በእሱ ላይ ሊተማመኑበት እንደሚችሉ ፣ እና እራስዎ የት እንደሚፈልጉ (እና እንዴት) እና ይህንን ከክሪፕቶግራፊ ጋር ለማጣመር በመሞከር ምክንያት በቂ ግንዛቤ ስለሌለው “ሁለት ወፎች በ አንድ ድንጋይ” ይህ ውጤት ነው።

እንዴት አስፈለገ? በሚለው እውነታ ላይ በመመስረት msg_id የድጋሚ ማጫወት ጥቃቶችን ለመከላከል ከምስጠራው እይታ አንጻር የጊዜ ማህተም አስፈላጊ ነው፣ ልዩ መለያ ተግባርን ከእሱ ጋር ማያያዝ ስህተት ነው። ስለዚህ፣ አሁን ያለውን አርክቴክቸር በመሠረታዊነት ሳይለውጥ (የዝማኔዎች ዥረት ሲፈጠር፣ ይህ ለሌላ የዚህ ተከታታይ ልጥፎች ክፍል ከፍተኛ ደረጃ ያለው የኤፒአይ ርዕስ ነው)፣ አንድ ሰው የሚከተሉትን ማድረግ ይኖርበታል፡-

  1. የ TCP ግንኙነትን ከደንበኛው ጋር የሚይዘው አገልጋይ ኃላፊነቱን ይወስዳል - ከሶኬት ላይ ካነበበ እባክዎን ይቀበሉ ፣ ያስኬዱ ወይም ስህተት ይመልሱ ፣ ምንም ኪሳራ የለም። ከዚያ ማረጋገጫው የመታወቂያዎች ቬክተር አይደለም ፣ ግን በቀላሉ “የመጨረሻው የተቀበለው seq_no” - ቁጥር ብቻ ፣ እንደ TCP (ሁለት ቁጥሮች - የእርስዎ ሴክ እና የተረጋገጠው)። እኛ ሁል ጊዜ በክፍለ-ጊዜው ውስጥ ነን ፣ አይደል?
  2. የድግግሞሽ ጥቃቶችን ለመከላከል የጊዜ ማህተም የተለየ መስክ ይሆናል፣ la nonce። ተረጋግጧል, ነገር ግን ሌላ ምንም ነገር አይነካም. በቂ እና uint32 የእኛ ጨው ቢያንስ በየግማሽ ቀን የሚቀየር ከሆነ 16 ቢት ዝቅተኛ የትዕዛዝ ቢት ኢንቲጀር ለአሁኑ ጊዜ፣ የተቀረውን - ለአንድ ሰከንድ ክፍልፋይ (እንደአሁን) መመደብ እንችላለን።
  3. ተወግዷል msg_id በአጠቃላይ - በጀርባዎች ላይ ጥያቄዎችን ከመለየት አንጻር, በመጀመሪያ, የደንበኛ መታወቂያ, እና ሁለተኛ, የክፍለ ጊዜ መታወቂያ, ያገናኛቸዋል. በዚህ መሠረት እንደ ጥያቄ መለያ አንድ ነገር ብቻ በቂ ነው። seq_no.

ይህ ደግሞ በጣም የተሳካው አማራጭ አይደለም፤ ሙሉ በዘፈቀደ እንደ መለያ ሆኖ ሊያገለግል ይችላል - በነገራችን ላይ መልእክት ሲላክ ይህ ቀድሞውኑ በከፍተኛ ደረጃ ኤፒአይ ውስጥ ይከናወናል። አርክቴክቸርን ከዘመድ ወደ ፍፁምነት ሙሉ ለሙሉ ብንሰራ ይሻላል፣ ​​ግን ይህ ለሌላ ክፍል ርዕስ እንጂ ይህ ልጥፍ አይደለም።

ኤፒአይ?

ታ-ዳም! ስለዚህ ፣ በህመም እና በክራንች በተሞላ መንገድ ላይ በመታገል ፣ በመጨረሻ ማንኛውንም ጥያቄ ወደ አገልጋዩ ለመላክ እና ማንኛውንም መልስ ለመቀበል ፣ እንዲሁም ከአገልጋዩ ዝመናዎችን ለመቀበል ቻልን (ለጥያቄ ምላሽ ሳይሆን ፣ እሱ ራሱ) ። እንደ PUSH ሁሉ ይልካናል፣ ማንም ሰው በዚያ መንገድ ግልጽ ከሆነ)።

ትኩረት, አሁን በአንቀጹ ውስጥ በፐርል ውስጥ ብቸኛው ምሳሌ ይኖራል! (አገባቡን ለማያውቁት፣ የበረከት የመጀመሪያው መከራከሪያ የነገሩን መረጃ አወቃቀር ነው፣ ሁለተኛው ክፍል ደግሞ ነው)

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 ውስጥ ያለው የተለመደ የድር ኤፒአይ የውሂብ መዋቅር ነው፣ ክፍሎች እንዲሁ ከእቃዎች ጋር ከተያያዙ በስተቀር?...

እንግዲህ እንዲህ ሆነ...ምንድን ነው ጓዶቼ?.. ብዙ ጥረት - እና የድር ፕሮግራመሮች ባሉበት ለማረፍ ቆምን። ገና በመጀመር ላይ?... JSON በ HTTPS ላይ ብቻ ቀላል አይሆንም?! በለውጥ ምን አገኘን? ጥረቱ የሚያስቆጭ ነበር?

TL+MTProto ምን እንደሰጠን እና ምን አማራጮች ሊኖሩ እንደሚችሉ እንገምግም። ደህና፣ በጥያቄ ምላሽ ሞዴል ላይ የሚያተኩረው ኤችቲቲፒ መጥፎ ብቃት ነው፣ ግን ቢያንስ በTLS ላይ የሆነ ነገር አለ?

የታመቀ ተከታታይነት. ከJSON ጋር የሚመሳሰል ይህን የውሂብ መዋቅር ስመለከት፣ የእሱ ሁለትዮሽ ስሪቶች እንዳሉ አስታውሳለሁ። MsgPack በበቂ ሁኔታ ሊወጣ የማይችል እንደሆነ ምልክት እናድርገው፣ ግን ለምሳሌ፣ CBOR አለ - በነገራችን ላይ፣ በ ውስጥ የተገለጸው መስፈርት RFC 7049. በመግለጫው ተለይቶ ይታወቃል መለያዎች, እንደ ማስፋፊያ ዘዴ, እና መካከል አስቀድሞ ደረጃውን የጠበቀ ይገኛል፡

  • 25 + 256 - ተደጋጋሚ መስመሮችን ከመስመሩ ቁጥር ጋር በማጣቀስ በመተካት እንደዚህ ያለ ርካሽ የማመቅ ዘዴ
  • 26 - ተከታታይ የፔርል ነገር ከክፍል ስም እና የገንቢ ክርክሮች ጋር
  • 27 - ተከታታይ ቋንቋ-ገለልተኛ ነገር ከአይነት ስም እና ከገንቢ ክርክሮች ጋር

ደህና፣ በቲኤል እና በ CBOR ውስጥ ተመሳሳዩን ውሂብ በሕብረቁምፊ እና በነገር ማሸግ በነቃ ለመደርደር ሞከርኩ። ውጤቱ ከሜጋባይት የሆነ ቦታ ለ CBOR ሞገስ መለዋወጥ ጀመረ፡-

cborlen=1039673 tl_len=1095092

እና ስለዚህ, መደምደሚያለማመሳሰል አለመሳካት ወይም ያልታወቀ ለዪ ችግር የማይጋለጡ ከንጽጽር ቅልጥፍና ጋር በጣም ቀላል የሆኑ ቅርጸቶች አሉ።

ፈጣን ግንኙነት መመስረት. ይህ ማለት እንደገና ከተገናኘ በኋላ (ቁልፉ አንድ ጊዜ ሲፈጠር) ዜሮ RTT ማለት ነው - ከመጀመሪያው MTProto መልእክት ላይ ተፈፃሚነት ይኖረዋል ፣ ግን በአንዳንድ ቦታዎች - ተመሳሳይ ጨው ይምቱ ፣ ክፍለ-ጊዜው የበሰበሰ አይደለም ፣ ወዘተ. TLS በምትኩ ምን ይሰጠናል? በርዕሱ ላይ ጥቅስ፡-

በTLS ውስጥ PFS ሲጠቀሙ፣ TLS የክፍለ ጊዜ ትኬቶች (RFC 5077) ቁልፎቹን እንደገና ሳይደራደሩ እና ቁልፍ መረጃዎችን በአገልጋዩ ላይ ሳያከማቹ ኢንክሪፕት የተደረገውን ክፍለ ጊዜ ለመቀጠል ። የመጀመሪያውን ግንኙነት ሲከፍት እና ቁልፎችን ሲፈጥር, አገልጋዩ የግንኙነት ሁኔታን ኢንክሪፕት አድርጎ ለደንበኛው (በክፍለ ጊዜ ቲኬት መልክ) ያስተላልፋል. በዚህ መሠረት ግንኙነቱ ከቀጠለ ደንበኛው የክፍለ ጊዜ ትኬትን ጨምሮ የክፍለ ጊዜውን ቁልፍ ወደ አገልጋዩ ይልካል። ቲኬቱ በጊዜያዊ ቁልፍ (የክፍለ ጊዜ ትኬት ቁልፍ) የተመሰጠረ ነው፣ እሱም በአገልጋዩ ላይ የተከማቸ እና በሁሉም የፊት ለፊት አገልጋዮች መካከል መሰራጨት ያለበት ኤስኤስኤልን በክላስተር መፍትሄዎች።[10]። ስለዚህ የክፍለ ጊዜ ትኬት ማስተዋወቅ ጊዜያዊ የአገልጋይ ቁልፎች ከተጣሱ PFSን ሊጥስ ይችላል ለምሳሌ ለረጅም ጊዜ ሲቀመጡ (OpenSSL, nginx, Apache በነባሪነት ለፕሮግራሙ ቆይታ ሙሉ ያከማቻሉ, ታዋቂ ጣቢያዎች ይጠቀማሉ. ቁልፉ ለብዙ ሰዓታት, እስከ ቀናት ድረስ).

እዚህ RTT ዜሮ አይደለም፣ ቢያንስ ClientHello እና ServerHello መለዋወጥ ያስፈልግዎታል፣ከዚያ በኋላ ደንበኛው ከFinished ጋር ውሂብ መላክ ይችላል። ግን እዚህ እኛ ድህረ ገጽ እንደሌለን ማስታወስ ያለብን አዲስ የተከፈቱ ግንኙነቶች ስብስብ ያለው መልእክተኛ ነው ፣ ግንኙነቱ ብዙውን ጊዜ አንድ እና ብዙ ወይም ከዚያ ያነሰ ረጅም ጊዜ ያለው ፣ በአንጻራዊነት አጭር የድረ-ገጾች ጥያቄዎች - ሁሉም ነገር ተባዝቷል። ከውስጥ። ማለትም፣ በጣም መጥፎ የምድር ውስጥ ባቡር ክፍል ካላጋጠመን በጣም ተቀባይነት አለው።

ሌላ ነገር ረሳው? በአስተያየቶቹ ውስጥ ይፃፉ.

ይቀጥላል!

በዚህ ተከታታይ ልጥፎች ሁለተኛ ክፍል ውስጥ ቴክኒካዊ ሳይሆን ድርጅታዊ ጉዳዮችን - አቀራረቦችን ፣ ርዕዮተ ዓለምን ፣ በይነገጽን ፣ የተጠቃሚዎችን አመለካከት ፣ ወዘተ እንመለከታለን። ይሁን እንጂ እዚህ በቀረበው ቴክኒካዊ መረጃ ላይ በመመስረት.

ሦስተኛው ክፍል የቴክኒካዊ አካል / የልማት ልምድን መተንተን ይቀጥላል. በተለይ ይማራሉ፡-

  • ከተለያዩ የቲኤል ዓይነቶች ጋር የፓንዲሞኒየም ቀጣይነት
  • ሾለ ሰርጦች እና ሱፐር ቡድኖች ያልታወቁ ነገሮች
  • ንግግሮች ለምን ከሮስተር የበለጠ መጥፎ ናቸው።
  • ሾለ ፍፁም እና አንጻራዊ መልእክት አድራሻ
  • በፎቶ እና በምስል መካከል ያለው ልዩነት ምንድነው?
  • ስሜት ገላጭ ምስሎች በሰያፍ ጽሑፍ ላይ እንዴት ጣልቃ እንደሚገቡ

እና ሌሎች ክራንች! ይከታተሉ!

ምንጭ: hab.com

አስተያየት ያክሉ