Protocol
UnixProto
UnixProto — транспорт, на якому працює Unixgram. Він розв'язує одну задачу: доставити повідомлення туди й назад поганим каналом, не видаючи при цьому, що саме передається. Нижче — як це влаштовано.
Шлях повідомлення
Стек транспорту
Рукостискання і сесія
Два незалежні шари
Транспорт відповідає за те, як payload нарізаний у потоці TCP. Пакет відповідає за те, що всередині одного payload. Шари не знають один про одного: клієнт може обрати будь-який транспорт, і формат пакета від цього не зміниться.
П'ять транспортів
Транспорт обирається один раз, за першими байтами з'єднання. Різні варіанти дають різний компроміс між накладними витратами і тим, наскільки потік схожий на випадковий шум.
Обфускація
Потік цілком, разом із тегом транспорту, загортається в AES-256-CTR. Це не шифрування — ключ виводиться з самого рукостискання. Задача інша: прибрати впізнавані заголовки, за якими трафік класифікується як «месенджер».
Шифрований канал
Обмін ключами — X25519, далі HKDF-SHA256 дає 256-бітний auth_key. Усередині пакета лежить сіль, ідентифікатор повідомлення, метод і параметри. Сіль порівнюється за сталий час, а ідентифікатор зобов'язаний строго зростати — це захист від повтору. Незашифровані виклики сервер відхиляє.
Realtime поверх WebSocket
Другий контур — кадри MessagePack на окремому порту. Версія протоколу узгоджується одним числом під час рукостискання і може бути лише знижена. Клієнт, який просить надто стару версію, отримує термінальну відмову й переходить на резервний канал.
Доставка між репліками
Реєстр з'єднань живе в процесі, тому push, що надійшов на одну репліку, самі по собі не побачать клієнти інших. Кожне відправлення публікується в спільний канал Redis, і кожна репліка доставляє своїм клієнтам сама. Відправник чекає на власну копію назад — інакше локальні клієнти отримали б подію двічі.
Транспорти та їхні накладні витрати на пакет
| Транспорт | Тег | Кадрування | Накладні |
|---|---|---|---|
| legacy | — | uint32 BE довжина + тіло | 4 Б |
| abridged | 0xef | довжина/4 одним байтом; 0x7f + 3 Б LE для довгих | 1–4 Б |
| intermediate | 0xeeeeeeee | uint32 LE довжина + тіло | 4 Б |
| padded intermediate | 0xdddddddd | uint32 LE довжина + тіло + 0–15 випадкових байт | 4–19 Б |
| full | — | довжина + seqno + тіло + CRC32 | 12 Б |