139 lines
9.2 KiB
C
139 lines
9.2 KiB
C
/*
|
|
* 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 <stdint.h>
|
|
|
|
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
|