Stop readiness publication after callback close and rescan teardown links

This commit is contained in:
evgeny committed 2026-10-23 21:49:11 +02:00
1 parent f37221107d
commit 4614577d19
2 files changed
+29 -14

No files matched your search

+27 -14
View File
@@ -269,7 +269,12 @@ void etcp_fire_conn_status(struct ETCP_CONN* etcp, int status) {
(status >= 0 && status < (int)(sizeof(names)/sizeof(names[0]))) ? names[status] : "?");
etcp->callbacks_running++;
struct etcp_status_cbk_entry* cbe = etcp->instance->conn_status_cbks;
while (cbe) { struct etcp_status_cbk_entry* n = cbe->next; cbe->fn(etcp, status, cbe->arg); cbe = n; }
while (cbe) {
struct etcp_status_cbk_entry* n = cbe->next;
cbe->fn(etcp, status, cbe->arg);
if (etcp->close_requested && status != ETCP_CONN_STATUS_DOWN && status != ETCP_CONN_STATUS_DELETE) break;
cbe = n;
}
etcp->callbacks_running--;
}
@@ -281,7 +286,12 @@ void etcp_cbk_fire(struct ETCP_CONN* conn, int event) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[%s] callback event: %s", conn->log_name, (idx >= 0 && idx < (int)(sizeof(names)/sizeof(names[0]))) ? names[idx] : "?");
conn->callbacks_running++;
struct etcp_cbk_entry* cbe = conn->cbks;
while (cbe) { struct etcp_cbk_entry* n = cbe->next; if (cbe->fn && (cbe->event_mask & event)) cbe->fn(conn, event, cbe->arg); cbe = n; }
while (cbe) {
struct etcp_cbk_entry* n = cbe->next;
if (cbe->fn && (cbe->event_mask & event)) cbe->fn(conn, event, cbe->arg);
if (conn->close_requested && event != ETCP_CBK_EVENT_DOWN && event != ETCP_CBK_EVENT_DELETE) break;
cbe = n;
}
conn->callbacks_running--;
if (!conn->callbacks_running) {
struct etcp_cbk_entry** pp = &conn->cbks;
@@ -293,7 +303,7 @@ void etcp_cbk_fire(struct ETCP_CONN* conn, int event) {
}
static void etcp_on_up(struct ETCP_CONN* etcp) {
if (etcp->state == 2) return; // defensive: после DELETE UP не стреляет
if (etcp->state == 2 || etcp->close_requested) return;
etcp_down_timer_cancel(etcp);
int total_links = 0; for (struct ETCP_LINK* l = etcp->links; l; l = l->next) total_links++;
uint64_t elapsed_ms = (get_time_tb() - etcp->setup_start_tb) / 10;
@@ -310,7 +320,7 @@ static void etcp_on_up(struct ETCP_CONN* etcp) {
strbuf_free(&sb);
(void)elapsed_ms;
etcp_cbk_fire(etcp, ETCP_CBK_EVENT_UP);
etcp_fire_conn_status(etcp, ETCP_CONN_STATUS_UP);
if (!etcp->close_requested) etcp_fire_conn_status(etcp, ETCP_CONN_STATUS_UP);
}
static void etcp_on_down(struct ETCP_CONN* etcp, struct ETCP_LINK* down_link) {
@@ -328,7 +338,7 @@ static void etcp_on_down(struct ETCP_CONN* etcp, struct ETCP_LINK* down_link) {
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] Connection DOWN — closing, links: %s", etcp->log_name, any ? strbuf_str(&sb) : "(none)");
strbuf_free(&sb);
etcp_cbk_fire(etcp, ETCP_CBK_EVENT_DOWN);
etcp_fire_conn_status(etcp, ETCP_CONN_STATUS_DOWN);
if (!etcp->close_requested) etcp_fire_conn_status(etcp, ETCP_CONN_STATUS_DOWN);
}
@@ -341,9 +351,7 @@ static void etcp_connection_free_resources(struct ETCP_CONN* etcp) {
// Close links
if (etcp->links) {
struct ETCP_LINK* link = etcp->links;
while (link) { struct ETCP_LINK* next = link->next; etcp_link_close(link); link = next; }
etcp->links = NULL;
while (etcp->links) etcp_link_close(etcp->links);
}
// Drain and free all queues
@@ -443,9 +451,8 @@ void etcp_connection_close(struct ETCP_CONN* etcp) {
// Close links (detach from socket scan queues)
if (etcp->links) {
struct ETCP_LINK* link = etcp->links;
while (link) { struct ETCP_LINK* next = link->next; etcp_link_close(link); link = next; }
etcp->links = NULL;
/* Callback закрытия одного пути может удалить соседний: следующий берём заново. */
while (etcp->links) etcp_link_close(etcp->links);
}
// Remove from instance queue
@@ -582,7 +589,7 @@ void etcp_conn_apply_peer_reset_id(struct ETCP_CONN* conn, uint64_t peer_reset_i
// внутренняя функция. Вызывается один раз когда первый линк готов.
void etcp_conn_ready(struct ETCP_CONN* conn) {
if (!conn) return;
if (!conn || conn->close_requested) return;
if (conn->state == 2) { DEBUG_WARN(DEBUG_CATEGORY_ETCP, "[%s] conn_ready on deleted conn", conn->log_name); return; }
if (conn->initialized || conn->session_required) return; // ready or awaiting authenticated confirmation
@@ -595,6 +602,7 @@ void etcp_conn_ready(struct ETCP_CONN* conn) {
for (struct ETCP_LINK* link = conn->links; link; link = link->next)
if (link->initialized && link->link_status) conn->links_up = 1;
etcp_conn_queue_set_ready(conn);
if (conn->close_requested) return;
// Реинит уже готового соединения (state!=0): etcp_conn_queue_set_ready не сработал
// (ранний выход по state!=0), поэтому reinit_pending остаётся висеть и блокирует приём —
@@ -602,6 +610,7 @@ void etcp_conn_ready(struct ETCP_CONN* conn) {
if (conn->reinit_pending) {
conn->reinit_pending = 0;
etcp_cbk_fire(conn, ETCP_CBK_EVENT_REINIT);
if (conn->close_requested) return;
etcp_fire_conn_status(conn, ETCP_CONN_STATUS_REINIT);
}
if (conn->normalizer && !conn->close_requested) queue_resume_callback(conn->normalizer->input);
@@ -646,8 +655,12 @@ void etcp_conn_queue_set_ready(struct ETCP_CONN* conn) {
conn->log_name, conn->state, (unsigned long long)conn->peer_node_id);
etcp_cbk_fire(conn, ETCP_CBK_EVENT_INIT);
if (conn->reinit_pending) { conn->reinit_pending = 0; etcp_cbk_fire(conn, ETCP_CBK_EVENT_REINIT);
etcp_fire_conn_status(conn, ETCP_CONN_STATUS_REINIT); }
if (conn->close_requested) return;
if (conn->reinit_pending) {
conn->reinit_pending = 0; etcp_cbk_fire(conn, ETCP_CBK_EVENT_REINIT);
if (conn->close_requested) return;
etcp_fire_conn_status(conn, ETCP_CONN_STATUS_REINIT);
}
if (conn->links_up) etcp_on_up(conn);
}
+2
View File
@@ -94,12 +94,14 @@ void etcp_remove_link_status_cbk(struct UTUN_INSTANCE* inst, etcp_link_status_cb
void etcp_fire_link_status_cbk(struct ETCP_LINK* link, int old_state, int old_status) {
if (!link || !link->etcp || !link->etcp->instance) return;
struct ETCP_CONN* conn = link->etcp;
int closing_connection = conn->close_requested;
int was_attached = 0;
for (struct ETCP_LINK* current = conn->links; current; current = current->next) if (current == link) { was_attached = 1; break; }
conn->callbacks_running++;
struct etcp_link_status_cbk_entry* cbe = conn->instance->link_status_cbks;
while (cbe) {
cbe->fn(conn, link, old_state, old_status, cbe->arg);
if (!closing_connection && conn->close_requested) break;
if (was_attached) {
int attached = 0;
for (struct ETCP_LINK* current = conn->links; current; current = current->next)