# conn_mgr — Менеджер установки соединений ## 1. Назначение Трёхфазный асинхронный менеджер подключения к удалённым нодам. Отвечает за установку ETCP-соединения с выбором оптимального способа: 1. **DIRECT** — прямое INIT-рукопожатие со всеми известными IPv4-адресами цели (с проверкой NAT-совместимости) 2. **REVERSE** — если у нас прямой IP, а цель за NAT: отправляем наши адреса через BGP, цель подключается к нам 3. **INDIRECT** — обмениваемся через BGP списками кандидатов-посредников, выбираем общих по минимальной сумме RTT, трафик идёт через `etcp_router` Также выполняет фоновые задачи: периодический ping всех BGP-нод, поддержание списка лучших посредников, idle-таймаут для неактивных соединений, локальное сканирование сети. Типы соединений (итоговый результат): - `CONN_TYPE_DIRECT` (1) — прямое соединение - `CONN_TYPE_REVERSE` (2) — цель подключилась к нам - `CONN_TYPE_INDIRECT` (3) — через посредника ## 2. Как пользоваться ### Инициализация ```c struct CONN_MGR* mgr = conn_mgr_init(instance); // Регистрирует обработчик в etcp_router для ETCP_RT_ID_CONN_MGR (0x11) // Запускает фоновые таймеры: bg_ping, candidate_ping ``` ### Подключение ```c static void my_connect_cb(int result, uint64_t node_id, void* arg) { if (result == CONN_MGR_OK) { /* подключено */ } else if (result == CONN_MGR_ERR_TIMEOUT) { /* таймаут */ } else if (result == CONN_MGR_ERR_UNREACHABLE) { /* недостижима */ } } conn_mgr_connect_node(mgr, target_node_id, idle_timeout_ms, my_connect_cb, arg); ``` ### Отправка данных ```c struct ll_entry* entry = queue_entry_new(0); entry->dgram = data; entry->len = len; conn_mgr_send(mgr, node_id, entry); // entry освобождается внутри ``` ### Кандидаты-посредники Внешний код (обычно `route_connectivity`) вызывает `conn_mgr_update_best_candidates()` для заполнения списка лучших посредников (топ-3 по RTT). Список используется фазой INDIRECT. ### Нюансы - Повторный `connect_node` для уже подключённой ноды вернёт `CONN_MGR_ERR_ALREADY_CONNECTED` - Для ноды в состоянии CONNECTING новый вызов добавит ещё один callback в список ожидания - Для INDIRECT-соединений `conn_mgr_send` использует round-robin по выбранным посредникам - Пока существует активный ETCP-линк к ноде, немедленно возвращает CONNECTED ## 3. API ### Корневые структуры | Структура | Описание | |-----------|----------| | `CONN_MGR` | Корневая структура менеджера. Хранит массив `entries[]`, топ-3 `best_candidates`, таймеры (`bg_ping_timer`, `candidate_ping_timer`), списки `reverse_pending`/`exchange_pending`, `next_request_id` | | `CONN_MGR_ENTRY` | Запись о подключении к одной ноде: `state`, `conn_type`, `idle_timeout_ms`, список коллбэков `cb_list`, массив `intermediaries[]`, состояния `local_scan_state`/`main_connect_state`, текущая `main.phase` | | `CONN_MGR_CANDIDATE` | Пара `{node_id, rtt}` — запись о кандидате-посреднике (packed) | | `cm_cb_node` | Узел связного списка коллбэков для асинхронного результата подключения | | `cm_reverse_pending` | Запись об ожидании REVERSE-подключения (связный список) | | `cm_exchange_pending` | Запись об ожидании INDIRECT-обмена, включает кешированный ответ и таймер probe-повторов | ### Жизненный цикл | Функция | Описание | |---------|----------| | `conn_mgr_init(instance)` | Выделяет CONN_MGR, регистрирует `ETCP_RT_ID_CONN_MGR` в маршрутизаторе, запускает bg_ping и candidate_ping таймеры | | `conn_mgr_destroy(mgr)` | Отменяет таймеры, освобождает все entries, exchange_pending, reverse_pending | ### Подключение / отключение | Функция | Описание | |---------|----------| | `conn_mgr_connect_node(mgr, id, timeout, cb, arg)` | Запускает 3-фазное подключение. Если уже подключена — сразу callback с OK. Если в процессе — добавляет callback в список | | `conn_mgr_disconnect_node(mgr, id)` | Шлёт DISCONNECT пакет, сбрасывает `conn_mgr_type` в `NODEINFO_Q`, удаляет entry | | `conn_mgr_send(mgr, id, entry)` | Отправляет данные подключённой ноде через `etcp_router`; для INDIRECT — round-robin по посредникам; обновляет `last_traffic_tb` | | `conn_mgr_set_idle_timeout(mgr, id, ms)` | Устанавливает/снимает idle-таймер для ноды. При неактивности дольше `ms` — автоотключение | | `conn_mgr_get_status(mgr, id, &state, &type)` | Возвращает текущее состояние и тип соединения | ### Кандидаты-посредники | Функция | Описание | |---------|----------| | `conn_mgr_update_best_candidates(mgr, id, rtt)` | Вставляет/обновляет кандидата в отсортированном топ-3 по RTT. Худшие кандидаты вытесняются | ### Протокольные подкоманды (ETCP_RT_ID_CONN_MGR = 0x11) | Константа | Описание | |-----------|----------| | `CONN_MGR_SUBCMD_DIRECT_REQ` (0x01) | Фаза 2: "я за NAT, подключись ко мне" — наши адреса | | `CONN_MGR_SUBCMD_DIRECT_RESP` (0x02) | Ответ на DIRECT_REQ (зарезервирован) | | `CONN_MGR_SUBCMD_INTERM_EXCHANGE_REQ` (0x03) | Фаза 3 инициатор: наш топ-4 кандидатов | | `CONN_MGR_SUBCMD_INTERM_EXCHANGE_RESP` (0x04) | Фаза 3 ответ: свои + чужие кандидаты с RTT с обеих сторон | | `CONN_MGR_SUBCMD_INTERM_SELECTED` (0x05) | Фаза 3 финал: выбранные посредники | | `CONN_MGR_SUBCMD_DISCONNECT` (0x06) | Уведомление о разрыве | ### Пакеты протокола (все packed) | Структура | Поля | |-----------|------| | `CONN_MGR_DIRECT_REQ` | `cmd, subcmd, request_id, addr_count` + массив адресов `{type, ip[4], port, sock_id}` | | `CONN_MGR_DIRECT_RESP` | `cmd, subcmd, request_id, accepted` | | `CONN_MGR_INTERM_EXCHANGE_REQ` | `cmd, subcmd, request_id, candidate_count, candidates[4]` | | `CONN_MGR_INTERM_EXCHANGE_RESP` | `cmd, subcmd, request_id, my_count, your_count, my_candidates[4], your_candidates[4]` | | `CONN_MGR_INTERM_SELECTED` | `cmd, subcmd, request_id, count, selected[3]` | | `CONN_MGR_DISCONNECT` | `cmd, subcmd, node_id` | ### Коды возврата | Код | Значение | |-----|----------| | `CONN_MGR_OK` (0) | Успех | | `CONN_MGR_ERR_NOT_FOUND` (-1) | Нода не найдена в BGP | | `CONN_MGR_ERR_NO_ADDRESSES` (-2) | Нет адресов для подключения | | `CONN_MGR_ERR_TIMEOUT` (-3) | Таймаут | | `CONN_MGR_ERR_UNREACHABLE` (-4) | Недостижима (все фазы) | | `CONN_MGR_ERR_ALREADY_CONNECTED` (-6) | Уже подключены | | `CONN_MGR_ERR_INTERNAL` (-7) | Внутренняя ошибка | ### Ключевые константы | Константа | Значение | Смысл | |-----------|----------|-------| | `CONN_MGR_MAX_CANDIDATES` | 3 | Макс. число лучших посредников в списке | | `CONN_MGR_MAX_INTERMEDIARIES` | 3 | Макс. число выбранных посредников для одного соединения | | `CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS` | 5000 | Таймаут фазы DIRECT | | `CONN_MGR_CONNECT_REVERSE_TIMEOUT_MS` | 15000 | Таймаут фазы REVERSE | | `CONN_MGR_INTERM_EXCHANGE_TIMEOUT_MS` | 15000 | Таймаут фазы INDIRECT | | `CONN_MGR_CANDIDATE_STALE_TB` | 300000 | Порог устаревания кандидата (~30 сек) | | `CONN_MGR_CANDIDATE_PING_TB` | 20000 | Интервал ping кандидатов (~2 сек) | | `CONN_MGR_BG_PING_INTERVAL_TB` | 1000 | Интервал фонового ping нод (~100 мс) | | `CONN_MGR_BG_PING_CYCLE_MIN_TB` | 100000 | Мин. длительность цикла обхода всех нод (~10 сек) | | `CONN_MGR_IDLE_CHECK_INTERVAL_TB` | 10000 | Интервал проверки idle (~1 сек) | | `CONN_MGR_LOCAL_SCAN_ATTEMPTS` | 3 | Попыток локального сканирования |