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:
1 parent
6902f5fd95
commit
a7ecee01f5
40 files changed
+650
-449
No files matched your search
@@ -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",
|
||||
|
||||
@@ -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++)
|
||||
|
||||
Reference in new issue
Block a user