diff --git a/src/transport_layer/etcp_keepalive.c b/src/transport_layer/etcp_keepalive.c index 03ae0ef2..78e0c6db 100644 --- a/src/transport_layer/etcp_keepalive.c +++ b/src/transport_layer/etcp_keepalive.c @@ -188,10 +188,14 @@ static void keepalive_timer_cb(void* arg) { link->pkt_sent_since_keepalive = 0; // Отправка keepalive (в спячке — с флагом и свежим дедлайном) - if (link->ka_sleeping) - ka_send_sleep_keepalive(link); - else if (!link->is_server || link->recv_keepalive) + if (link->ka_sleeping) { + if (link->is_server) + etcp_link_send_keepalive(link); /* echo: поля уже зеркальны из on_recv */ + else + ka_send_sleep_keepalive(link); /* клиент: пересчитать тайминг и анонс */ + } else if (!link->is_server || link->recv_keepalive) { etcp_link_send_keepalive(link); + } restart_timer: link->keepalive_timer = uasync_set_timeout(link->etcp->instance->ua, link->ka_period_ms * 10, link, keepalive_timer_cb, "link_keepalive"); @@ -364,6 +368,12 @@ static void ka_server_arm_phase(struct ETCP_CONN* etcp) { uasync_cancel_timeout(etcp->instance->ua, etcp->peer_phase_timer); etcp->peer_phase_timer = NULL; } + /* гвард: нулевой тайминг (битый/legacy пакет) → не армать, иначе timer=0 даёт busy-loop */ + if (dur_01s == 0) { + DEBUG_WARN(DEBUG_CATEGORY_KEEPALIVE, "[%s] server: zero phase duration (phase=%d), skip arming", + etcp->log_name, etcp->peer_sleep_phase); + return; + } etcp->peer_phase_timer = uasync_set_timeout(etcp->instance->ua, (int)((uint32_t)dur_01s * 1000), etcp, ka_server_phase_timer_cb, "peer_phase"); }