Share atomic network index construction and typed socket teardown

This commit is contained in:
evgeny committed 2026-10-26 09:08:42 +01:00
1 parent b44ea19b4b
commit 5e63bc2a42
1 file changed
+41 -29
+41 -29
View File
@@ -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");