etcp: replace connections linked-list with indexed ll_queue, add state/ref_count lifecycle

- Remove ETCP_CONN.next linked-list, UTUN_INSTANCE.connections list/count
- Unified connections in single ll_queue indexed by peer_node_id (0=pending)
- struct conn_queue_entry { peer_node_id, conn* } for uniform queue data
- Connection lifecycle via etcp.c: create→pending, conn_ready→indexed, close→detach+deferred free
- Close split: phase1 detach from external world, phase2 deferred via uasync_call_soon
- etcp_conn_set_peer_node_id: reindex on ID change (WARN)
- etcp_conn_ref_take/free: blocking close until refcount returns to 0
- Remove chat_connections — use unified connections queue directly
- Update all iteration/search patterns across 40 files (src + tests + chatgui)
This commit is contained in:
Evgeny committed 2026-07-15 19:56:47 +03:00
1 parent 6902f5fd95
commit a7ecee01f5
40 files changed
+650 -449

No files matched your search

+2 -15
View File
@@ -564,10 +564,6 @@ struct cc_parallel_ctx {
static void cc_parallel_cleanup(struct cc_parallel_state* st) {
if (!st) return;
if (st->inst && st->inst->chat_connections) {
struct ll_entry* e = queue_find_data_by_index(st->inst->chat_connections, (const uint8_t*)&st->node_id);
if (e) { queue_remove_data(st->inst->chat_connections, e); queue_entry_free(e); }
}
u_free(st->conns);
u_free(st->timers);
u_free(st);
@@ -764,8 +760,7 @@ void chat_core_connect_from_invite(struct chat_invite* inv) {
pst->conns[idx] = NULL; pst->timers[idx] = NULL; pst->pending_count--; continue;
}
pst->conns[idx] = conn;
conn->peer_node_id = inv->node_id;
{ struct ll_entry* qe = queue_entry_new(16); if (qe) { *(uint64_t*)qe->data = inv->node_id; *(struct ETCP_CONN**)(qe->data+8) = conn; queue_data_put_with_index(g_cc.inst->chat_connections, qe); } }
etcp_conn_set_peer_node_id(conn, inv->node_id);
pst->timers[idx] = uasync_set_timeout(g_cc.inst->ua, CC_PARALLEL_CONNECT_TIMEOUT_MS * 10,
pctx, cc_parallel_timeout_cb, "cc_parallel");
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: parallel connect attempt %d/%d to %d.%d.%d.%d:%d",
@@ -810,10 +805,6 @@ struct ca_state {
static void ca_cleanup(struct ca_state* st) {
if (!st) return;
if (st->inst && st->inst->chat_connections) {
struct ll_entry* e = queue_find_data_by_index(st->inst->chat_connections, (const uint8_t*)&st->node_id);
if (e) { queue_remove_data(st->inst->chat_connections, e); queue_entry_free(e); }
}
if (st->ctxs) { for (int i = 0; i < st->addr_count; i++) u_free(st->ctxs[i]); u_free(st->ctxs); }
u_free(st->conns);
u_free(st->timers);
@@ -962,10 +953,7 @@ void chat_core_connect_auto(uint64_t node_id,
}
sc_init_ctx(&conn->crypto_ctx, &g_cc.inst->my_keys);
sc_set_peer_public_key(&conn->crypto_ctx, pubkey, 0);
conn->peer_node_id = node_id;
conn->next = g_cc.inst->connections;
g_cc.inst->connections = conn;
g_cc.inst->connections_count++;
etcp_conn_set_peer_node_id(conn, node_id);
struct ca_ctx* pctx = u_calloc(1, sizeof(struct ca_ctx));
if (!pctx) { etcp_connection_close(conn); pst->conns[i] = NULL; pst->timers[i] = NULL; pst->ctxs[i] = NULL; pst->pending_count--; continue; }
@@ -980,7 +968,6 @@ void chat_core_connect_auto(uint64_t node_id,
pst->conns[i] = NULL; pst->timers[i] = NULL; pst->ctxs[i] = NULL; pst->pending_count--; continue;
}
pst->conns[i] = conn;
{ struct ll_entry* qe = queue_entry_new(16); if (qe) { *(uint64_t*)qe->data = node_id; *(struct ETCP_CONN**)(qe->data+8) = conn; queue_data_put_with_index(g_cc.inst->chat_connections, qe); } }
pst->timers[i] = uasync_set_timeout(g_cc.inst->ua, CA_CONNECT_TIMEOUT_MS * 10,
pctx, ca_timeout_cb, "ca_timeout");
DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: auto_connect attempt %d/%d to %d.%d.%d.%d:%d",
+38 -42
View File
@@ -90,15 +90,18 @@ static void ac_gc(struct auto_connect* ac) {
if (now - ac->flights[i].created_tb < deadline) continue;
uint64_t nid = ac->flights[i].node_id;
/* check if link already UP — if so, just free slot (already connected) */
struct ETCP_CONN* c = ac->inst->connections;
int found_up = 0;
while (c) {
if (c->peer_node_id == nid) {
struct ETCP_LINK* l = c->links;
while (l) { if (l->initialized && l->link_status) { found_up = 1; break; } l = l->next; }
if (found_up) break;
{
struct ll_entry* entry = ac->inst->connections->head;
while (entry) {
struct conn_queue_entry* ce = (struct conn_queue_entry*)entry->data;
if (ce->conn->peer_node_id == nid) {
struct ETCP_LINK* l = ce->conn->links;
while (l) { if (l->initialized && l->link_status) { found_up = 1; break; } l = l->next; }
if (found_up) break;
}
entry = entry->next;
}
c = c->next;
}
if (found_up) {
chat_core_connect_auto_cancel(ac->flights[i].ca_state);
@@ -130,12 +133,9 @@ static int ac_find_free_slot(struct auto_connect* ac) {
/* ── check if node already has active ETCP connection ── */
static int ac_node_has_conn(struct UTUN_INSTANCE* inst, uint64_t nid) {
struct ETCP_CONN* c = inst->connections;
while (c) {
if (c->peer_node_id == nid) return 1;
c = c->next;
}
return 0;
if (!inst->connections) return 0;
struct ll_entry* e = queue_find_data_by_index(inst->connections, (const uint8_t*)&nid);
return e != NULL;
}
/* ── fill up to AC_MAX_FLIGHTS by advancing cursor ── */
@@ -433,24 +433,22 @@ static void cs_join_timeout_cb(void* arg) {
/* ── helper: find active ETCP_CONN for node ── */
struct CHAT_CONN_ENTRY { uint64_t node_id; struct ETCP_CONN* conn; };
static struct ETCP_CONN* cs_find_conn_for_node(struct UTUN_INSTANCE* inst, uint64_t node_id) {
struct ll_entry* e = queue_find_data_by_index(inst->chat_connections, (const uint8_t*)&node_id);
if (e) { struct CHAT_CONN_ENTRY* ce = (struct CHAT_CONN_ENTRY*)e->data; if (ce->conn->initialized && ce->conn->links_up) return ce->conn; }
if (!inst->connections) return NULL;
struct ll_entry* e = queue_find_data_by_index(inst->connections, (const uint8_t*)&node_id);
if (e) { struct conn_queue_entry* ce = (struct conn_queue_entry*)e->data; if (ce->conn->initialized && ce->conn->links_up) return ce->conn; }
return NULL;
}
/* ── helper: check if peer has active ETCP link ── */
static int cs_is_peer_online(struct UTUN_INSTANCE* inst, uint64_t peer_id) {
struct ETCP_CONN* c = inst->connections;
while (c) {
if (c->peer_node_id == peer_id) {
struct ETCP_LINK* l = c->links;
while (l) { if (l->initialized && l->link_status) return 1; l = l->next; }
}
c = c->next;
if (!inst->connections) return 0;
struct ll_entry* e = queue_find_data_by_index(inst->connections, (const uint8_t*)&peer_id);
if (e) {
struct conn_queue_entry* ce = (struct conn_queue_entry*)e->data;
struct ETCP_LINK* l = ce->conn->links;
while (l) { if (l->initialized && l->link_status) return 1; l = l->next; }
}
return 0;
}
@@ -509,10 +507,6 @@ static void cs_on_conn_down(struct ETCP_CONN* conn, void* arg) {
(void)arg;
if (!conn || !g_cs) return;
uint64_t peer = conn->peer_node_id;
if (g_cs->inst->chat_connections) {
struct ll_entry* e = queue_find_data_by_index(g_cs->inst->chat_connections, (const uint8_t*)&peer);
if (e) { queue_remove_data(g_cs->inst->chat_connections, e); queue_entry_free(e); }
}
uint16_t rtt = conn->rtt_avg_100;
if (rtt > 0 && peer != 0 && g_cs->inst->topo_groups && g_cs->inst->topo_groups->topo_sqlite_db) {
sqlite3* db = g_cs->inst->topo_groups->topo_sqlite_db;
@@ -617,13 +611,14 @@ int chat_sync_init(struct UTUN_INSTANCE* inst,
etcp_bind(inst, ETCP_RT_ID_CHAT_SYNC, chat_sync_recv_cb);
etcp_add_new_conn_cbk(inst, cs_on_new_conn, NULL);
inst->chat_connections = queue_new(inst->ua, 16, 0, 8, "chat_conns");
struct ETCP_CONN* c = inst->connections;
while (c) {
etcp_conn_add_up_cbk(c, cs_on_conn_up, NULL);
etcp_conn_add_down_cbk(c, cs_on_conn_down, NULL);
c = c->next;
{
struct ll_entry* entry = inst->connections->head;
while (entry) {
struct conn_queue_entry* ce = (struct conn_queue_entry*)entry->data;
etcp_conn_add_up_cbk(ce->conn, cs_on_conn_up, NULL);
etcp_conn_add_down_cbk(ce->conn, cs_on_conn_down, NULL);
entry = entry->next;
}
}
cs_refresh_channels(cs);
@@ -646,17 +641,18 @@ void chat_sync_destroy(struct UTUN_INSTANCE* inst) {
member_sync_destroy(inst);
cs->initialized = 0; g_cs = NULL;
queue_free(inst->chat_connections); inst->chat_connections = NULL;
etcp_unbind(inst, ETCP_RT_ID_CHAT_SYNC);
if (cs->refresh_timer) { uasync_cancel_timeout(inst->ua, cs->refresh_timer); cs->refresh_timer = NULL; }
cs_cancel_proto_timers(cs);
struct ETCP_CONN* c = inst->connections;
while (c) {
etcp_conn_remove_up_cbk(c, cs_on_conn_up, NULL);
etcp_conn_remove_down_cbk(c, cs_on_conn_down, NULL);
c = c->next;
{
struct ll_entry* entry = inst->connections->head;
while (entry) {
struct conn_queue_entry* ce = (struct conn_queue_entry*)entry->data;
etcp_conn_remove_up_cbk(ce->conn, cs_on_conn_up, NULL);
etcp_conn_remove_down_cbk(ce->conn, cs_on_conn_down, NULL);
entry = entry->next;
}
}
for (int i = 0; i < cs->channel_count; i++)