BGP: фикс владения адресами в реестре (мульти-группа), проброс group_id в сервис (conn_mgr per-group), membership-фильтр create_group; тест media через chat-группу

This commit is contained in:
evgeny committed 2026-09-12 02:13:34 +03:00
1 parent 6c9a47b201
commit 42a94aa916
14 files changed
+324 -71

No files matched your search

+49 -23
View File
@@ -132,6 +132,21 @@ uint64_t* topo_node_best_hop_list(struct TOPO_GROUP_NODE* nq, uint8_t* out_count
return (uint64_t*)((uint8_t*)best + sizeof(struct TOPO_NODEPATH));
}
/* Освобождает списки адресов (sock_meta + addrs + reality) узла в глобальном реестре.
* Адреса — глобальная идентичность узла, шарится между группами через node_registry,
* поэтому освобождаются только при последнем unref (topo_node_registry_unref). */
static void topo_node_identity_free(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
if (!groups || !ni) return;
free_v4_sock_list(groups->v4_sock_meta_pool, ni->v4_sock_meta);
free_v4_addr_list(groups->v4_addr_pool, ni->v4_addrs);
free_v6_sock_list(groups->v6_sock_meta_pool, ni->v6_sock_meta);
free_v6_addr_list(groups->v6_addr_pool, ni->v6_addrs);
free_reality_sock_list(ni->reality_socks);
ni->v4_sock_meta = NULL; ni->v4_addrs = NULL;
ni->v6_sock_meta = NULL; ni->v6_addrs = NULL;
ni->reality_socks = NULL;
}
void topo_node_free_raw(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
if (!ni) return;
if (groups) {
@@ -151,18 +166,7 @@ void topo_node_destroy(struct TOPO_GROUPS* groups, struct TOPO_NODE* ni) {
void topo_nodeq_free_group_fields(struct TOPO_GROUPS* groups, struct TOPO_GROUP_NODE* nq) {
if (!groups || !nq) return;
struct TOPO_NODE* ni = topo_node_registry_find(groups, nq->node_id);
if (ni) {
free_v4_sock_list(groups->v4_sock_meta_pool, ni->v4_sock_meta);
free_v4_addr_list(groups->v4_addr_pool, ni->v4_addrs);
free_v6_sock_list(groups->v6_sock_meta_pool, ni->v6_sock_meta);
free_v6_addr_list(groups->v6_addr_pool, ni->v6_addrs);
free_reality_sock_list(ni->reality_socks);
ni->v4_sock_meta = NULL; ni->v4_addrs = NULL;
ni->v6_sock_meta = NULL; ni->v6_addrs = NULL;
ni->reality_socks = NULL;
topo_node_registry_unref(groups, nq->node_id);
}
topo_node_registry_unref(groups, nq->node_id);
if (nq->subnets) {
free_v4_sub_list(groups->v4_subnet_pool, nq->subnets->v4_subnets);
free_v6_sub_list(groups->v6_subnet_pool, nq->subnets->v6_subnets);
@@ -183,22 +187,42 @@ struct TOPO_NODE* topo_node_registry_find(struct TOPO_GROUPS* groups, uint64_t n
return node;
}
/* Является ли входящий узел полной идентичностью (BGP NODEINFO / локальный узел).
* Partial-узлы из invite/DB-load не несут ed25519 — по ним идентичность не перезаписываем. */
static int topo_node_is_full_identity(const struct TOPO_NODE* ni) {
for (int i = 0; i < SC_PUBKEY_SIZE; i++) if (ni->ed25519_public_key[i]) return 1;
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);
if (existing) {
int n4 = topo_list_count((struct _topo_head*)ni->v4_addrs);
int n6 = topo_list_count((struct _topo_head*)ni->v6_addrs);
int e4 = topo_list_count((struct _topo_head*)existing->v4_addrs);
int e6 = topo_list_count((struct _topo_head*)existing->v6_addrs);
int drop4 = (e4 && n4), drop6 = (e6 && n6);
if (drop4 || drop6)
DEBUG_WARN(DEBUG_CATEGORY_BGP, "registry_store: node=%016llx EXISTS — dropping new addrs v4=%d v6=%d (existing v4=%d v6=%d)",
(unsigned long long)ni->node_id, drop4 ? n4 : 0, drop6 ? n6 : 0, e4, e6);
topo_node_ref(existing);
if (!existing->v4_addrs && ni->v4_addrs) { existing->v4_addrs = ni->v4_addrs; ni->v4_addrs = NULL; }
if (!existing->v6_addrs && ni->v6_addrs) { existing->v6_addrs = ni->v6_addrs; ni->v6_addrs = NULL; }
if (!existing->reality_socks && ni->reality_socks) { existing->reality_socks = ni->reality_socks; ni->reality_socks = NULL; }
/* Идентичность (ver/имя/pubkeys/подпись) — авторитетна у полного NODEINFO,
* иначе реестр держит устаревший ver/имя и форвард nodeinfo ломает подпись. */
if (topo_node_is_full_identity(ni)) {
existing->ver = ni->ver;
existing->client_type = ni->client_type;
existing->client_activity = ni->client_activity;
memcpy(existing->public_key, ni->public_key, SC_PUBKEY_SIZE);
memcpy(existing->ed25519_public_key, ni->ed25519_public_key, SC_PUBKEY_SIZE);
memcpy(existing->x25519_self_sig, ni->x25519_self_sig, 64);
if (ni->node_name) {
if (existing->node_name) u_free(existing->node_name);
existing->node_name = ni->node_name; ni->node_name = NULL;
}
}
/* Адреса — глобальная идентичность. Обновляем каждый список, который входящий узел несёт
* (частичные узлы заполняют только то, что знают, не затирая остальное). */
if (ni->v4_sock_meta) { free_v4_sock_list(groups->v4_sock_meta_pool, existing->v4_sock_meta); existing->v4_sock_meta = ni->v4_sock_meta; ni->v4_sock_meta = NULL; }
if (ni->v4_addrs) { free_v4_addr_list(groups->v4_addr_pool, existing->v4_addrs); existing->v4_addrs = ni->v4_addrs; ni->v4_addrs = NULL; }
if (ni->v6_sock_meta) { free_v6_sock_list(groups->v6_sock_meta_pool, existing->v6_sock_meta); existing->v6_sock_meta = ni->v6_sock_meta; ni->v6_sock_meta = NULL; }
if (ni->v6_addrs) { free_v6_addr_list(groups->v6_addr_pool, existing->v6_addrs); existing->v6_addrs = ni->v6_addrs; ni->v6_addrs = NULL; }
if (ni->reality_socks) { free_reality_sock_list(existing->reality_socks); existing->reality_socks = ni->reality_socks; ni->reality_socks = NULL; }
topo_node_free_raw(groups, ni);
return existing;
}
@@ -223,6 +247,8 @@ void topo_node_registry_unref(struct TOPO_GROUPS* groups, uint64_t node_id) {
struct TOPO_NODE* ni = topo_node_registry_find(groups, node_id);
if (!ni) return;
uint32_t prev_ref = ni->group_ref_count;
if (prev_ref == 1)
topo_node_identity_free(groups, ni);
topo_node_unref(ni);
if (prev_ref == 1) {
struct ll_entry* e = groups->node_registry ? queue_find_data_by_index(groups->node_registry, &node_id) : NULL;