You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

79 lines
4.7 KiB

#ifndef ETCP_KEEPALIVE_H
#define ETCP_KEEPALIVE_H
#ifdef __cplusplus
extern "C" {
#endif
// подмодуль ETCP: keepalive-пакеты, таймер, адаптивный период и протокол
// спячки (sleep) на флагах самого keepalive-пакета.
#include "etcp_connections.h"
/* ─── Протокол спячки поверх keepalive-пакета (code ETCP_KEEPALIVE = 0x08) ───
*
* Обычный keepalive (normal-режим) и спячка (standby) — раздельные механизмы
* (разные таймеры, разный код):
*
* normal: периодический flagless-keepalive (адаптивный период) + dead-link
* по keepalive_timeout. Активен только когда бодрствуют обе стороны.
*
* standby (спящий узел): периодический flagless НЕ шлётся вовсе. На фазовых
* переходах duty-cycle (SLEEP 120с / ACTIVE 2с) шлётся анонс
* KA_FLAG_SLEEP с таймингом. В ACTIVE-окне анонс ретраится каждые
* keepalive_interval до ACK (лимит: сколько влезет в окно, но ≥
* KA_SLEEP_MIN_ATTEMPTS). Кумулятивные провалы (сброс по ACK) — при
* KA_SLEEP_MAX_FAILS → link down (детект мёртвого пира в спячке).
*
* Формат пакета:
* data[0] = ETCP_KEEPALIVE (0x08)
* data[1] = flags (bit0 = KA_FLAG_SLEEP — «я сплю», bit1 = KA_FLAG_SLEEP_ACK — ответ)
* data[2..3] = ka_period_ms (LE 16-bit) — база dead-link таймаута, мс
* data[4..5] = active_remaining (LE 16-bit, x0.1с) — до SLEEP-фазы (0 = уже спим)
* data[6..7] = sleep_duration (LE 16-bit, x0.1с) — длительность SLEEP-фазы
* далее = зашифрованный нулевой padding; тело без SLEEP занимает 4 байта, с SLEEP — 8
*
* Протокол полностью симметричный (без привязки к STCP-роли is_server):
* спящий шлёт анонс KA_FLAG_SLEEP, пир «затыкается» (гасит свой normal-keepalive)
* и отвечает KA_FLAG_SLEEP_ACK. Спящий, получив ACK, снимает ретраи. В standby
* обе стороны НЕ шлют периодические flagless-keepalive.
*
* По таймингу анонса пир ведёт фазу троттлинга duty-cycle (SLEEP-фаза → тормозим
* протоколы, ACTIVE-окно → обмен).
*
* Пробуждение (форграунд): спящий шлёт flagless-keepalive — пир снимает standby
* и фазу троттлинга, возвращается в normal-режим.
*/
// Флаги keepalive-пакета (data[1])
#define KA_FLAG_SLEEP 0x01 // «я сплю» (анонс, с таймингом)
#define KA_FLAG_SLEEP_ACK 0x02 // «подтверждаю твой сон» (ответ на анонс)
// Параметры анонса спячки
#define KA_SLEEP_MIN_ATTEMPTS 5 // минимум попыток анонса в ACTIVE-окне
#define KA_SLEEP_MAX_FAILS 10 // провалов анонса подряд → link down
// --- перенесены из etcp_connections.c (имена сохранены) ---
uint16_t negotiate_keepalive(uint8_t my_type, uint16_t my_ka,
uint8_t peer_type, uint16_t peer_ka);
void etcp_link_send_keepalive(struct ETCP_LINK* link);
void start_keepalive_timer(struct ETCP_LINK* link);
// --- новое ---
// Обработка keepalive-пакетов (ETCP_KEEPALIVE) из etcp_packet_decrypted.
// Возвращает 1 если пакет обработан (и освобождён), 0 — если это не keepalive.
int etcp_keepalive_on_recv(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt,
struct ETCP_LINK* link, size_t pkt_len);
// Подписка на фактический режим/фазу standby; без duty-cycle — на активность клиента.
// Вызывается из init_connections.
void etcp_keepalive_register(struct UTUN_INSTANCE* inst);
// После INIT/INIT_RESPONSE, TCP handshake и reconnect сразу анонсирует текущий режим/фазу.
// В standby запускает sleep-анонс с ретраями UDP; в normal — обычный keepalive.
void etcp_keepalive_link_ready(struct ETCP_LINK* link);
#ifdef __cplusplus
}
#endif
#endif // ETCP_KEEPALIVE_H