From 5e63bc2a4297d5ec4cdd501f0779b6639d79ffe7 Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 26 Oct 2026 01:07:07 +0100 Subject: [PATCH] Share atomic network index construction and typed socket teardown --- src/utun_instance.c | 70 ++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/src/utun_instance.c b/src/utun_instance.c index f1dfba7d..b382a117 100644 --- a/src/utun_instance.c +++ b/src/utun_instance.c @@ -93,11 +93,49 @@ static int local_sockaddr_equal(const struct sockaddr_storage *a, const struct s if (a->ss_family == AF_INET6) { const struct sockaddr_in6 *ia = (const struct sockaddr_in6 *)a; const struct sockaddr_in6 *ib = (const struct sockaddr_in6 *)b; - return memcmp(&ia->sin6_addr, &ib->sin6_addr, 16) == 0 && ia->sin6_port == ib->sin6_port; + return memcmp(&ia->sin6_addr, &ib->sin6_addr, 16) == 0 && ia->sin6_port == ib->sin6_port && ia->sin6_scope_id == ib->sin6_scope_id; } return 0; } +/* Собирает самостоятельный индекс сетей; любой отказ освобождает только новую очередь. */ +static struct ll_queue* instance_build_networks(struct UASYNC* ua, const struct CFG_NETWORK* networks) { + struct ll_queue* queue = queue_new(ua, 16, offsetof(struct NETWORK_ENTRY, id), 7, "networks"); + if (!queue) { DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "cannot create network index"); return NULL; } + for (const struct CFG_NETWORK* net = networks; net; net = net->next) { + struct ll_entry* entry = queue_entry_new(sizeof(struct NETWORK_ENTRY)); + if (!entry) { DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "cannot allocate network %s", net->name); goto fail; } + struct NETWORK_ENTRY* item = (struct NETWORK_ENTRY*)entry->data; + if (net->id > UINT64_C(0x00ffffffffffffff) || + sc_hex_to_binary(net->pubkey_hex, item->pubkey, sizeof(item->pubkey)) != SC_OK || + sc_hex_to_binary(net->signing_key_hex, item->signing_key, sizeof(item->signing_key)) != SC_OK) { + DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "invalid id/keys for network %s", net->name); queue_entry_free(entry); goto fail; + } + item->id = net->id; snprintf(item->name, sizeof(item->name), "%s", net->name); + if (queue_data_put_with_index(queue, entry) < 0) { + DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "cannot index network %s", net->name); goto fail; + } + DEBUG_DEBUG(DEBUG_CATEGORY_CONFIG, "network indexed name=%s id=%014llx", net->name, (unsigned long long)net->id); + } + return queue; +fail: + queue_clear(queue); queue_free(queue); return NULL; +} + +/* Удаляет listener и правильную модель UDP/TCP, не оставляя сервер с заимствованным socket. */ +static void instance_remove_socket(struct UTUN_INSTANCE* instance, struct ETCP_SOCKET* socket) { + uint8_t id = socket->sock_id; uint64_t generation = socket->generation; + ncd_remove_socket_links(instance, socket); + socket = instance->etcp_sockets; + while (socket && (socket->sock_id != id || socket->generation != generation)) socket = socket->next; + if (!socket) return; // callback уже удалил endpoint + if (socket->is_tcp) { + struct stcp_server* listener = stcp_server_list_find_by_sock(instance, socket); + if (listener) { stcp_server_list_remove(instance, listener); stcp_link_server_destroy(listener); } + tcp_socket_remove(socket); + } else etcp_socket_remove(socket); +} + // Common initialization function (called by both create functions) // Returns 0 on success, -1 on error (instance is NOT freed on error - caller must handle) static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* ua, struct utun_config* config) { @@ -164,38 +202,12 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "Ed25519 pubkey derived successfully"); if (etcp_padding_start(&instance->padding, ua, instance->name) < 0) return -1; - // Initialize networks queue (indexed by 56-bit network id) - instance->networks = queue_new(ua, 16, offsetof(struct NETWORK_ENTRY, id), 7, "networks"); - if (!instance->networks) { - DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to create networks queue"); - return -1; - } - // Initialize connection queue + instance->networks = instance_build_networks(ua, config->networks); + if (!instance->networks) return -1; instance->connections = queue_new(ua, 256, 0, 8, "connections"); if (!instance->connections) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create connections queue"); return -1; } instance->tcp_connections = queue_new(ua, 256, offsetof(struct tcp_conn_entry, node_id), sizeof(uint64_t), "tcpconn"); if (!instance->tcp_connections) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create tcp_connections queue"); return -1; } - struct CFG_NETWORK *net = config->networks; - while (net) { - struct ll_entry *entry = queue_entry_new(sizeof(struct NETWORK_ENTRY)); - if (!entry) { - DEBUG_ERROR(DEBUG_CATEGORY_SYS, "Failed to allocate network entry for %s", net->name); - return -1; - } - struct NETWORK_ENTRY *ne = (struct NETWORK_ENTRY*)entry->data; - ne->id = net->id & 0x00FFFFFFFFFFFFFFULL; - if (sc_hex_to_binary(net->pubkey_hex, ne->pubkey, sizeof(ne->pubkey)) != SC_OK || - sc_hex_to_binary(net->signing_key_hex, ne->signing_key, sizeof(ne->signing_key)) != SC_OK) { - DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "invalid keys for network %s", net->name); queue_entry_free(entry); return -1; - } - strncpy(ne->name, net->name, sizeof(ne->name) - 1); - ne->name[sizeof(ne->name) - 1] = '\0'; - if (queue_data_put_with_index(instance->networks, entry) < 0) { - DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "cannot index configured network %s", net->name); return -1; - } - DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Network added: [%s] id=%012llx", ne->name, (unsigned long long)ne->id); - net = net->next; - } // Create memory pools instance->ack_pool = memory_pool_init(sizeof(struct ACK_PACKET), "ack_pool");