You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

128 lines
7.9 KiB

/*
* node_conn_direct — общий прямой транспорт к узлу по node_id.
*
* Модуль управляет ETCP-соединениями через непрозрачные handle'ы (NODE_CONN_DIRECT).
* Каждый владелец открывает свой handle; несколько handle разделяют ETCP_CONN.
* close снимает только своё владение. Последний handle закрывает неготовый транспорт
* сразу; для UP начинает CLOSE/KEEP_ALIVE (до 5 s), пир может сохранить соединение.
*
* Кто использует:
* - conn_mgr (Connection Manager) — создаёт handle'ы для DIR/REV/IND-соединений
* - 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