Files
utun2/src/control_server_doc.md
T

76 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Control Server (control_server)
## 1. Назначение
TCP-сервер для мониторинга ETCP-соединений. Принимает подключения от GUI-клиента `etcpmon`, отдаёт по запросу метрики соединений/каналов/TUN/роутера, список узлов BGP-топологии, позволяет менять уровни отладки на лету. Уведомляет подписанных клиентов об изменениях узлов через `control_server_notify_node_change()`.
## 2. Как пользоваться
1. Вызвать `control_server_init()` — создаёт слушающий TCP-сокет на адресе из конфига `control_sock`, регистрирует accept-колбэк в uasync.
2. Выполнять цикл uasync: read-колбэк сам принимает и разбирает команды. Периодический вызов
`control_server_process_updates()` не требуется; эта функция лишь повторно разбирает уже накопленные данные.
3. При изменении/удалении узла UTUN-группы вызывать `control_server_notify_node_change()` /
`control_server_notify_node_removed()` — сервер отметит ID и отправит актуальное состояние при освобождении TX.
4. При остановке вызвать `control_server_shutdown()`.
**Нюансы:**
- Доступ разрешён только IPv4-клиентам по `control_allow` в конфиге; без правил доступ запрещён. IPv6-клиенты отклоняются.
- В покое клиент отключается после 30 секунд без команд. При активной отправке тот же таймер
отсчитывает 30 секунд без положительного `send()`; поступление команд его не продлевает.
- Лог пишется в `control_server.log`: дампы содержат первые 256 байт каждого чтения RX и некоторых ответов TX.
- `control_server_process_updates()` разбирает команды; метрики отправляются только по `CMD_GET_METRICS`.
- Очередь отправки владеет исходными буферами до полной отправки или отключения; частичная отправка хранит отдельное смещение.
- В TX помещается один кадр до 32 КиБ. Следующий producer ждёт пустой очереди через deferred
`queue_waiter_wait()`. Чтение сокета и разбор уже принятого RX-буфера приостановлены до освобождения TX.
- Подписка сохраняет ID текущих узлов (`8 × N` байт), сериализует их по одному при освобождении TX.
Узлы повторно ищутся по ID; удалённые до своей очереди пропускаются. После начального списка
отправляется `NODE_INFO_END` с seq запроса, затем накопленные live-изменения.
- Live-изменения объединяются по ID (последнее обновление/удаление); предел — 256 различных ID.
При переполнении подписчик отключается с WARN. CHAT-узлы в эту подписку не входят.
- При stop/ошибке отменяются timer и waiter, включая уже запланированный callback, затем освобождаются
список ID и TX-буфер. `control_client_send()` сам клиента не освобождает: ошибку обрабатывает владелец callback.
- Если список сокетов превышает предел сообщения (32 768 байт; сейчас помещается 230 записей),
возвращается `RSP_ERROR` с кодом `SERVER_BUSY`. Список не усекается; сокеты `probe_only` не учитываются.
- `SET_DEBUG_CONFIG` требует ровно `2 + category_count` байт, не более 64 категорий.
Несоответствие длины закрывает соединение без применения настроек.
## 3. API
### Структуры
| Структура | Назначение |
|-----------|-----------|
| `struct control_server` | Состояние сервера: `listen_fd`, связный список `clients`, uasync-контекст, счётчик клиентов. |
| `struct control_client` | Состояние клиента: `fd`, буфер приёма (`recv_buffer`), `output_queue` для асинхронной отправки, `selected_peer_id`, флаг подписки на узлы. |
### Функции
| Функция | Назначение |
|---------|-----------|
| `control_server_init(server, ua, instance, bind_addr, max_clients)` | Создать слушающий сокет, зарегистрировать в uasync. Возвращает 0 / -1. |
| `control_server_shutdown(server)` | Закрыть всех клиентов, освободить слушающий сокет, закрыть лог-файл. |
| `control_server_process_updates(server)` | Повторно разобрать накопленные данные всех клиентов; вызов необязателен. |
| `control_server_get_client_count(server)` | Вернуть количество подключённых клиентов. |
| `control_server_notify_node_change(server, node)` | Разослать подписанным клиентам сериализованную информацию об узле. |
| `control_server_notify_node_removed(server, node_id)` | Разослать подписанным клиентам уведомление об удалении узла. |
### Поддерживаемые команды ETCPMON
| Команда | Ответ | Описание |
|---------|-------|----------|
| `CMD_LIST_CONN` | `RSP_CONN_LIST` | Список активных ETCP-соединений. |
| `CMD_SELECT_CONN` | — | Выбрать соединение по `peer_node_id` для метрик. |
| `CMD_GET_METRICS` | `RSP_METRICS` | Полные метрики: ETCP, TUN, router, все каналы с BBR. |
| `CMD_LIST_SOCKETS` | `RSP_SOCKET_LIST` | Список локальных сокетов с NAT-типом и NAT-адресом. |
| `CMD_ACTION` | `RSP_ACTION_RESULT` или `RSP_ERROR`, с seq запроса | Полные имена `"nodes"`/`"nat"`; `nat` подтверждает запуск проверки, неизвестное имя даёт ошибку. |
| `CMD_GET_DEBUG_CONFIG` | `RSP_DEBUG_CONFIG` | Текущие уровни отладки (глобальный + по категориям). |
| `CMD_SET_DEBUG_CONFIG` | — | Установить уровни отладки. |
| `CMD_SUBSCRIBE_NODES` | `RSP_NODE_INFO` (список) + `RSP_NODE_INFO_END` | Подписка на изменения узлов + текущий список. |
| `CMD_DISCONNECT` | — | Отключение клиента. |
Общий формат задаёт `tools/etcpmon/etcpmon_protocol.h`: 4-байтовый заголовок с `seq_id`, packed-структуры,
целые в порядке байтов хоста, без согласования версии/шифрования. Обычный ответ копирует `seq_id`
запроса; снимки `NODE_INFO` имеют `seq=0`, маркер `NODE_INFO_END` — seq запроса подписки.
`NODE_INFO` содержит префикс `01 04` и результат `topo_node_serialize()` для UTUN с подсетями.
Action требует ровно 32 байта payload с NUL внутри поля. Повреждённая команда закрывает соединение;
неизвестное корректное имя или недоступная служба возвращают `RSP_ERROR` без разрыва TCP.