Retain NCD entry and transport through synchronous CLOSE callbacks

This commit is contained in:
evgeny committed 2026-10-24 20:18:15 +02:00
1 parent 88004f11ca
commit 702389d8d9
1 file changed
+11 -6
+11 -6
View File
@@ -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); }