From 702389d8d95a0d71168e4e7df4cf2db5014a798a Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 24 Oct 2026 20:18:15 +0200 Subject: [PATCH] Retain NCD entry and transport through synchronous CLOSE callbacks --- src/transport_layer/node_conn_direct.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/transport_layer/node_conn_direct.c b/src/transport_layer/node_conn_direct.c index ddb9e0bb..36476add 100644 --- a/src/transport_layer/node_conn_direct.c +++ b/src/transport_layer/node_conn_direct.c @@ -907,22 +907,24 @@ int node_conn_direct_open_node(struct UTUN_INSTANCE* inst, uint64_t node_id, static void ncd_handle_close(struct NODE_CONN_DIRECT* h, int force) { if (!h || h->closed) return; struct ncd_entry* entry = h->entry; + entry->active_calls++; + struct ETCP_CONN* conn = entry->conn; + int held = conn && etcp_conn_ref_take(conn) == 0; ncd_cancel_deliver_up(h, entry->ua); h->closed = 1; h->cb = NULL; h->cb_arg = NULL; entry->handle_count--; DEBUG_DEBUG(DEBUG_CATEGORY_NCD, "[ncd] handle close node=%016llx remaining=%d force=%d", (unsigned long long)entry->node_id, entry->handle_count, force); - if (entry->handle_count || entry->closed) { ncd_collect(entry); return; } - struct ETCP_CONN* conn = entry->conn; + if (entry->handle_count || entry->closed) goto done; if (force || !conn || conn->close_requested || conn->state == 2 || entry->timed_out || (!conn->state && !conn->links_up)) { - ncd_finish(entry, 1); return; + ncd_finish(entry, 1); goto done; } if (!conn->links_up) { DEBUG_INFO(DEBUG_CATEGORY_NCD, "[ncd] last handle released while DOWN, retaining until ETCP timeout node=%016llx", (unsigned long long)entry->node_id); ncd_finish(entry, 0); if (etcp_conn_schedule_down_close(conn) < 0) etcp_connection_close(conn); - return; + goto done; } if (entry->connect_timer) { uasync_cancel_timeout(entry->ua, entry->connect_timer); entry->connect_timer = NULL; } conn->fin_wait = 1; conn->fin_wait_clear_cb = ncd_fin_wait_cancelled; conn->fin_wait_clear_arg = entry; @@ -935,6 +937,7 @@ static void ncd_handle_close(struct NODE_CONN_DIRECT* h, int force) { DEBUG_WARN(DEBUG_CATEGORY_NCD, "[ncd] CLOSE send failed"); queue_dgram_free(e); queue_entry_free(e); } } + if (entry->closed || conn->close_requested || !conn->fin_wait || entry->handle_count) goto done; uint64_t now = get_time_tb(), wait_tb = NCD_FIN_WAIT_TIMEOUT_TB; for (struct ETCP_LINK* link = conn->links; link; link = link->next) { if (!link->link_status || (!link->ka_my_sleeping && !link->ka_peer_sleeping)) continue; @@ -944,10 +947,12 @@ static void ncd_handle_close(struct NODE_CONN_DIRECT* h, int force) { entry->fin_wait_timer = uasync_set_timeout(entry->ua, delay, entry, ncd_fin_wait_timeout_cb, "ncd_fin_wait"); if (!entry->fin_wait_timer) { DEBUG_ERROR(DEBUG_CATEGORY_NCD, "[ncd] cannot schedule FIN_WAIT node=%016llx", (unsigned long long)entry->node_id); - ncd_finish(entry, 1); return; + ncd_finish(entry, 1); goto done; } DEBUG_INFO(DEBUG_CATEGORY_NCD, "[ncd] fin_wait node=%016llx timeout_ms=%d", (unsigned long long)entry->node_id, delay / 10); - ncd_collect(entry); +done: + entry->active_calls--; ncd_collect(entry); + if (held) etcp_conn_ref_free(conn); } void node_conn_direct_close(struct NODE_CONN_DIRECT* h) { ncd_handle_close(h, 0); } void node_conn_direct_force_close(struct NODE_CONN_DIRECT* h) { ncd_handle_close(h, 1); }