Share atomic network index construction and typed socket teardown
This commit is contained in:
1 parent
b44ea19b4b
commit
5e63bc2a42
1 file changed
+41
-29
+41
-29
@@ -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");
|
||||
|
||||
Reference in new issue
Block a user