Update datagram and TCP exit documentation for explicit ownership

This commit is contained in:
evgeny committed 2026-10-24 13:42:20 +02:00
1 parent 2894e06014
commit 5914e26579
3 files changed
+27 -18

No files matched your search

+12 -9
View File
@@ -9,18 +9,19 @@
Каждый `UTUN_INSTANCE` владеет отдельным `inst->icmp_proxy`, глобального контекста нет.
`init(inst, ua)` задаёт таймаут 50000 tb (5 с), случайное начало `next_token` и
сохраняет `server.enabled` в `is_exit`. Для exit открывает один неблокирующий
`AF_INET/SOCK_RAW/IPPROTO_ICMP` и регистрирует его чтение в uasync.
регистрирует общий binding. Raw socket отдельно запускает `icmp_proxy_enable_exit(inst)`:
один неблокирующий `AF_INET/SOCK_RAW/IPPROTO_ICMP` регистрируется в uasync до публикации.
Повторный init сохраняет существующий контекст и возвращает 0. Ошибка создания
контекста или случайного token возвращает -1. Ошибка raw socket/регистрации
оставляет контекст без рабочего сокета, но init возвращает 0 и запрашивает router binding;
результат bind также не пробрасывается. Поэтому успешный init сам по себе не подтверждает
возможность отправки реального ping. Raw socket требует соответствующих прав ОС.
контекста/случайного token/binding возвращает отрицательный код без публикации контекста.
`enable_exit` возвращает -errno при отказе raw socket/nonblocking/регистрации, сохраняя
общий контекст и приём клиентских REPLY. Instance трактует отсутствие прав/поддержки raw
как отключение только ICMP exit с WARN; отказ обязательного ресурса прерывает создание instance.
TCP client/server не создают и не уничтожают общий контекст.
`test_loopback` по умолчанию выключен. `icmp_proxy_set_test_loopback(inst, 1)` разрешает
виртуальный REPLY **только при отсутствии raw socket**; открытый сокет имеет приоритет,
флаг его не отключает. Без контекста setter ничего не делает.
виртуальный REPLY явно, закрывая ранее открытый raw socket. Переключение при pending-запросах
отклоняется с WARN; без контекста setter ничего не делает. Production fallback без сети отсутствует.
## Запрос и сопоставление ответа
@@ -35,11 +36,13 @@ Raw reader проверяет IPv4 IHL/протокол, Echo Reply type/code и
Данные ответа берутся из raw пакета. Сохранённый в request префикс payload до 1500 байт
для формирования ответа не используется; он не ограничивает длину реального echo payload.
Таймер запускается после первого отправленного запроса, затем каждые 5 с, пока pending
Таймер резервируется до первого raw send, затем продлевается каждые 5 с, пока pending
не пуст. Удаляет записи с возрастом **больше** 5 с на очередном обходе; удаление не происходит
точно в момент достижения порога. `destroy` снимает binding, отменяет таймер, закрывает
raw socket/регистрацию, освобождает pending и обнуляет `inst->icmp_proxy`.
Все действия — в uasync; `inst` и `ua` заимствуются до destroy.
Отказ таймера до отправки отклоняет запрос; отказ продления освобождает все pending с ERROR.
Запрос без действующего таймера в pending не публикуется.
## Сообщения и доставка
+5 -5
View File
@@ -9,10 +9,10 @@
Контекст встроен в `inst->tcp_proxy_server`. `init(inst)` обнуляет его, читает
`config->global.tcp_proxy_server_enabled`, при включении регистрирует сервис
`ETCP_RT_ID_TCP_PROXY_SERVER` (0x04) и вызывает UDP/ICMP init независимо от наличия клиента.
`ETCP_RT_ID_TCP_PROXY_SERVER` (0x04).
NULL inst даёт -1; отсутствие config или отключённый сервер дают 0 без binding.
Результаты bind/UDP/ICMP init не пробрасываются: 0 не гарантирует готовность всех сервисов.
Повторный init при живых потоках недопустим.
Занятый binding/ошибка bind возвращает -1; enabled выставляется только после успеха.
Повторный init отклоняется. Общие UDP/ICMP создаёт и уничтожает instance независимо от TCP-модулей.
INI-парсер включает сервер при обработке параметра секции `[tcp_proxy_server]`.
Поддержанные ключи: `tcp_recv_buf`, `fib`, `so_mark`, `netif`, `bind_ip`,
@@ -79,7 +79,7 @@ DATA retry и диагностический таймер, уничтожает
через uasync_call_soon, чтобы текущая синхронная доставка могла проверить freed.
Указатель нельзя использовать как живой поток после conn_free.
destroy выключает сервер, снимает binding и уничтожает общие UDP/ICMP-контексты.
Клиент того же instance должен быть остановлен раньше; ua должен обработать отложенные free.
destroy выключает сервер и снимает только его binding; общие UDP/ICMP-контексты сохраняются.
Instance останавливает proxy до разборки UTUN-группы и транспорта; ua обрабатывает отложенные free.
Все операции выполняются в uasync. Каждую секунду диагностический таймер пишет
размеры TCP-очередей, наличие write_buf, кеши пулов и OS socket buffers на уровне proxy=trace.
+10 -4
View File
@@ -8,8 +8,8 @@
## Контекст и жизненный цикл
Контекст принадлежит `inst->udp_proxy`, глобального контекста нет. `init(inst, ua)`
создаёт его и запрашивает router binding, повторный init возвращает 0, сохраняя контекст.
`is_exit` — снимок роли при init, но диспетчер проверяет текущее
создаёт его вместе с router binding, повторный init с тем же ua возвращает 0, сохраняя контекст.
Контекст публикуется только после успеха; TCP client/server им не управляют. Диспетчер проверяет текущее
`inst->tcp_proxy_server.enabled` для REQUEST. REPLY принимается только при наличии
`tcp_proxy_client` и совпадении peer с его `via_node_id`. Один instance может совмещать роли.
@@ -18,12 +18,18 @@ Exit индексирует flows линейным списком по
неблокирующий `AF_INET/SOCK_DGRAM`, привязанный к `INADDR_ANY:0`, и read callback в uasync.
Ответ принимается только от исходного `dst_ip:dst_port`; в REPLY адреса и порты меняются местами.
REQUEST и принятый ответ обновляют `last_activity_tb`.
Новый flow публикуется после socket/nonblocking/bind/read registration и создания таймера.
Отказ любого этапа освобождает новый flow целиком. Результат sendto проверяется по точной длине:
нулевая датаграмма с sent=0 успешна, EINTR повторяется, остальные ошибки/короткий send
логируются с peer/tuple/длиной/errno. Датаграмма отбрасывается без добавления очереди повторов;
рабочий flow сохраняется, невалидный сокет удаляется.
Таймер запускается при первом flow и проверяет список каждые 600000 tb (60 с),
пока flows остаются. Удаляет flow при неактивности **больше** 60 с; удаление происходит
на очередном обходе, а не точно в момент достижения порога. `destroy` снимает binding,
отменяет таймер, закрывает сокеты/регистрации и обнуляет `inst->udp_proxy`.
Все операции выполняются в uasync; `inst` и `ua` заимствуются до destroy.
Отказ продления таймера закрывает оставшиеся flows с ERROR, не оставляя их без механизма очистки.
## Сообщения и доставка
@@ -44,5 +50,5 @@ router перед подкомандой, поэтому заголовок пр
Возврат 0 означает постановку в очередь; -1 — отсутствие TUN, недопустимый размер
или ошибку выделения. Входной payload остаётся у вызывающего кода.
`recv_cb` принимает владение entry/dgram при любом исходе. `init` не пробрасывает
ошибку router bind, поэтому 0 не подтверждает работоспособность регистрации.
`recv_cb` принимает владение entry/dgram при любом исходе. `init` возвращает -1 при
неверных аргументах, другом ua, занятом binding или ошибке выделения/регистрации.