diff --git a/src/routing_layer/conn_mgr_core.c b/src/routing_layer/conn_mgr_core.c index 7eae361c..59640bca 100644 --- a/src/routing_layer/conn_mgr_core.c +++ b/src/routing_layer/conn_mgr_core.c @@ -181,6 +181,12 @@ struct CONN_MGR_ENTRY* cm_ensure_entry(struct CONN_MGR* mgr, uint64_t node_id) { void cm_entry_cleanup(struct CONN_MGR_ENTRY* entry) { if (!entry || entry->state == CONN_MGR_STATE_DISCONNECTED) return; if (entry->main.timer) { uasync_cancel_timeout(entry->mgr->instance->ua, entry->main.timer); entry->main.timer = NULL; } + { struct cm_reverse_pending** pp = &entry->mgr->reverse_pending; + while (*pp) { + if ((*pp)->entry == entry) { struct cm_reverse_pending* rp = *pp; *pp = rp->next; u_free(rp); } + else pp = &(*pp)->next; + } + } { struct cm_exchange_pending** pp = &entry->mgr->exchange_pending; while (*pp) { if ((*pp)->entry == entry) { @@ -281,6 +287,11 @@ void cm_ncd_callback(struct NODE_CONN_DIRECT* ncd_h, enum ncd_event ncd_ev, void cm_entry_cleanup(entry); return; } + /* Инициатор с handle'ами: выбор следующей фазы делаем только из DIRECT (phase==0). + * В REVERSE (phase==2) эскалацией владеет собственный 15с таймер, а повторные + * NCD-таймауты (шаримый NCD оживляется другими модулями) игнорируем — иначе + * cm_start_phase_reverse утечёт старыми таймерами и выстрелит в освобождённый entry. */ + if (entry->main.phase == 2) return; { struct TOPO_GROUP* g = entry->mgr->group; struct TOPO_GROUP_NODE* t = topo_node_find_by_id(g, entry->node_id); if (cm_has_direct_ip(entry->mgr, g->local_node) && !(t && cm_has_direct_ip(entry->mgr, t))) @@ -684,6 +695,7 @@ void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry) { etcp_route_send(entry->mgr->instance, group->group_id, entry->node_id, qe, 1, 0); struct cm_reverse_pending* rp = u_calloc(1, sizeof(*rp)); if (rp) { rp->request_id=req_id; rp->entry=entry; rp->next=entry->mgr->reverse_pending; entry->mgr->reverse_pending=rp; } + if (entry->main.timer) { uasync_cancel_timeout(entry->mgr->instance->ua, entry->main.timer); entry->main.timer = NULL; } entry->main.timer = uasync_set_timeout(entry->mgr->instance->ua, CONN_MGR_CONNECT_REVERSE_TIMEOUT_MS*10, entry, cm_reverse_timeout_cb, "conn_mgr_reverse"); DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: phase 2 (reverse) sent DIRECT_REQ to 0x%016llx with %u addrs", diff --git a/src/routing_layer/conn_mgr_indirect.c b/src/routing_layer/conn_mgr_indirect.c index e4c40711..b742f488 100644 --- a/src/routing_layer/conn_mgr_indirect.c +++ b/src/routing_layer/conn_mgr_indirect.c @@ -27,6 +27,7 @@ void cm_start_phase_indirect(struct CONN_MGR_ENTRY* entry) { struct ll_entry* qe = queue_entry_new(0); if (!qe) return; qe->dgram=u_malloc(1+sizeof(req)); qe->dgram[0]=ETCP_RT_ID_CONN_MGR; memcpy(qe->dgram+1,&req,sizeof(req)); qe->len=(uint16_t)(1+sizeof(req)); etcp_route_send(mgr->instance, mgr->group->group_id, entry->node_id, qe, 1, 0); + if (entry->main.timer) { uasync_cancel_timeout(mgr->instance->ua, entry->main.timer); entry->main.timer = NULL; } entry->main.timer = uasync_set_timeout(mgr->instance->ua, CONN_MGR_INTERM_EXCHANGE_TIMEOUT_MS*10, entry, cm_exchange_timeout_cb, "conn_mgr_interm_exch"); struct cm_exchange_pending* ep = u_calloc(1,sizeof(*ep)); if (ep) { ep->request_id=entry->main.request_id; ep->entry=entry; ep->timer=entry->main.timer; ep->next=mgr->exchange_pending; mgr->exchange_pending=ep; }