fix: removed all the trash (except for kmtp itself)

This commit is contained in:
Andreev Gregory 2024-12-22 20:18:49 +03:00
parent 87f6c8435f
commit 4440b50798
3 changed files with 99 additions and 47 deletions

View File

@ -1,3 +1,14 @@
#import "head.typ" as head : *
#show: MyStyle
= 2 Ears 1 Mouth Specification
2 Ears 1 Mouth (2e1m) это договорённость о передачи аудиопотока, используемая для общения
в играх с "proximity-voice-чатом". Клиент отправляет чистый PCM поток с одним каналом с
семплами в формате signed 16-bit two's complement числа. Это то, что "говорит" клиент.
Сервер отправляет клиенту чистый PCM поток такого-же формата, но с двумя каналами: первый
соответствует тому, что левое ухо клиента "слышит", а второй соответствует сигналу,
приходящему на правое ухо.
Вот и всё. В kmtp-классификации кладов 2e1m имеет кодовое имя `2e1m`.

View File

@ -1,3 +1,47 @@
#import "head.typ" as head : *
#show: MyStyle
= KMON Specification
KMON (KM Object Notation) это множество объектов, удобных для использования в программах с динамической типизацией.
Этот документ описывает этом ножество объектов и как их интегрпретировать, а так же определяет биекцию между
множеством kmon и подмножеством строк, представляющих собой запись km-объкта.
KMON является упрощённым аналогом JSON, использующимся в KM Project. KMON это официальное название типа объектов,
однако в самом мире игры KM он известен как SON (Suckless
Object Notation).
KM-объект (объект типа kmon/KMobj) может быть одного из 5-и подтипов: null (пустой), int (число),
str (строка), arr (массив), dict (словарь). При этом int хранит в себе целое число (со знаком),
str хранит в себе строку байт (не обязательно корректную, это просто массив из октетов произвольной длины).
Arr хранит массив км-объектов, Dict хранит словарь, где ключи: строки из алфавита, состоящего лишь из
букв латинского алфавита, чисел и символов #text(fill:red)[`+` `/` `=` `-` `-`]; а значения словаря - другие
км-объекты.
Такие объекты, хранящиеся в другом км-объекти называются сыновьями родительского объекта.
Принято хранить в числовом км-объекте число от $-2^63$ до $2^63+1$.
Число записывается естесственным образом. null-объект записывается как литерал `null`.
Строка `str` может записываться в формате `'{str}'`, здесь мы окружаем строку одинарной
кавычкой. Такой способ записи может использоваться только если в строке нет символа
одинарной кавычки. Произвольную строку можно записать вторым способом:
`={len(str)}>{str}`, здесь мы перед строкой пишем знак равенства, указываем длину строки
(в шестнадцатиричной системе счисления), оканчиваем размер знаком "больше" и записываем
саму строку. Это два единственных "формальных" способа записи. Все имплементации
десериализватора должны быть способны их прочитать. Есть ещё опциональная третья запись.
`"str.sub('\', '\\').sub('"', '\"')"`. Здесь мы сперва экранируем в строке все двойные
кавычки и обратные слэши, и обрамляем получившуюся строку в двойные кавычки.
Это называется "человекочитаемый формат". Программа, посылающая км-объект в таком формате должна быть уверена, что получатель поддерживает человекочитаемый формат строк.
Вокруг записи км-объекта можно ставить справа и слева пробелы, смысл от этого не будет
меняться.
Для записи массивов все его элементы разделяются запятыми, и полученная строка окружается
квадратными скобками (слева левой, справа правой).
Запись словаря похожа на запись массива тем, что запись словаря - это разделённый
запятыми список пар (ключ, км-объект), окруженный фигурными скобками (слева левой,
справа правой). Пара ключ, км объект состоит из 3-ёх частей (которые можно окружать
и разделять пробелами): ключ "по формату словарного ключа", записанный напрямую,
потом двоеточие, после него сам км-объект, значение в словаре по данному ключу.
Ключи не должны повторяться.

View File

@ -3,12 +3,12 @@
#show: MyStyle
= KMTP Specification
= KMTP, Sub-KMTP Спецификация
== Область применения
KMTP это протокол, созданный специально для будущей видеоигры KM (Используется
в рамках KM project). Он нацелен на замену чрезвычайно непрофессионального и раздутого
в рамках KM project). Он нацелен на замену чрезвычайно раздутого
протокола http+websocket. KMTP (KM Transport Protocol) это его официальное название,
однако в самом мире игры KM он известен как STP (Suckless
Transport Protocol).
@ -28,8 +28,7 @@ KMTP применяется когда между двумя общающими
хотя под это понятие попадает даже содержимое jpeg картинки, скачанной с файлового
сервера.
В начале соединения клиент может предствиться передав "логин" и "пароль",
а сервер может представиться, передав свой пароль.
В начале соединения клиент может предствиться передав "логин" и "пароль".
Каналы связи называются
- client's output / server's output / request channel
@ -39,33 +38,31 @@ KMTP применяется когда между двумя общающими
"сообщение". Они бывают двух видов: "запросы" (отправляются клиентом) и
"ответы" (отправляются сервером). Но есть ещё одно деление: на "мастер-сообщение"
и "суб-сообщение" (применимое к обоим типам адресанта сообщения).
Контент каждого канала начинается с мастер-сообщения своего типа, а все
последующие сообщения, отправленные по каналу, (если таковые есть)
записаны в формате "суб-сообщений".
У каждого типа есть свой формат, форматы различаются набором обязатльных "полей".
Контент каждого канала начинается с мастер-сообщения своего типа.
Если клиент и сервер договорились сделать "апгрейд" до sub-kmtp, то все дальнейшие
сообщения будут записаны в формате "суб-сообщений".
У каждого типа есть свой формат, форматы различаются набором обязательных "полей".
Каждый kmtp-канал содержит последовательность kmtp-сообщений. Первое сообщение -
мастер-сообщение, остальные - суб-сообщения.
При этом все суб-сообщения в канале как-бы считаются телом мастер-сообщения.
Поэтому если есть поток суб-сообщений, приложенный к мастер-сообщению, то другого
тела у мастер сообщения нет. Есть специальное поле заголовка мастер-сообщения,
сообщающее, идёт ли после мастер-сообщения поток суб-сообщений. О поляъ расскажу позже.
Поток суб-сообщений оканчивается когда вместо следующего сообщения отправитель передаёт
по каналу LF (line feed). Опять же, если потока нет, о передавать этот LF
в конце не нужно.
Каждый канал содержит только мастер-сообщение (соответсвующего типа) и ничего более.
Поток суб-сообений это часть местер сообщения. Естесственно, поток суб-сообщений
будет присутсвовать только когда был произведён апгрейд до sub-kmtp.
В этом случае сначала идёт мастер-заголовок сообщения, а всё остальное (та часть
сообщения, называющаяся кладом) - это sub-kmtp. Вместо него, конечно же, мог бы быть
совсем другой клад мастер сообщения.
Сообщения содержат заголовок, чей формат полность определён и тело, называемое "кладом".
Клад бывает 4 типов: отсутствующий (none) - это когда клад отсутствует, "письмо" (letter) -
Клад бывает 4 типов: "письмо" (letter) -
это когда клад имеет заранее известный (из заголовка сообщения) конечный размер,
"вкид" (vkid) - это когда клад продолжается до самого конца канала без возможности
вернуться обратно к kmtp-протоколу, при чем бесконечность вкида известна заранее. А ещё есть
"отвал" (otval) - это когда размер клада заранее неизвестен и должен быть на ходу
определён тем, кто принимает отвал. После перехода на отвал канал ещё может обратно
вернуться к протоколу kmtp, однако определить этот момент возврата не понимая
вернуться к протоколу sub-kmtp, однако определить этот момент возврата не понимая
протокола, который использует отвал - невозможно. Потому при появлении в канале отвала
любой прокси, что не понимает протокол отвала сразу потеряет возможность распознавать весь
дальнейший трафик.
Поток суб-сообщений - это вклад. А именно "вкид". Чтобы указать принимающему
дальнейший трафик. Как можно заметить практического смысла использовать отвал
вместо вкида в мастер-kmtp сообщении нет.
Поток суб-сообщений - это клад. А именно "отвал". Чтобы указать принимающему
что вкид нашего мастер-сообщения это имеенно поток суб-сообщений, надо в специальное
поле для типа клада записать "sub-kmtp". При этом если клиент отправит поле типа клада
"sub-kmtp", все понимают, что он сейчас начнёт отправлять именно поток суб-запросов,
@ -76,8 +73,7 @@ KMTP применяется когда между двумя общающими
(в том же порядке, в котором соответствующие запросы были заданы). На
мастер-запрос (master-request) приходит мастер-ответ (master-response),
на суб-запрос (sub-request) приходит суб-ответ (sub-response).
Но сервер также может в любой момент времени отправить в выходной канал особый вид
Но! Сервер также может в любой момент времени отправить в выходной канал особый вид
сообщения, называемое "событие" (event). Событие адресовано мастер-запросу, а не
суб-запросам. События имеют такую же структуру, что и суб-ответы, отличаются они только тем,
что в заголовке события "поле Status" обязано быть равно "Event (DC)".
@ -91,8 +87,6 @@ KMTP применяется когда между двумя общающими
После блока обязательных полей следует множество именованных полей. Их число не определено,
пользователи kmtp вольны сами придумывать эти поля.
Оканчивается заголовок символом LF (Перевод строки). После заголовка идёт клад.
Если клад не none и клад окончился возвращением к kmtp-протоколу, после клада
добавляется символ LF. Он не несёт никакой пользы, но важно не забыть перепрыгнуть через него.
Поля имеют формат "имя" + ":"/">" + "значение" + LF. При этом есть безымянные поля, где
"имя" пусто.
@ -102,7 +96,7 @@ KMTP применяется когда между двумя общающими
":" заменяется на ">". Эти поля: "Virtual-Host", "Auth-Username", "Auth-Password".
Они отличаются от других тем, что они присутствуют только в мастер-сообщениях.
Об этом позже будет рассказано.
"значение" несёт в себе строку произвольного формата, но важно то, как она обёрнута.
"Значение" несёт в себе строку произвольного формата, но важно то, как она обёрнута.
Если надо передать строку str, значение записывается как "=" + hex(len(str)) + ">" + str,
при этом если так получилось, что str не содержит символа `'` (ascii 0x27), то можно
записать значение как "'" + str + "'". Семантика сообщения от выбора способа записи
@ -118,9 +112,10 @@ KMTP применяется когда между двумя общающими
#let master-field-name-decl(name) = bold(name)
Устройство блока заголовка суб-запроса:
+ #field-name-decl[Location]: Юникс путь нужного ресурса на сервере. В мастер-запросе
не может быть относительны путём, ведь нам неотчего отталкиваться.
+ #field-name-decl[Function]: функцию, производимая над ресурсом.
+ #field-name-decl[Location]: Путь нужного ресурса на сервере. В мастер-запросе
не может быть относительным путём, ведь нам неотчего отталкиваться. Правила такие же,
как для юникс-путя.
+ #field-name-decl[Function]: Функция, производимая над ресурсом.
Ближайшим аналогом будет
поле method из http. KMTP определяет ряд функций с определённым значение,
однако пользователи kmtp могут сами определять свои функции, если сервер
@ -133,25 +128,23 @@ KMTP применяется когда между двумя общающими
указания сдвига данных, передаваемых в кладе клиента (например, если клиент
загружал большой файл, но соединение оборвалось, это поле можно использовать
чтобы указать с какого места продолжается закачка).
+ #field-name-decl[Client-Klad-Seek-Pos]: Формат тот же что и у Client-Klad-Sek-Pos
+ #field-name-decl[Resource-Klad-Seek-Pos]: Формат тот же что и у Client-Klad-Sek-Pos
(#math.penta.filled). Но здесь указывается сдвиг относительно ресурса на сервере.
Так, к примеру, клиент может указать с какого момента продолжить скачивание большого
файла с сервера.
+ #field-name-decl[Body-Type]: если за сообщением следует "тело",
то здесь указывается как
его прочитать. Это может быть пустая строка, если тела нет, число в 16-ричной
системе счисления, если произошел отнюх, "otval" если произошел отвал,
"vkid", если произошел вкид (как можешь убедиться, эти 4 случая невозможно
перепутать) #math.penta.filled. Важно! Если Body-Type пуст, то клада нет, сообщение
оканчивается там, где оканчивается его заголовок. Но если Body-Type это "0" или
"00 ... 0", то клад есть, го тип - письмо, и после пустого письма должен стоять
обязательный перевод строки. Да, как бы это не было странно, но у суб-сообщений
его прочитать. Это может быть число в 16-ричной
системе счисления, если передано письмо, "otval" если произошел отвал,
"vkid", если произошел вкид (как можешь убедиться, эти 3 случая невозможно
перепутать) #math.penta.filled. Да, как бы это не было странно, но у суб-сообщений
может быть свой клад, получается что клад суб-сообщения это клад в кладе
мастер-сообщения.
+ #bold[Upgrade-Name]: если тело есть, то здесь указывается узнаваемое имя протокола,
+ #bold[Upgrade-Name]: Здесь указывается узнаваемое имя протокола,
к которому мы переходим. На это поле наложены такие же ограничения, как
на поле Function (используются только символы, допустимые в kmon
ключе), поэтому кавычки не используются #math.penta.filled. Пустая строка допустима.
Имеет смысл только если клад не пуст.
Для удобства мастер-запрос очень похож на суб-запрос. Различие лишь в том, что
в мастер-запрос в начало добавляются 3 мастер-поля:
@ -178,14 +171,14 @@ KMTP применяется когда между двумя общающими
Не обязано быть привязано к реальному времени. Может быть пустой строкой - это
эквивалентно нулю. #math.penta.filled. Нет ограничения на размер этого числа.
Мастер-ответ отличается от суб-ответа тем, что в начале присутствует одно мастер поле:
+ #master-field-name-decl[Auth-Password]: Это то, что ты подумал.
Мастер-ответ ничем не отличается от суб-ответа.
Status мастер-ответа не может быть #roman-status[DC] (Event).
Получается, что список обязательных полей, использующих синтаксис `=HEX>str or 'str'`,
который дефолтен для именованных полей, довольно мал: это все мастер-поля + поле
Location. Нужно учесть, что значение поля Location не должно содержать октета 0.
Location. Нужно учесть, что значение поля Location не должно содержать октета 0,
хотя это наврятле будет проверяться.
Этот документ сам определяет ряд именованных полей сообщения.
Есть целый ряд незапланированных полей, вида `"Proxy-" + n + "-" + Name`,
@ -193,6 +186,10 @@ Location. Нужно учесть, что значение поля Location н
n-ым с конца прокси (отсчет начинается от стороны получателя). От одного прокси может
передаваться много разных полей, поэтому можно дополнительно указать суб-имя `Name`.
Считается, что kmtp-прокси при прохождении через него заголовка сообщения, порядок
всех полей, начинающихся с `"Proxy-"`, инкрементирует, а если хочет и свои поля
добавить, Поставит в их имена префикс `"Proxy-1-"`.
+ #field-name-decl[Proxy-n-Address]: Адрес клиента, который видит прокси, но конечный
сервер не видит. Здесь #field-name-decl[Proxy-n-Address] - это параметризованное имя
поля.
@ -216,7 +213,7 @@ n-ым с конца прокси (отсчет начинается от сто
- #roman-status[CCCVII] (Temporary Redirect)
- #roman-status[CCCX] (Go Back)
#heading(level: 3)[Коды ошибки, виноват клиент (CD...)]
#heading(level: 3)[Ошибка когда виноват клиент (CD...)]
- #roman-status[CD] (Bad request)
- #roman-status[CDI] (Unauthorized)
- #roman-status[CDIII] (Forbidden)
@ -232,7 +229,7 @@ n-ым с конца прокси (отсчет начинается от сто
- #roman-status[CDLXIV] (Inadmissible Body Type)
- #roman-status[CDLXXVI] (Incorrect Seek Pos Resource Side)
#heading(level: 3)[Коды ошибки, виноват сервер, прокси или машина, на которой
#heading(level: 3)[Ошибка когда виноват сервер, прокси или машина, на которой
они работают (D...)]
- #roman-status[D] (Internal Server Error)
- #roman-status[DII] (Destination Unreachable)
@ -243,13 +240,13 @@ n-ым с конца прокси (отсчет начинается от сто
(Nuclear Reactor That Was Managed By This Computer Was Blown Up By Terrorists) \
Упс, это спойлеры к KM.
#heading(level: 3)[Коды ошибки, виновато общество в котором вы живёте (DCC...)]
#heading(level: 3)[Ошибка когда виновато общество в котором вы живёте (DCC...)]
- #roman-status[DCCLI] (Unavailable For Legal Reasons) \
Запрашиваемый ресурс / запрашиваямая операция над ресурсом недопустима в стране
сервера.
- #roman-status[DCCLII] (Cancelled For Legal Reasons)\
Запрашиваемый ресурс / запрашиваямая операция над ресурсом недопустима в стране
клиента. Отличие от DCCLII в том, что другим клиентам из других стран этот же
клиента. Отличие от DCCLI в том, что другим клиентам из других стран этот же
ресурс может быть доступен.
== Широко известные функции. Поле Function.