109 lines
10 KiB
Plaintext
109 lines
10 KiB
Plaintext
Динамический пакетный драйвер ETCP
|
||
================================
|
||
|
||
Потребитель: lib/packet_link.h. Экземпляр API драйвера: lib/packet_link_backend.h.
|
||
Привязка к ETCP: src/transport_layer/etcp_link_io.h/c, etcp_connections.h.
|
||
Все операции выполняются в одном uasync-потоке. Платформенные callbacks драйвер
|
||
сам переводит в этот поток. Тип транспорта не определяет интерфейс доставки.
|
||
|
||
Использование
|
||
-------------
|
||
conn = etcp_connection_create(instance, "peer"); // пока без линков
|
||
etcp_connection_set_peer(conn, peer_x25519_key); // проверить результат
|
||
link = etcp_link_add(conn, &driver); // проверить результат
|
||
|
||
Драйвер создаёт вызывающий модуль. В packet_link_driver передаются ctx, ua,
|
||
диагностическое name и функции bind/get_state/send/set_rx_enabled/stop/destroy.
|
||
direction задаёт физическое направление (UNKNOWN/OUTGOING/INCOMING), копируется
|
||
при bind и доступно через packet_link_get_direction. Оно не задаёт роль handshake
|
||
верхнего протокола. name служит также подписью транспорта в диагностике;
|
||
по его содержимому не выбираются кодирование или способ доставки.
|
||
Один ctx обслуживает один двусторонний канал к пиру. Общий UDP-сокет или BLE-радио
|
||
может принадлежать отдельному владельцу и обслуживать несколько экземпляров.
|
||
Несколько разных драйверов добавляются в один conn отдельными вызовами link_add.
|
||
Если conn уже настроен NCD, повторно set_peer вызывать не нужно.
|
||
Наличие ключа ещё не доказывает владение им: ETCP проверяет защищённый handshake.
|
||
Обнаружение ключа неизвестного пира не является частью пакетного драйвера.
|
||
|
||
Владение и события
|
||
-----------------
|
||
packet_link_bind копирует API, name, callbacks и снимок состояния. bind драйвера
|
||
копирует таблицу обратных вызовов, заимствует arg и не выдаёт события синхронно.
|
||
Успех передаёт ctx оболочке; отказ сохраняет его у вызывающего, без новой подписки.
|
||
Один экземпляр допускает только одну привязку; повторный bind возвращает ошибку.
|
||
Все потенциально неуспешные выделения оболочки делаются до bind.
|
||
При отказе etcp_link_add соединение сохраняется, драйвер остаётся у вызывающего.
|
||
|
||
Первое уведомление состояния отложено. RX первоначально выключен; ETCP включает
|
||
его после возврата link_add, при OPEN. OPEN драйвера означает готовность канала,
|
||
а UP ETCP — результат своего handshake и подтверждения эпох сессии.
|
||
|
||
send принимает целый ll_entry вне очереди. OK передаёт владение entry и dgram.
|
||
Любой отказ оставляет их вызывающему. Частичного принятия нет. Успех означает
|
||
принятие ответственности, а не доставку удалённому приложению. Ошибка после
|
||
принятия сообщается состоянием TERMINATED. Подтверждения ETCP сохраняются.
|
||
|
||
max_packet — максимум байтов целого пакета на границе драйвера, неизменный на время
|
||
его жизни; в него входят защита и заголовки ETCP. ATT MTU сюда не подставляется:
|
||
драйвер GATT сам фрагментирует принятый пакет. ETCP ограничивает свой wire-пакет
|
||
1500 байтами и вычисляет полезную часть с учётом заголовков выбранного кодирования.
|
||
|
||
tx_ready сообщает о собственных ресурсах драйвера. Если собственной очереди нет,
|
||
используется публичная готовность следующего модуля. Чужие буферы не инспектируются.
|
||
WOULD_BLOCK не требует опроса: восстановление готовности даёт state_changed.
|
||
Проверка готовности не заменяет результат send.
|
||
|
||
Драйвер может синхронно сообщить изменение состояния из send; оболочка сразу
|
||
обновляет снимок, но откладывает/объединяет верхний state_changed. RX из send
|
||
запрещён. received передаёт владение пакетом получателю; при отключённом RX драйвер
|
||
сам ограничивает накопление и не выдаёт callback. Поле memlen содержит размер
|
||
доступного dgram, len — размер данных. Оболочка очередей данных не создаёт.
|
||
|
||
close сразу отменяет уведомления и вызывает stop. stop запрещает дальнейшие
|
||
события, но не освобождает ctx. Если платформенный API не позволяет закрытие
|
||
из callback, драйвер откладывает физическое отключение после отмены подписки.
|
||
destroy выполняется через call_soon после выхода обработчиков. До уничтожения
|
||
uasync закрыть линки и выполнить drain. После close handle недействителен.
|
||
TERMINATED необратим; CONNECTING→OPEN запускает handshake. Возврат внешнего канала
|
||
в CONNECTING снимает готовность ETCP; последующий OPEN возобновляет handshake.
|
||
|
||
Доставка и кодирование
|
||
----------------------
|
||
ETCP_LINK владеет привязкой io. packet_link из get заимствован и отдельно не закрывается.
|
||
Общий путь отправки/приёма вызывает кодирование через etcp_link_codec и доставку
|
||
через API экземпляра драйвера. Кодирование не выбирается по имени драйвера.
|
||
|
||
etcp_link_get_snapshot копирует описание линка в uasync без callbacks и ссылок
|
||
на ресурсы драйвера: подпись, физическое направление, состояние ETCP, IP-адреса
|
||
и имя сокета, если они есть. Внешний пакетный канал имеет has_ip=0, имя/направление
|
||
берутся из packet_link. IP-путь сохраняет подписи UDP/TCP/TCP+REALITY и свои адреса.
|
||
Desktop MEMBER_DETAIL и Android JNI JSON сериализуют один и тот же снимок.
|
||
|
||
etcp_link_add использует защищённые датаграммы ETCP без IP-заголовков. Ключ пира
|
||
уже задан в conn. Приём привязан к каналу, поэтому адресный bootstrap, NAT и поиск
|
||
сокета не нужны. INIT и согласование эпох используют существующие форматы ETCP.
|
||
|
||
Существующий etcp_link_new — фабрика IP-путей: подготавливает UDP/STCP-драйвер
|
||
и подключает его через тот же packet_link_bind. Адреса, listener, reconnect,
|
||
SOCKS и REALITY остаются в IP-привязке. Прежние wire-форматы сохранены:
|
||
UDP получает зашифрованную датаграмму, STCP — plaintext для собственного framing.
|
||
Неизвестный UDP endpoint проходит прежний bootstrap; известный — callback драйвера.
|
||
|
||
UDP сначала пробует sendto; EAGAIN сохраняет одну датаграмму. writable сокета
|
||
возобновляет передачу; SOCKS ожидает relay ready без EPOLLOUT-цикла.
|
||
STCP разрешает один ожидающий пакет в TX адаптера. Нижний STCP извлекает следующий
|
||
после освобождения собственной досылки. RX сохраняет прежние лимиты/паузы TCP.
|
||
DATA, ACK и измерительные серии проверяют готовность. ACK и служебные признаки
|
||
фиксируются после принятого send; при отказе остаются для повторной отправки.
|
||
|
||
Проверки и диагностика
|
||
---------------------
|
||
test_packet_link: владение, TX blocked/resume, объединённые события, RX pause,
|
||
закрытие из callbacks, отмена событий и отсутствие утечек.
|
||
test_etcp_packet_link: UDP EAGAIN, два пути общего сокета, ACK rollback/commit.
|
||
test_etcp_driver: пустые conn, отказ bind без потери владения, копирование API,
|
||
два ядра без сокетов, защищённый INIT/DATA, сообщения 1500 байт, backpressure,
|
||
независимые драйверы и освобождение ресурсов.
|
||
Существующие проверки UDP/STCP/session сохраняют прежние ожидания.
|
||
sys=debug показывает состояние packet_link, etcp=debug — привязку/протокол.
|