/* * node_conn_direct — общий прямой мультиадресный транспорт к узлу по node_id для BGP/topo_group. * Адреса узла используются для создания и обновления линков общего ETCP-соединения. * * Архитектурная роль NODE_CONN_DIRECT (NCD handle): * - выражает владение прямым транспортом, в том числе во время установления связи; * - группа удерживает его для своей BGP/topo_group-сессии; * - временный handle попытки подключения после установления связи должен перейти группе * либо быть закрыт; передачу владения выполняют через node_conn_direct_transfer(); * - не выражает длительность звонка или передачи файла: эту потребность хранит CONN_MGR_HANDLE. * CM подбирает оптимальный P2P-путь для больших объёмов данных (медиа, файлы, звонки), * а NCD управляет прямым транспортом и его адресами независимо от конкретной медиа-операции. * * Модуль управляет ETCP-соединениями через непрозрачные handle'ы (NODE_CONN_DIRECT). * Каждый владелец открывает свой handle; несколько handle разделяют ETCP_CONN. * close снимает только своё владение. Последний handle закрывает неготовый транспорт * сразу; для UP начинает CLOSE/KEEP_ALIVE (до 5 s), пир может сохранить соединение. * * Кто использует: * - conn_mgr (Connection Manager) — временные handle'ы попыток установления прямого транспорта * - topo_group — владеет транспортом групповой сессии с начала CONNECTING * - протокол join — временный транспорт до добавления участника * - любой модуль, кому нужно надёжное ETCP-соединение с конкретным node_id * * Переходы UP/DOWN/TIMEOUT/CLOSED доставляются синхронно. Закрытие любого handle * из callback безопасно. Начальное UP при open готового conn откладывается через uasync_call_soon. * Все операции — в потоке uasync. NCD не проверяет членство и готовность группы. */ #ifndef NODE_CONN_DIRECT_H #define NODE_CONN_DIRECT_H #include struct UTUN_INSTANCE; struct ETCP_CONN; struct TOPO_NODE; struct ETCP_SOCKET; /* ─── Return codes ─── */ #define NCD_NEW 0 /* создано новое соединение */ #define NCD_REUSED 1 /* переиспользовано существующее */ #define NCD_ERR -1 /* ошибка */ /* ─── Opaque handle ─── */ struct NODE_CONN_DIRECT; /* ─── Callback events (единый callback на handle) ─── */ enum ncd_event { NCD_EVENT_UP = 0, /* соединение поднялось (линки работают) */ NCD_EVENT_DOWN = 1, /* соединение упало */ NCD_EVENT_CLOSED = 3, /* транспорт окончательно удалён; get_conn=NULL, владелец закрывает handle */ NCD_EVENT_TIMEOUT = 2, /* срок первой попытки истёк; удерживаемый handle может получить поздний UP */ }; typedef void (*ncd_callback)(struct NODE_CONN_DIRECT* h, enum ncd_event event, void* arg); /* * Открыть handle к узлу по node_id. * Node info ищется через node_registry, fallback — SQLite. * cb вызывается при изменении статуса / таймауте. * Если conn уже готов — cb(NCD_EVENT_UP) через uasync_call_soon (не синхронно). * До первой отправки дождаться UP. Результат: NCD_NEW/NCD_REUSED или NCD_ERR. * При успехе вызывающий обязан закрыть *out_handle, в том числе после CLOSED. */ int node_conn_direct_open(struct UTUN_INSTANCE* inst, uint64_t node_id, ncd_callback cb, void* cb_arg, struct NODE_CONN_DIRECT** out_handle, struct ETCP_SOCKET* specific_sock); /* NULL — авто-подбор всех совместимых сокетов для линков */ /* * То же, но с уже загруженным TOPO_NODE (ni не владеем — можно передать временный на стеке). * ni должен содержать public_key, v4_addrs/v6_addrs для создания линков. */ int node_conn_direct_open_node(struct UTUN_INSTANCE* inst, uint64_t node_id, ncd_callback cb, void* cb_arg, struct NODE_CONN_DIRECT** out_handle, struct TOPO_NODE* ni, /* публичный ключ + адреса пира (не владеем) */ struct ETCP_SOCKET* specific_sock); /* NULL — авто-подбор */ /* Освободить handle и отменить его callbacks; другие владельцы сохраняют транспорт. */ void node_conn_direct_close(struct NODE_CONN_DIRECT* h); /* Применить принятую запись из общего реестра к уже существующему соединению. * Не создаёт соединение и не приобретает handle. Число новых линков или -1 при ошибке. */ int node_conn_direct_update_node(struct UTUN_INSTANCE* inst, uint64_t node_id); /* Как close, но последний handle закрывает транспорт сразу, без fin_wait. * При наличии других handle общий транспорт и их callbacks сохраняются. */ void node_conn_direct_force_close(struct NODE_CONN_DIRECT* h); /* Сменить или сбросить (cb=NULL) callback на уже открытом handle. * Не влияет на refcounting и состояние conn. */ void node_conn_direct_set_callback(struct NODE_CONN_DIRECT* h, ncd_callback cb, void* cb_arg); /* Передать владение handle новому владельцу (смена callback + arg). * После вызова handle принадлежит new_cb_arg, прежний владелец * должен забыть указатель. Соединение не трогается. */ void node_conn_direct_transfer(struct NODE_CONN_DIRECT* h, ncd_callback new_cb, void* new_cb_arg); /* Идентификатор узла; 0 для NULL. */ uint64_t node_conn_direct_node_id(const struct NODE_CONN_DIRECT* h); /* Заимствованный транспорт, в том числе до UP; NULL после CLOSED. Не закрывать напрямую. */ struct ETCP_CONN* node_conn_direct_get_conn(struct NODE_CONN_DIRECT* h); /* ─── Протокол CLOSE / KEEP_ALIVE (ETCP_RT_ID_NCD_CONTROL = 0x12) ─── */ #define NCD_SUBCMD_CLOSE 0x01 #define NCD_SUBCMD_KEEP_ALIVE 0x02 #pragma pack(push, 1) struct ncd_control_msg { uint8_t cmd; /* ETCP_RT_ID_NCD_CONTROL */ uint8_t subcmd; /* NCD_SUBCMD_CLOSE / KEEP_ALIVE */ uint64_t node_id; /* node_id отправителя */ }; #pragma pack(pop) #define NCD_CONTROL_MSG_SIZE sizeof(struct ncd_control_msg) /* ─── Управление линками на конкретном сокете ─── */ /* * ncd_add_socket_links — итерирует все активные NCD-соединения (ncd_registry), * для каждого загружает TOPO_NODE с адресами пира и создаёт линки (etcp_link_new) * на переданном сокете (только совместимые family: v4/v6). Аналог ncd_create_links * но вызывается извне (auto_socket) при добавлении нового интерфейса. * Возвращает количество созданных линков (0 если нечего добавить или ошибка). */ int ncd_add_socket_links(struct UTUN_INSTANCE* inst, struct ETCP_SOCKET* sock); /* * ncd_remove_socket_links — итерирует все активные NCD-соединения, * для каждого закрывает линки (etcp_link_close) привязанные к переданному сокету. * Вызывается при удалении сокета (интерфейс пропал). Возвращает количество закрытых линков. */ int ncd_remove_socket_links(struct UTUN_INSTANCE* inst, struct ETCP_SOCKET* sock); #endif