Browse Source

Expire ETCP transports after 30 seconds continuously down

master
evgeny 20 hours ago
parent
commit
034be69ac1
  1. 42
      src/transport_layer/etcp.c
  2. 3
      src/transport_layer/etcp.h

42
src/transport_layer/etcp.c

@ -195,6 +195,42 @@ static uint16_t timestamp_diff(uint16_t t1, uint16_t t2) {
static const char EMPTY_NAME[] = ""; static const char EMPTY_NAME[] = "";
// Create new ETCP connection // Create new ETCP connection
// Таймаут непрерывного DOWN удаляет транспорт независимо от внешних ссылок.
static void etcp_down_timeout_cb(void* arg) {
struct ETCP_CONN* conn = arg;
conn->down_timer = NULL;
if (conn->close_requested || conn->state == 2) return;
if (conn->links_up) {
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timeout ignored: transport is UP", conn->log_name);
return;
}
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timeout: deleting transport peer=%016llx refs=%d timeout_ms=%d",
conn->log_name, (unsigned long long)conn->peer_node_id, conn->ref_count, ETCP_DOWN_TIMEOUT_TB / 10);
etcp_connection_close(conn);
}
// Повторный DOWN не продлевает ожидание; первое подключение тоже имеет конечный срок.
static int etcp_down_timer_start(struct ETCP_CONN* conn) {
if (conn->down_timer || conn->links_up || conn->close_requested || conn->state == 2) return 0;
conn->down_timer = uasync_set_timeout(conn->instance->ua, ETCP_DOWN_TIMEOUT_TB, conn, etcp_down_timeout_cb, "etcp_down");
if (!conn->down_timer) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "[%s] cannot schedule DOWN timeout", conn->log_name);
etcp_connection_close(conn);
return -1;
}
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timer started timeout_ms=%d refs=%d",
conn->log_name, ETCP_DOWN_TIMEOUT_TB / 10, conn->ref_count);
return 0;
}
// UP и окончательное закрытие отменяют отложенное удаление.
static void etcp_down_timer_cancel(struct ETCP_CONN* conn) {
if (!conn->down_timer) return;
uasync_cancel_timeout(conn->instance->ua, conn->down_timer); conn->down_timer = NULL;
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] DOWN timer cancelled up=%u closing=%u",
conn->log_name, conn->links_up, conn->close_requested);
}
struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* name) { struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* name) {
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, ""); DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "");
if (!instance) return NULL; if (!instance) return NULL;
@ -281,6 +317,8 @@ struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* n
return NULL; return NULL;
} }
if (etcp_down_timer_start(etcp) < 0) return NULL;
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] connection initialized. ETCP=%p mtu=%d, next_tx_id=%u state=pending", DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "[%s] connection initialized. ETCP=%p mtu=%d, next_tx_id=%u state=pending",
etcp->log_name, etcp, etcp->mtu, etcp->next_tx_id); etcp->log_name, etcp, etcp->mtu, etcp->next_tx_id);
@ -328,6 +366,7 @@ void etcp_cbk_fire(struct ETCP_CONN* conn, int event) {
static void etcp_on_up(struct ETCP_CONN* etcp) { static void etcp_on_up(struct ETCP_CONN* etcp) {
if (etcp->state == 2) return; // defensive: после DELETE UP не стреляет if (etcp->state == 2) return; // defensive: после DELETE UP не стреляет
etcp_down_timer_cancel(etcp);
int total_links = 0; for (struct ETCP_LINK* l = etcp->links; l; l = l->next) total_links++; 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; uint64_t elapsed_ms = (get_time_tb() - etcp->setup_start_tb) / 10;
struct strbuf sb = strbuf_new(); int any = 0; struct strbuf sb = strbuf_new(); int any = 0;
@ -428,6 +467,7 @@ void etcp_connection_close(struct ETCP_CONN* etcp) {
callring_put(CR_CCLOSE_IN, (uintptr_t)etcp, 0); callring_put(CR_CCLOSE_IN, (uintptr_t)etcp, 0);
etcp->close_requested = 1; etcp->close_requested = 1;
etcp_down_timer_cancel(etcp);
etcp_padding_stop(&etcp->padding); etcp_padding_stop(&etcp->padding);
if (etcp->callbacks_running) { if (etcp->callbacks_running) {
if (etcp->close_token) return; if (etcp->close_token) return;
@ -1073,6 +1113,8 @@ void etcp_on_link_down(struct ETCP_CONN* etcp, struct ETCP_LINK* down_link) {
} }
int was_up = etcp->links_up; int was_up = etcp->links_up;
etcp->links_up = up; etcp->links_up = up;
if (!up) etcp_down_timer_start(etcp);
else etcp_down_timer_cancel(etcp);
if (up == 0 && was_up != 0) { if (up == 0 && was_up != 0) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "All links fall down"); DEBUG_INFO(DEBUG_CATEGORY_ETCP, "All links fall down");
etcp_on_down(etcp, down_link); etcp_on_down(etcp, down_link);

3
src/transport_layer/etcp.h

@ -187,6 +187,7 @@ struct ETCP_CONN {
// Timers // Timers
void* retrans_timer; // Retrans check timer void* retrans_timer; // Retrans check timer
void* ack_resp_timer; // ACK send timer void* ack_resp_timer; // ACK send timer
void* down_timer; // удаление после непрерывного DOWN, включая первоначальное ожидание
// Bandwidth measurement state // Bandwidth measurement state
// uint8_t burst_in_progress; // Burst transmission flag - Not used // uint8_t burst_in_progress; // Burst transmission flag - Not used
@ -245,6 +246,8 @@ struct ETCP_CONN {
// Создать транспортный объект; жизненным циклом прикладного соединения управляет NCD. // Создать транспортный объект; жизненным циклом прикладного соединения управляет NCD.
struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* name); struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance, char* name);
#define ETCP_DOWN_TIMEOUT_TB 300000 /* 30 секунд в 0.1 ms */
/** /**
* @brief Закрыть соединение: фаза-1 detach + отложенная фаза-2 очистка. * @brief Закрыть соединение: фаза-1 detach + отложенная фаза-2 очистка.
* *

Loading…
Cancel
Save