Document LAN invitation framing and server link preview contracts

This commit is contained in:
evgeny committed 2026-10-28 12:28:28 +01:00
1 parent 237ba93e1a
commit 25dda68ecf
2 files changed
+33 -4

No files matched your search

@@ -55,8 +55,9 @@ data class InviteAddr(
override fun hashCode(): Int = family * 31 + address.contentHashCode() + port * 31 + socketId * 31 + proto
}
/** Полный снимок приглашения; равенство учитывает все поля, включая реквизиты входа и исходную ссылку.
* channelId — 1..Long.MAX_VALUE; joinKey/nodeId хранят все биты uint64 в Long (для unsigned-вывода использовать toULong()).
/** Предпросмотр приглашения; равенство учитывает все поля и исходную ссылку.
* CHANNEL: channelId=1..Long.MAX_VALUE и ненулевой joinKey; SERVER: channelId/joinKey=0, password пуст, add_key остаётся в link.
* joinKey/nodeId хранят все биты uint64 в Long (для unsigned-вывода использовать toULong()).
* pubkey — 32 байта X25519 узла подключения, addrs — 1..32 его адресов. password — UTF-8 preview, link — исходная wire-ссылка. */
data class InviteData(
val channelId: Long,
+30 -2
View File
@@ -141,8 +141,10 @@ UDP-лог — в `[log_udp] ip/port`; полный набор задаёт Conf
Для подключения канала/участника используются общие chat_core/topo_group API.
`InviteLink.kt` получает предпросмотр через `NativeLib.decodeInvite()` — JNI вызывает
общий `src/chat/invite_link.c`. Ссылка `utun://...` содержит версию 0x03, пароль,
channel_id, join_key, REALITY-параметры и блоки публичного ключа/адресов.
общий `src/chat/invite_link.c`. Ссылка `utun://...` содержит версию 0x04 и kind:
CHANNEL несёт пароль/channel_id/join_key, SERVER — 32-байтовый add_key без полей канала.
Далее идут REALITY-параметры и блоки публичного ключа/адресов. В Kotlin-preview
SERVER имеет channelId/joinKey=0 и пустой password; add_key остаётся в исходной ссылке.
JOIN передаёт исходную ссылку и request ID через потокобезопасный chat_join_port;
принятый запрос завершается CONNECT_RESULT с тем же request. Отрицательный возврат
submit означает отказ без события. Детали: `src/chat/chat_join.h`, `chat_join_port.h`.
@@ -151,6 +153,32 @@ submit означает отказ без события. Детали: `src/cha
Merkle распространяет запись; доступ к группе определяется локальной таблицей участников.
JOIN_READY добавления и READY групповой сессии — разные состояния.
LAN-приглашения хранит app-scoped `LocalDiscovery`; AppEventHandler передаёт ему
события напрямую на main, без replay ViewModel. Список устройств 61 заменяется
целиком; входящая канальная ссылка 62 только ставится в очередь показа, без JOIN.
Кадры 61..63 имеют BE-поля ID/длин, 64 содержит байт активности. Принимаются
не более 128 устройств, имена 1..127 UTF-8 байтов без ASCII control, ссылка до
1100 байтов; входящая UI-очередь ограничена 8 приглашениями. Повреждённые кадры,
невалидный UTF-8, нулевые/повторные ID устройств не заменяют прежнее состояние.
Одна исходящая LAN-отправка на приложение хранит request и снимок адресата.
Событие 63 применяется только к pending с совпавшими request и peer; статусы
0/1/2 означают failed/received/forbidden. ACK подтверждает приём ссылки, не JOIN.
Отказ/исключение JNI завершает pending ошибкой. Stop очищает устройства и pending,
сохраняет уже полученные приглашения; поздний ACK не возобновляет завершённый запрос.
Android MulticastLock следует эффективной активности native discovery, а не
видимости Activity. Владелец сохраняется до configure/acquire и при ошибке
query/release: следующий ACTIVE/STOP повторяет операцию с тем же lock.
В логе указаны точный этап и сохранён ли владелец; на повторном ACTIVE удерживаемый
lock не захватывается ещё раз. Постоянный таймер повторов здесь не запускается.
`InviteLinkDialog` получает candidates/link/pending от владельца генерации.
Он показывает QR или текст, запрашивает LAN-снимок и отображает результат
последней отправки вместе с её адресатом. Закрытие не отменяет pending-доставку.
Ошибка QR логируется без ссылки, текст остаётся доступен; ошибка clipboard
показывается в диалоге. Смена ссылки сбрасывает подтверждение копирования.
DM-команды используют conv_id и поколение беседы. История приходит событием
CHAT_EVT_DM_MESSAGES, список — CHAT_EVT_DM_CONVERSATIONS. Frontend отбрасывает
ответы старого поколения/другой беседы. Voice/video принимают target `dm:<conv_id>`;