topo: комментарии к функциям topo_node/topo_group

conn_mgr: src node_id вместо conn->peer_node_id, препенд ETCP_RT_ID_CONN_MGR к dgram, bind CONN_MGR после etcp_router_init

call: guard CALL_ST_CONNECTING при accept
This commit is contained in:
evgeny committed 2026-09-17 17:30:05 +03:00
1 parent 1fce405204
commit e7fc69bb1d
7 files changed
+95 -19

No files matched your search

+29
View File
@@ -18,16 +18,19 @@
#include "../lib/u_async.h"
#include "../ntp_time.h"
/* Инкремент refcount узла: держит TOPO_NODE живым, пока на него ссылаются группы. */
void topo_node_ref(struct TOPO_NODE* ni) {
if (!ni) return;
ni->group_ref_count++;
}
/* Инкремент refcount узла в глобальном реестре по node_id (взял ссылку через реестр). */
void topo_node_registry_ref(struct TOPO_GROUPS* groups, uint64_t node_id) {
struct TOPO_NODE* ni = topo_node_registry_find(groups, node_id);
if (ni) ni->group_ref_count++;
}
/* Декремент refcount; при обнулении освобождает имя узла и сам TOPO_NODE. */
void topo_node_unref(struct TOPO_NODE* ni) {
if (!ni) return;
if (--ni->group_ref_count == 0) {
@@ -36,6 +39,7 @@ void topo_node_unref(struct TOPO_NODE* ni) {
}
}
/* Освобождают односвязные списки структур узла (sock_meta/адреса/подсети v4,v6) из memory_pool. */
static void free_v4_sock_list(struct memory_pool* pool, struct TOPO_SOCKMETA4* head) {
while (head) { struct TOPO_SOCKMETA4* next = head->next; memory_pool_free(pool, head); head = next; }
}
@@ -54,10 +58,12 @@ static void free_v4_sub_list(struct memory_pool* pool, struct TOPO_SUBNET4* head
static void free_v6_sub_list(struct memory_pool* pool, struct TOPO_SUBNET6* head) {
while (head) { struct TOPO_SUBNET6* next = head->next; memory_pool_free(pool, head); head = next; }
}
/* Освобождает список reality-сокетов узла (выделялся u_calloc). */
static void free_reality_sock_list(struct TOPO_REALITY_SOCK* head) {
while (head) { struct TOPO_REALITY_SOCK* next = head->next; u_free(head); head = next; }
}
/* Ищет reality-параметры сокета узла по socket_id (NULL, если сокет без reality). */
const struct TOPO_REALITY_SOCK* topo_node_find_reality_sock(const struct TOPO_NODE* ni, uint8_t socket_id) {
if (!ni) return NULL;
for (const struct TOPO_REALITY_SOCK* r = ni->reality_socks; r; r = r->next)
@@ -65,6 +71,7 @@ const struct TOPO_REALITY_SOCK* topo_node_find_reality_sock(const struct TOPO_NO
return NULL;
}
/* Копирует reality-параметры узла в link->reality и поднимает флаг reality_set. */
void topo_node_apply_reality(struct ETCP_LINK* link, const struct TOPO_REALITY_SOCK* rs) {
if (!link || !rs) return;
memcpy(link->reality.server_static_pubkey, rs->server_pubkey, REALITY_AUTH_KEY_SIZE);
@@ -147,6 +154,7 @@ static void topo_node_identity_free(struct TOPO_GROUPS* groups, struct TOPO_NODE
ni->reality_socks = NULL;
}
/* Полностью освобождает TOPO_NODE со всеми списками и именем (без учёта refcount). */
void topo_node_free_raw(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
if (!ni) return;
if (groups) {
@@ -160,10 +168,12 @@ void topo_node_free_raw(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
u_free(ni);
}
/* Публичная обёртка free_raw — уничтожение узла глобального реестра. */
void topo_node_destroy(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
topo_node_free_raw(groups, ni);
}
/* Освобождает per-group поля TOPO_GROUP_NODE: unref идентичности в реестре + подсети, сброс handle. */
void topo_nodeq_free_group_fields(struct TOPO_GROUPS* groups, struct TOPO_GROUP_NODE* nq) {
if (!groups || !nq) return;
topo_node_registry_unref(groups, nq->node_id);
@@ -178,6 +188,7 @@ void topo_nodeq_free_group_fields(struct TOPO_GROUPS* groups, struct TOPO_GROUP_
// ===== глобальный реестр TOPO_NODE =====
/* Ищет TOPO_NODE в глобальном реестре по node_id (NULL, если узла нет). */
struct TOPO_NODE* topo_node_registry_find(struct TOPO_GROUPS* groups, uint64_t node_id) {
if (!groups || !groups->node_registry) return NULL;
struct ll_entry* e = queue_find_data_by_index(groups->node_registry, &node_id);
@@ -194,6 +205,7 @@ static int topo_node_is_full_identity(const struct TOPO_NODE* ni) {
return 0;
}
/* Кладёт узел в реестр; если он уже есть — обновляет идентичность/адреса и возвращает существующий. */
struct TOPO_NODE* topo_node_registry_store(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
if (!groups || !ni) return NULL;
struct TOPO_NODE* existing = topo_node_registry_find(groups, ni->node_id);
@@ -242,6 +254,7 @@ struct TOPO_NODE* topo_node_registry_store(struct TOPO_GROUPS* groups, struct TO
return ni;
}
/* Снимает ссылку группы на узел; при последней — чистит идентичность и удаляет запись из реестра. */
void topo_node_registry_unref(struct TOPO_GROUPS* groups, uint64_t node_id) {
if (!groups) return;
struct TOPO_NODE* ni = topo_node_registry_find(groups, node_id);
@@ -258,6 +271,7 @@ void topo_node_registry_unref(struct TOPO_GROUPS* groups, uint64_t node_id) {
// ===== serialization =====
/* Собирает канонический буфер для Ed25519-подписи узла (id, ver, pubkey, имя, тип, адреса). */
int topo_node_build_sig_msg(struct TOPO_NODE* ni, uint8_t* buf, size_t buf_size) {
if (!ni || !buf || buf_size < 64 + 9) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "build_sig_msg: invalid args"); return -1; }
size_t off = 0;
@@ -311,6 +325,7 @@ int topo_node_build_sig_msg(struct TOPO_NODE* ni, uint8_t* buf, size_t buf_size)
return (int)off;
}
/* Подписывает свой узел Ed25519: build_sig_msg + sc_ed25519_sign → ni->x25519_self_sig. */
void topo_node_sign_self(struct UTUN_INSTANCE* instance, struct TOPO_NODE* ni) {
if (!instance || !ni) return;
uint8_t sig_msg[TOPO_SIG_MSG_MAX_SIZE];
@@ -319,6 +334,7 @@ void topo_node_sign_self(struct UTUN_INSTANCE* instance, struct TOPO_NODE* ni) {
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Ed25519 self-sign FAILED for node=%016llx", (unsigned long long)ni->node_id);
}
/* Вычисляет суммарный размер динамической части NODEINFO по счётчикам заголовка. */
int topo_node_dyn_size(const struct TOPOMSG_NODE* msg) {
return msg->node_name_len
+ msg->local_v4_sockets * sizeof(struct TOPOMSG_SOCKMETA4)
@@ -332,6 +348,7 @@ int topo_node_dyn_size(const struct TOPOMSG_NODE* msg) {
+ msg->hop_count * 8;
}
/* Сериализует узел в wire-формат NODEINFO (заголовок + имя + адреса + подсети + hop_list). */
int topo_node_serialize(struct TOPO_NODE* ni, struct TOPO_GROUP_NODE* nq,
uint64_t group_id, uint8_t flags,
uint8_t* out, size_t out_max, uint16_t cumulative_rtt) {
@@ -412,6 +429,7 @@ int topo_node_serialize(struct TOPO_NODE* ni, struct TOPO_GROUP_NODE* nq,
// ===== deserialization =====
/* Разбирает wire-формат NODEINFO в TOPO_NODE + подсети/hop_list/cumulative_rtt (память через пулы). */
int topo_node_deserialize(struct TOPO_GROUP* group, const uint8_t* data, size_t len, struct TOPO_NODE** out_ni, struct TOPO_NODESUBNETS** out_subnets,
uint64_t** out_hop_list, uint8_t* out_hop_count,
uint16_t* out_cumulative_rtt) {
@@ -531,6 +549,7 @@ int topo_node_deserialize(struct TOPO_GROUP* group, const uint8_t* data, size_t
return 0;
}
/* Ищет per-group узел TOPO_GROUP_NODE в группе по node_id (NULL, если нет). */
struct TOPO_GROUP_NODE* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t node_id) {
if (!group || !group->nodes) return NULL;
uint64_t key = node_id;
@@ -538,6 +557,7 @@ struct TOPO_GROUP_NODE* topo_node_find_by_id(struct TOPO_GROUP* group, uint64_t
return e ? (struct TOPO_GROUP_NODE*)e : NULL;
}
/* Решает, нужен ли ping узлу: да, если в любой группе last_ping старше PING_TTL_TB. */
int topo_node_ping_request_cbk(struct TOPO_GROUPS* groups, uint64_t node_id) {
if (!groups || !groups->group_list) return 0;
uint64_t now = get_time_tb();
@@ -560,6 +580,7 @@ int topo_node_ping_request_cbk(struct TOPO_GROUPS* groups, uint64_t node_id) {
return 0;
}
/* Обновляет RTT/last_ping узла во всех группах, пишет RTT в БД и уведомляет подписчиков. */
void topo_node_ping_update_rtt(struct TOPO_GROUPS* groups, uint64_t node_id, uint16_t rtt) {
if (!groups || !groups->group_list) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "ping_update_rtt: no groups, node=%016llx rtt=%u", (unsigned long long)node_id, (unsigned)rtt);
@@ -588,6 +609,7 @@ void topo_node_ping_update_rtt(struct TOPO_GROUPS* groups, uint64_t node_id, uin
}
}
/* Суммарный RTT цепочки до узла: минимальный (rtt_last + cumulative_rtt) среди живых путей. */
uint16_t topo_get_chain_rtt(struct TOPO_GROUP_NODE* nq) {
if (!nq || !nq->paths || !nq->paths->head) {
return 0xFFFF;
@@ -606,6 +628,7 @@ uint16_t topo_get_chain_rtt(struct TOPO_GROUP_NODE* nq) {
// ===== dump / format =====
/* Есть ли у узла непустая диагностика связности (статусы/таймстемпы проб). */
static int is_node_connectivity_active(struct TOPO_CONNECTIVITY* c) {
return c->probe_status != PROBE_STATUS_NONE
|| c->interface_status != PROBE_RESULT_UNKNOWN
@@ -616,6 +639,7 @@ static int is_node_connectivity_active(struct TOPO_CONNECTIVITY* c) {
|| c->last_ping_time != 0;
}
/* Читаемое имя статуса/результата пробы и типа conn_mgr для дампа. */
static const char* probe_status_str(uint8_t s) {
switch (s) { case 0: return "NONE"; case 1: return "IN_PROGRESS"; case 2: return "DONE"; default: return "?"; }
}
@@ -626,6 +650,7 @@ static const char* conn_mgr_type_str(uint8_t t) {
switch (t) { case 1: return "DIRECT"; case 2: return "REVERSE"; case 3: return "INDIRECT"; default: return "NONE"; }
}
/* Выводит в лог полный дамп узлов группы (адреса, пути, связность, conn_mgr). */
void topo_node_dump_all(struct TOPO_GROUP* group) {
if (!group || !group->nodes) return;
@@ -713,6 +738,7 @@ void topo_node_dump_all(struct TOPO_GROUP* group) {
}
}
/* То же, что dump_all, но в строковый буфер (для control-сервера). */
int topo_node_format_all(struct TOPO_GROUP* group, char* buf, size_t buf_size) {
if (!group || !group->nodes || !buf || buf_size == 0) return 0;
int pos = 0;
@@ -804,6 +830,7 @@ int topo_node_format_all(struct TOPO_GROUP* group, char* buf, size_t buf_size) {
// ===== update my nodeinfo =====
/* Пересоздаёт local_node группы при изменении имени/подсетей/ключей, инкрементируя версию. */
int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GROUP* group) {
if (!instance || !group) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args"); return -1; }
size_t name_len = 0;
@@ -897,6 +924,7 @@ int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GR
return vc;
}
/* Пересобирает списки адресов своего узла из ETCP-сокетов; при изменении — подпись, БД, рассылка. */
int topo_node_update_my_addresses(struct UTUN_INSTANCE* instance) {
if (!instance || !instance->topo_groups) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args"); return -1; }
struct TOPO_GROUP* default_group = topo_groups_get_default(instance->topo_groups);
@@ -1065,6 +1093,7 @@ int topo_node_update_my_addresses(struct UTUN_INSTANCE* instance) {
return changed ? 1 : 0;
}
/* Callback изменения сокета (адрес/статус) — инициирует пересборку адресов своего узла. */
void topo_node_on_socket_changed(struct ETCP_SOCKET* sock, int event, void* arg) {
(void)arg;
if (!sock || !sock->instance) return;