2024-11-10 17:37:42 +00:00
|
|
|
|
#import "head.typ" as head : *
|
|
|
|
|
|
|
|
|
|
#show: MyStyle
|
|
|
|
|
|
|
|
|
|
|
2024-12-22 17:18:49 +00:00
|
|
|
|
= KMTP, Sub-KMTP Спецификация
|
2024-11-10 17:37:42 +00:00
|
|
|
|
|
|
|
|
|
== Область применения
|
|
|
|
|
|
|
|
|
|
KMTP это протокол, созданный специально для будущей видеоигры KM (Используется
|
2024-12-22 17:18:49 +00:00
|
|
|
|
в рамках KM project). Он нацелен на замену чрезвычайно раздутого
|
2024-11-10 17:37:42 +00:00
|
|
|
|
протокола http+websocket. KMTP (KM Transport Protocol) это его официальное название,
|
|
|
|
|
однако в самом мире игры KM он известен как STP (Suckless
|
|
|
|
|
Transport Protocol).
|
|
|
|
|
|
|
|
|
|
KMTP должен использоваться поверх надёжного транспортного протокола,
|
|
|
|
|
создающего двунаправленный поток байт,
|
|
|
|
|
такого как TCP, так как даже малейшая ошибка может привести к непредсказуемым последствиям.
|
|
|
|
|
|
|
|
|
|
KMTP применяется когда между двумя общающимися процессами
|
|
|
|
|
выделено отношение "клиент-сервер". KMTP предполагает, что на сервере расположено
|
|
|
|
|
множество файлов (ресурсов) в древовидной структуре, а клиент обращается к ним,
|
|
|
|
|
сообщая какую функцию он хочет произвести над тем или иным ресурсом. После этого
|
|
|
|
|
возможны передача серверу
|
|
|
|
|
потока байт (аргумент функции) и приём от сервера потока байт (результат функции).
|
|
|
|
|
|
|
|
|
|
Очень часто kmtp будет применяться как обёртка для протокола более высокого уровня,
|
|
|
|
|
хотя под это понятие попадает даже содержимое jpeg картинки, скачанной с файлового
|
|
|
|
|
сервера.
|
|
|
|
|
|
2024-12-22 17:18:49 +00:00
|
|
|
|
В начале соединения клиент может предствиться передав "логин" и "пароль".
|
2024-11-10 17:37:42 +00:00
|
|
|
|
|
|
|
|
|
Каналы связи называются
|
|
|
|
|
- client's output / server's output / request channel
|
|
|
|
|
- client's input / servers's output / response channel
|
|
|
|
|
|
|
|
|
|
Ключевым элементом данного протокола является структура байт под названием
|
|
|
|
|
"сообщение". Они бывают двух видов: "запросы" (отправляются клиентом) и
|
|
|
|
|
"ответы" (отправляются сервером). Но есть ещё одно деление: на "мастер-сообщение"
|
|
|
|
|
и "суб-сообщение" (применимое к обоим типам адресанта сообщения).
|
2024-12-22 17:18:49 +00:00
|
|
|
|
Контент каждого канала начинается с мастер-сообщения своего типа.
|
|
|
|
|
Если клиент и сервер договорились сделать "апгрейд" до sub-kmtp, то все дальнейшие
|
|
|
|
|
сообщения будут записаны в формате "суб-сообщений".
|
|
|
|
|
У каждого типа есть свой формат, форматы различаются набором обязательных "полей".
|
|
|
|
|
|
|
|
|
|
Каждый канал содержит только мастер-сообщение (соответсвующего типа) и ничего более.
|
|
|
|
|
Поток суб-сообений это часть местер сообщения. Естесственно, поток суб-сообщений
|
|
|
|
|
будет присутсвовать только когда был произведён апгрейд до sub-kmtp.
|
|
|
|
|
В этом случае сначала идёт мастер-заголовок сообщения, а всё остальное (та часть
|
|
|
|
|
сообщения, называющаяся кладом) - это sub-kmtp. Вместо него, конечно же, мог бы быть
|
|
|
|
|
совсем другой клад мастер сообщения.
|
2024-11-10 17:37:42 +00:00
|
|
|
|
|
|
|
|
|
Сообщения содержат заголовок, чей формат полность определён и тело, называемое "кладом".
|
2024-12-22 17:18:49 +00:00
|
|
|
|
Клад бывает 4 типов: "письмо" (letter) -
|
2024-11-10 17:37:42 +00:00
|
|
|
|
это когда клад имеет заранее известный (из заголовка сообщения) конечный размер,
|
|
|
|
|
"вкид" (vkid) - это когда клад продолжается до самого конца канала без возможности
|
|
|
|
|
вернуться обратно к kmtp-протоколу, при чем бесконечность вкида известна заранее. А ещё есть
|
|
|
|
|
"отвал" (otval) - это когда размер клада заранее неизвестен и должен быть на ходу
|
|
|
|
|
определён тем, кто принимает отвал. После перехода на отвал канал ещё может обратно
|
2024-12-22 17:18:49 +00:00
|
|
|
|
вернуться к протоколу sub-kmtp, однако определить этот момент возврата не понимая
|
2024-11-10 17:37:42 +00:00
|
|
|
|
протокола, который использует отвал - невозможно. Потому при появлении в канале отвала
|
|
|
|
|
любой прокси, что не понимает протокол отвала сразу потеряет возможность распознавать весь
|
2024-12-22 17:18:49 +00:00
|
|
|
|
дальнейший трафик. Как можно заметить практического смысла использовать отвал
|
|
|
|
|
вместо вкида в мастер-kmtp сообщении нет.
|
|
|
|
|
Поток суб-сообщений - это клад. А именно "отвал". Чтобы указать принимающему
|
2024-11-10 17:37:42 +00:00
|
|
|
|
что вкид нашего мастер-сообщения это имеенно поток суб-сообщений, надо в специальное
|
|
|
|
|
поле для типа клада записать "sub-kmtp". При этом если клиент отправит поле типа клада
|
|
|
|
|
"sub-kmtp", все понимают, что он сейчас начнёт отправлять именно поток суб-запросов,
|
|
|
|
|
а у сервера значение значения "sub-kmtp" в этои поле будет означать отправку потока
|
|
|
|
|
суб-ответов.
|
|
|
|
|
|
|
|
|
|
Клиент посылает серверу запросы и на каждый запрос приходит ровно один ответ
|
|
|
|
|
(в том же порядке, в котором соответствующие запросы были заданы). На
|
|
|
|
|
мастер-запрос (master-request) приходит мастер-ответ (master-response),
|
|
|
|
|
на суб-запрос (sub-request) приходит суб-ответ (sub-response).
|
2024-12-22 17:18:49 +00:00
|
|
|
|
Но! Сервер также может в любой момент времени отправить в выходной канал особый вид
|
2024-11-10 17:37:42 +00:00
|
|
|
|
сообщения, называемое "событие" (event). Событие адресовано мастер-запросу, а не
|
|
|
|
|
суб-запросам. События имеют такую же структуру, что и суб-ответы, отличаются они только тем,
|
|
|
|
|
что в заголовке события "поле Status" обязано быть равно "Event (DC)".
|
|
|
|
|
О том что такое "поле Status" будет сказано позже.
|
|
|
|
|
|
|
|
|
|
== Формат сообщения
|
|
|
|
|
|
|
|
|
|
Любое сообщение начинается с заголовка.
|
|
|
|
|
Заголовок начинается с нескольких обязательных полей. Их число, назначение и формат заранее
|
|
|
|
|
определены для каждого типа сообщений.
|
|
|
|
|
После блока обязательных полей следует множество именованных полей. Их число не определено,
|
|
|
|
|
пользователи kmtp вольны сами придумывать эти поля.
|
|
|
|
|
Оканчивается заголовок символом LF (Перевод строки). После заголовка идёт клад.
|
|
|
|
|
|
|
|
|
|
Поля имеют формат "имя" + ":"/">" + "значение" + LF. При этом есть безымянные поля, где
|
|
|
|
|
"имя" пусто.
|
|
|
|
|
"имя" это строка из символов `[a-zA-Z0-9-_+=/]` , что овпадает с форматом
|
|
|
|
|
ключей в kmon (о kmon можно прочитать в соответствующем документе).
|
|
|
|
|
Имя и значение разделены символом ":", но для некоторых 3-ёх обязательных полей
|
|
|
|
|
":" заменяется на ">". Эти поля: "Virtual-Host", "Auth-Username", "Auth-Password".
|
|
|
|
|
Они отличаются от других тем, что они присутствуют только в мастер-сообщениях.
|
|
|
|
|
Об этом позже будет рассказано.
|
2024-12-22 17:18:49 +00:00
|
|
|
|
"Значение" несёт в себе строку произвольного формата, но важно то, как она обёрнута.
|
2024-11-10 17:37:42 +00:00
|
|
|
|
Если надо передать строку str, значение записывается как "=" + hex(len(str)) + ">" + str,
|
|
|
|
|
при этом если так получилось, что str не содержит символа `'` (ascii 0x27), то можно
|
|
|
|
|
записать значение как "'" + str + "'". Семантика сообщения от выбора способа записи
|
|
|
|
|
значения не меняется. Такой формат совпадает с форматом строк в kmon.
|
|
|
|
|
Некоторые обязательные поля, о которых известно, что они не содержат символа перевода строки,
|
|
|
|
|
передаются без форматирования, напрямую: "имя" + ":" + str + LF.
|
|
|
|
|
Поля, которые имеют особую запись будут помечены в списке полей символом #math.penta.filled .
|
|
|
|
|
|
|
|
|
|
Сейчас будут полность определены обязательне поля всех 4 типов сообщений.
|
|
|
|
|
Хотя им всем даны имена, в канале они опущены, ибо известны заранее.
|
|
|
|
|
|
|
|
|
|
#let field-name-decl(name) = bold(name)
|
|
|
|
|
#let master-field-name-decl(name) = bold(name)
|
|
|
|
|
|
|
|
|
|
Устройство блока заголовка суб-запроса:
|
2024-12-22 17:18:49 +00:00
|
|
|
|
+ #field-name-decl[Location]: Путь нужного ресурса на сервере. В мастер-запросе
|
|
|
|
|
не может быть относительным путём, ведь нам неотчего отталкиваться. Правила такие же,
|
|
|
|
|
как для юникс-путя.
|
|
|
|
|
+ #field-name-decl[Function]: Функция, производимая над ресурсом.
|
2024-11-10 17:37:42 +00:00
|
|
|
|
Ближайшим аналогом будет
|
|
|
|
|
поле method из http. KMTP определяет ряд функций с определённым значение,
|
|
|
|
|
однако пользователи kmtp могут сами определять свои функции, если сервер
|
|
|
|
|
сможет их понять. Function имеет ограничение на используемые символы (функции
|
|
|
|
|
именуются как ключи в kmon), что делает ненужным оборачивание в кавычки.
|
|
|
|
|
(#math.penta.filled)
|
|
|
|
|
+ #field-name-decl[Client-Klad-Seek-Pos]: В этом поле записывается неотрицательное
|
|
|
|
|
число (в шестнадцатиричной системе счисления) #math.penta.filled. Пустая строка
|
|
|
|
|
эквивалентна нулю. Значение зависит от функции, но принято использовать его для
|
|
|
|
|
указания сдвига данных, передаваемых в кладе клиента (например, если клиент
|
|
|
|
|
загружал большой файл, но соединение оборвалось, это поле можно использовать
|
|
|
|
|
чтобы указать с какого места продолжается закачка).
|
2024-12-22 17:18:49 +00:00
|
|
|
|
+ #field-name-decl[Resource-Klad-Seek-Pos]: Формат тот же что и у Client-Klad-Sek-Pos
|
2024-11-10 17:37:42 +00:00
|
|
|
|
(#math.penta.filled). Но здесь указывается сдвиг относительно ресурса на сервере.
|
|
|
|
|
Так, к примеру, клиент может указать с какого момента продолжить скачивание большого
|
|
|
|
|
файла с сервера.
|
|
|
|
|
+ #field-name-decl[Body-Type]: если за сообщением следует "тело",
|
|
|
|
|
то здесь указывается как
|
2024-12-22 17:18:49 +00:00
|
|
|
|
его прочитать. Это может быть число в 16-ричной
|
|
|
|
|
системе счисления, если передано письмо, "otval" если произошел отвал,
|
|
|
|
|
"vkid", если произошел вкид (как можешь убедиться, эти 3 случая невозможно
|
|
|
|
|
перепутать) #math.penta.filled. Да, как бы это не было странно, но у суб-сообщений
|
2024-11-10 17:37:42 +00:00
|
|
|
|
может быть свой клад, получается что клад суб-сообщения это клад в кладе
|
|
|
|
|
мастер-сообщения.
|
2024-12-22 17:18:49 +00:00
|
|
|
|
+ #bold[Upgrade-Name]: Здесь указывается узнаваемое имя протокола,
|
2024-11-10 17:37:42 +00:00
|
|
|
|
к которому мы переходим. На это поле наложены такие же ограничения, как
|
|
|
|
|
на поле Function (используются только символы, допустимые в kmon
|
|
|
|
|
ключе), поэтому кавычки не используются #math.penta.filled. Пустая строка допустима.
|
2024-12-22 17:18:49 +00:00
|
|
|
|
Имеет смысл только если клад не пуст.
|
2024-11-10 17:37:42 +00:00
|
|
|
|
|
|
|
|
|
Для удобства мастер-запрос очень похож на суб-запрос. Различие лишь в том, что
|
|
|
|
|
в мастер-запрос в начало добавляются 3 мастер-поля:
|
|
|
|
|
+ #master-field-name-decl[Virtual-Host]
|
|
|
|
|
+ #master-field-name-decl[Auth-Username]
|
|
|
|
|
+ #master-field-name-decl[Auth-Password]
|
|
|
|
|
Каждое из них это то что ты подумал это это. Мастер-поле в сериализованном виде
|
|
|
|
|
начинается не с ":", как все обязательные поля, а с ">".
|
|
|
|
|
|
|
|
|
|
В мастер-запросе поле Location не может быть относительным путём, а в суб-запросах
|
|
|
|
|
может, точкой отсчета для относительных путей будет путь указанный в мастер-запросе.
|
|
|
|
|
|
|
|
|
|
#let roman-status(x) = bold(x)
|
|
|
|
|
|
|
|
|
|
Усройство блока заголовка суб-ответа:
|
|
|
|
|
+ #field-name-decl[Status]: одна строка из определённого набора, необходимая для
|
|
|
|
|
правильной интерпретации ответа. #math.penta.filled.
|
|
|
|
|
+ #field-name-decl[Resource-Klad-Seek-Pos]: #math.penta.filled.
|
|
|
|
|
+ #field-name-decl[Client-Klad-Seek-Pos]: #math.penta.filled.
|
|
|
|
|
+ #field-name-decl[Body-Type]: #math.penta.filled.
|
|
|
|
|
+ #field-name-decl[Upgrade-Name]: #math.penta.filled.
|
|
|
|
|
+ #field-name-decl[Last-Change-Time]: число (шестнадцатеричное),
|
|
|
|
|
отмеряющее время последнего изменения ресурса.
|
|
|
|
|
Не обязано быть привязано к реальному времени. Может быть пустой строкой - это
|
|
|
|
|
эквивалентно нулю. #math.penta.filled. Нет ограничения на размер этого числа.
|
|
|
|
|
|
2024-12-22 17:18:49 +00:00
|
|
|
|
Мастер-ответ ничем не отличается от суб-ответа.
|
2024-11-10 17:37:42 +00:00
|
|
|
|
|
|
|
|
|
Status мастер-ответа не может быть #roman-status[DC] (Event).
|
|
|
|
|
|
|
|
|
|
Получается, что список обязательных полей, использующих синтаксис `=HEX>str or 'str'`,
|
|
|
|
|
который дефолтен для именованных полей, довольно мал: это все мастер-поля + поле
|
2024-12-22 17:18:49 +00:00
|
|
|
|
Location. Нужно учесть, что значение поля Location не должно содержать октета 0,
|
|
|
|
|
хотя это наврятле будет проверяться.
|
2024-11-10 17:37:42 +00:00
|
|
|
|
|
|
|
|
|
Этот документ сам определяет ряд именованных полей сообщения.
|
|
|
|
|
Есть целый ряд незапланированных полей, вида `"Proxy-" + n + "-" + Name`,
|
|
|
|
|
где n - натуральное число, а Name - имя для поля. Это будет поле, переданное
|
|
|
|
|
n-ым с конца прокси (отсчет начинается от стороны получателя). От одного прокси может
|
|
|
|
|
передаваться много разных полей, поэтому можно дополнительно указать суб-имя `Name`.
|
|
|
|
|
|
2024-12-22 17:18:49 +00:00
|
|
|
|
Считается, что kmtp-прокси при прохождении через него заголовка сообщения, порядок
|
|
|
|
|
всех полей, начинающихся с `"Proxy-"`, инкрементирует, а если хочет и свои поля
|
|
|
|
|
добавить, Поставит в их имена префикс `"Proxy-1-"`.
|
|
|
|
|
|
2024-11-10 17:37:42 +00:00
|
|
|
|
+ #field-name-decl[Proxy-n-Address]: Адрес клиента, который видит прокси, но конечный
|
|
|
|
|
сервер не видит. Здесь #field-name-decl[Proxy-n-Address] - это параметризованное имя
|
|
|
|
|
поля.
|
|
|
|
|
|
|
|
|
|
== Коды статуса. Поле Status
|
|
|
|
|
|
|
|
|
|
=== Предисловие
|
|
|
|
|
|
|
|
|
|
У каждого сообщения сервера (ответа или события) поле Status
|
|
|
|
|
(код статуса) принимает одно
|
|
|
|
|
из возможных значений. Сейчас будут перечислены все допустимые значения
|
|
|
|
|
статуса ответа и их смысл.
|
|
|
|
|
|
|
|
|
|
=== Самые частые коды статуса, выражающие успех (CC..., DC...)
|
|
|
|
|
- #roman-status[CC] (Success)
|
|
|
|
|
- #roman-status[DC] (Event)
|
|
|
|
|
|
|
|
|
|
=== Коды перенаправления (CCC...)
|
|
|
|
|
- #roman-status[CCCI] (Moved Permanently)
|
|
|
|
|
- #roman-status[CCCIII] (See other)
|
|
|
|
|
- #roman-status[CCCVII] (Temporary Redirect)
|
|
|
|
|
- #roman-status[CCCX] (Go Back)
|
|
|
|
|
|
2024-12-22 17:18:49 +00:00
|
|
|
|
#heading(level: 3)[Ошибка когда виноват клиент (CD...)]
|
2024-11-10 17:37:42 +00:00
|
|
|
|
- #roman-status[CD] (Bad request)
|
|
|
|
|
- #roman-status[CDI] (Unauthorized)
|
|
|
|
|
- #roman-status[CDIII] (Forbidden)
|
|
|
|
|
- #roman-status[CDIV] (Not Found)
|
|
|
|
|
- #roman-status[CDV] (Inadmissible Function)
|
|
|
|
|
- #roman-status[CDX] (Gone)
|
|
|
|
|
- #roman-status[CDXIII] (Klad Too Long)
|
|
|
|
|
- #roman-status[CDXIV] (Path Too Long)
|
|
|
|
|
- #roman-status[CDXV] (Unsupported Media Type)
|
|
|
|
|
- #roman-status[CDXXXI] (Header Too Long)
|
|
|
|
|
- #roman-status[CDLXI] (Profile Not Found)
|
|
|
|
|
- #roman-status[CDLXII] (Incorrect Seek Pos Client Side)
|
|
|
|
|
- #roman-status[CDLXIV] (Inadmissible Body Type)
|
|
|
|
|
- #roman-status[CDLXXVI] (Incorrect Seek Pos Resource Side)
|
|
|
|
|
|
2024-12-22 17:18:49 +00:00
|
|
|
|
#heading(level: 3)[Ошибка когда виноват сервер, прокси или машина, на которой
|
2024-11-10 17:37:42 +00:00
|
|
|
|
они работают (D...)]
|
|
|
|
|
- #roman-status[D] (Internal Server Error)
|
|
|
|
|
- #roman-status[DII] (Destination Unreachable)
|
|
|
|
|
- #roman-status[DIII] (Service Unavailable)
|
|
|
|
|
- #roman-status[DXI] (System Failure)
|
|
|
|
|
- #roman-status[DXII] (Undelivered)
|
|
|
|
|
- #sparkingGreenSunEffect(1)[DXVIII]
|
|
|
|
|
(Nuclear Reactor That Was Managed By This Computer Was Blown Up By Terrorists) \
|
|
|
|
|
Упс, это спойлеры к KM.
|
|
|
|
|
|
2024-12-22 17:18:49 +00:00
|
|
|
|
#heading(level: 3)[Ошибка когда виновато общество в котором вы живёте (DCC...)]
|
2024-11-10 17:37:42 +00:00
|
|
|
|
- #roman-status[DCCLI] (Unavailable For Legal Reasons) \
|
|
|
|
|
Запрашиваемый ресурс / запрашиваямая операция над ресурсом недопустима в стране
|
|
|
|
|
сервера.
|
|
|
|
|
- #roman-status[DCCLII] (Cancelled For Legal Reasons)\
|
|
|
|
|
Запрашиваемый ресурс / запрашиваямая операция над ресурсом недопустима в стране
|
2024-12-22 17:18:49 +00:00
|
|
|
|
клиента. Отличие от DCCLI в том, что другим клиентам из других стран этот же
|
2024-11-10 17:37:42 +00:00
|
|
|
|
ресурс может быть доступен.
|
|
|
|
|
|
|
|
|
|
== Широко известные функции. Поле Function.
|
|
|
|
|
|
|
|
|
|
=== Предисловие
|
|
|
|
|
|
|
|
|
|
Множество кодов статуса ответа зафиксировано и не расширяемо, а вот свои функции серверу
|
|
|
|
|
придумывать не запрещено. Есть некоторые принятые значения для определённых
|
|
|
|
|
имён функций. Здесь представлен неисчерпывающий список таких имён функций.
|
|
|
|
|
|
|
|
|
|
=== read
|
|
|
|
|
|
|
|
|
|
Читает весь ресурс (файл) или его часть. Для указания интересующего нас постфикса
|
|
|
|
|
клиент заполняет своё поле Resource-Klad-Seek-Pos.
|