|
|
|
|
@ -124,6 +124,14 @@ static void keepalive_timer_cb(void* arg) {
|
|
|
|
|
|
|
|
|
|
link->keepalive_timer = NULL; |
|
|
|
|
|
|
|
|
|
// Клиент в standby: ничего не делаем (recovery/dead-link/отправка) — только переарм.
|
|
|
|
|
// Фазу сигналят фазовые переходы (ka_phase_cb), NAT держит сам сон (sleep ≤ NAT-таймаут).
|
|
|
|
|
if (link->ka_sleeping && !link->is_server) { |
|
|
|
|
link->keepalive_timer = uasync_set_timeout(link->etcp->instance->ua, |
|
|
|
|
link->ka_period_ms * 10, link, keepalive_timer_cb, "link_keepalive"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check if all links are down and start recovery if needed (client only)
|
|
|
|
|
if (link->is_server == 0 && etcp_all_links_down(link->etcp)) { |
|
|
|
|
if (link->is_tcp) { |
|
|
|
|
@ -187,13 +195,9 @@ static void keepalive_timer_cb(void* arg) {
|
|
|
|
|
} |
|
|
|
|
link->pkt_sent_since_keepalive = 0; |
|
|
|
|
|
|
|
|
|
// Отправка 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) { |
|
|
|
|
// Отправка keepalive: в спячке НЕ шлём (ни клиент, ни сервер) — фазу сигналят фазовые переходы.
|
|
|
|
|
if (!link->ka_sleeping) { |
|
|
|
|
if (!link->is_server || link->recv_keepalive) |
|
|
|
|
etcp_link_send_keepalive(link); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -272,11 +276,9 @@ static void ka_client_enter_sleep(struct ETCP_LINK* link) {
|
|
|
|
|
restart_keepalive_timer_ms(link, period); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Клиент: переанонс на входе в очередной цикл спячки (обновить дедлайн).
|
|
|
|
|
// Клиент: переанонс на входе в очередной цикл спячки (обновить фазу, без ре-ack).
|
|
|
|
|
static void ka_client_reannounce(struct ETCP_LINK* link) { |
|
|
|
|
if (!link->ka_sleeping) return; |
|
|
|
|
link->ka_sleep_acked = 0; |
|
|
|
|
link->ka_sleep_announce_end_tb = get_time_tb() + (uint64_t)KA_SLEEP_ANNOUNCE_TIMEOUT_MS * 10; |
|
|
|
|
ka_send_sleep_keepalive(link); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -400,7 +402,9 @@ int etcp_keepalive_on_recv(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt,
|
|
|
|
|
uint16_t sleep_duration = (pkt->data_len >= 8) |
|
|
|
|
? (pkt->data[6] | ((uint16_t)pkt->data[7] << 8)) : 0; |
|
|
|
|
if (link->is_server) { |
|
|
|
|
/* Сервер: пир в спячке — зеркалим флаг/поля для эхо и ведём фазу троттлинга. */ |
|
|
|
|
/* Сервер: пир в спячке — зеркалим флаг/поля и ведём фазу троттлинга.
|
|
|
|
|
ack-эхо шлём только на анонсе (переход 0→1), дальше в спячке молчим. */ |
|
|
|
|
int was_sleeping = link->ka_sleeping; |
|
|
|
|
link->ka_sleeping = 1; |
|
|
|
|
link->ka_sleep_period_ms = peer_period; |
|
|
|
|
link->ka_active_remaining = active_remaining; |
|
|
|
|
@ -412,10 +416,12 @@ int etcp_keepalive_on_recv(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt,
|
|
|
|
|
ka_server_set_phase(link->etcp, active_remaining == 0); |
|
|
|
|
ka_server_arm_phase(link->etcp); |
|
|
|
|
} |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_KEEPALIVE, "[%s] server: peer sleeping (period=%dms active_rem=%d.%ds sleep_dur=%d.%ds), echo ack", |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_KEEPALIVE, "[%s] server: peer sleeping (period=%dms active_rem=%d.%ds sleep_dur=%d.%ds), echo=%s", |
|
|
|
|
link->etcp->log_name, peer_period, |
|
|
|
|
(int)(active_remaining / 10), (int)(active_remaining % 10), |
|
|
|
|
(int)(sleep_duration / 10), (int)(sleep_duration % 10)); |
|
|
|
|
(int)(sleep_duration / 10), (int)(sleep_duration % 10), |
|
|
|
|
was_sleeping ? "no" : "ack"); |
|
|
|
|
if (!was_sleeping) |
|
|
|
|
etcp_link_send_keepalive(link); |
|
|
|
|
restart_keepalive_timer_ms(link, peer_period); |
|
|
|
|
} else { |
|
|
|
|
|