From 1a8072e9b2ceb33a155c1ccf524999f85d0862e4 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sun, 27 Sep 2026 20:08:17 +0300 Subject: [PATCH] Release group NCD ownership when destroying peers --- src/routing_layer/topo_group.c | 4 ++- tests/Makefile.am | 5 ++++ tests/test_group_ownership.c | 46 ++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 tests/test_group_ownership.c diff --git a/src/routing_layer/topo_group.c b/src/routing_layer/topo_group.c index 311d9c21..3425cbf3 100644 --- a/src/routing_layer/topo_group.c +++ b/src/routing_layer/topo_group.c @@ -396,7 +396,9 @@ static void topo_group_destroy(struct TOPO_GROUP* group) { struct ll_entry* e; while ((e = queue_data_get(group->senders_list)) != NULL) { - struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)e; + struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)e->data; + DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "group destroy: release peer=%016llx group=%016llx", + (unsigned long long)node_conn_direct_node_id(item->handle), (unsigned long long)group->group_id); if (item->handle) { node_conn_direct_close(item->handle); item->handle = NULL; } queue_entry_free(e); } diff --git a/tests/Makefile.am b/tests/Makefile.am index d5917a13..710dd58e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -64,6 +64,7 @@ check_PROGRAMS = \ test_invite_group_create \ test_etcp_connect \ test_node_conn_direct \ + test_group_ownership \ test_node_snapshot \ test_db_sync \ test_merkle_sync \ @@ -388,6 +389,10 @@ test_node_conn_direct_SOURCES = test_node_conn_direct.c test_node_conn_direct_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib test_node_conn_direct_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) +test_group_ownership_SOURCES = test_group_ownership.c +test_group_ownership_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib +test_group_ownership_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) + test_node_snapshot_SOURCES = test_node_snapshot.c test_node_snapshot_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib test_node_snapshot_LDADD = $(LIBUTUN) $(CRYPTO_LIBS) $(COMMON_LIBS) diff --git a/tests/test_group_ownership.c b/tests/test_group_ownership.c new file mode 100644 index 00000000..4ea1226c --- /dev/null +++ b/tests/test_group_ownership.c @@ -0,0 +1,46 @@ +#include +#include +#include "utun_instance.h" +#include "routing_layer/topo_group.h" +#include "transport_layer/etcp.h" +#include "transport_layer/node_conn_direct.h" +#include "../lib/u_async.h" +#include "../lib/debug_config.h" + +int main(void) { + debug_config_init(); debug_set_level(DEBUG_LEVEL_INFO); + utun_instance_set_tun_init_enabled(0); + struct UASYNC* ua = uasync_create(); assert(ua); + struct UTUN_INSTANCE* inst = utun_instance_create_from_str(ua, + "[global]\n" + "my_private_key=704f2e012c8fa8768130cb0f988a997dccb628372bc5ceccacc78dcbfec5916f\n" + "my_public_key=b3193173def895bd0fcea6f86af077c7d77216f10395275f627ac18242ec0f01\n" + "[server: udp]\naddr=127.0.0.1:0\ntype=public\n"); + assert(inst && utun_instance_init(inst) == 0); + struct TOPO_GROUP* a = topo_groups_create_group(inst->topo_groups, 42, TOPO_GROUP_TYPE_CHAT, NULL); + struct TOPO_GROUP* b = topo_groups_create_group(inst->topo_groups, 43, TOPO_GROUP_TYPE_CHAT, NULL); + assert(a && b); + struct SC_MYKEYS keys; assert(sc_generate_keypair(&keys) == SC_OK); + struct TOPO_ADDR4 addr = { .addr = {127, 0, 0, 1}, .port = 9, .protocol = TOPO_PROTO_UDP }; + struct TOPO_NODE node = { .v4_addrs = &addr }; + memcpy(node.public_key, keys.public_key, sizeof(node.public_key)); + node.node_id = sc_derive_node_id_from_pubkey(node.public_key); + struct NODE_CONN_DIRECT* owner = NULL; + assert(node_conn_direct_open_node(inst, node.node_id, NULL, NULL, &owner, &node, NULL) == NCD_NEW); + struct ETCP_CONN* conn = node_conn_direct_get_conn(owner); assert(conn); + /* Проверяем владение независимо от доставки пакетов и ответа удалённого узла. */ + assert(topo_group_new_conn(a, conn) == 0); + assert(topo_group_new_conn(a, conn) == 0 && queue_entry_count(a->senders_list) == 1); + assert(topo_group_new_conn(b, conn) == 0); + node_conn_direct_close(owner); + assert(!conn->close_requested); + topo_groups_remove_group(inst->topo_groups, 42); + assert(!conn->close_requested && queue_entry_count(b->senders_list) == 1); + topo_groups_remove_group(inst->topo_groups, 43); + /* Без внешнего владельца обе уничтоженные группы обязаны отпустить транспорт. */ + assert(conn->close_requested && !inst->ncd_registry); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "group ownership: duplicate attach, shared connection and final release passed"); + inst->running = 0; utun_instance_destroy(inst); + uasync_poll(ua, 0); uasync_destroy(ua, 0); + return 0; +}