Browse Source

Propagate remote UDP link DOWN to the connection expiry timer

master
evgeny 16 hours ago
parent
commit
24c64967fd
  1. 5
      doc/service_lifecycle.md
  2. 9
      src/transport_layer/etcp_connections.c
  3. 14
      tests/test_etcp_server_lifecycle.c

5
doc/service_lifecycle.md

@ -39,7 +39,7 @@ SQLite открывается ядром один раз: `db_path/chats.db`, л
не задан. Остановка чата сохраняет каналы и сообщения в этой БД. В варианте не задан. Остановка чата сохраняет каналы и сообщения в этой БД. В варианте
`:memory:` данные сохраняются только до уничтожения ядра. `:memory:` данные сохраняются только до уничтожения ядра.
Общий транспорт живёт, пока есть его владельцы. Закрытие запроса одной группы Работающий общий транспорт сохраняется, пока он нужен хотя бы одному из пиров. Закрытие запроса одной группы
не разрывает соединение, нужное другой группе. При остановке группы отменяются не разрывает соединение, нужное другой группе. При остановке группы отменяются
её планировщики, запросы, таймеры и ожидания очередей; отправляется LEAVE, её планировщики, запросы, таймеры и ожидания очередей; отправляется LEAVE,
закрываются логические каналы маршрутизатора и удаляется её ожидающий транзит закрываются логические каналы маршрутизатора и удаляется её ожидающий транзит
@ -62,7 +62,8 @@ KEEP_ALIVE полностью отменяет FIN_WAIT. Ожидание CLOSE
Контроль RX независим от отправки keepalive. Объявленный сон не отключает проверку Контроль RX независим от отправки keepalive. Объявленный сон не отключает проверку
жизни: срок от последнего RX равен максимуму согласованного keepalive timeout и жизни: срок от последнего RX равен максимуму согласованного keepalive timeout и
объявленного остатка ACTIVE+SLEEP с запасом normal timeout. Фазовые таймеры и наши объявленного остатка ACTIVE+SLEEP с запасом normal timeout. Фазовые таймеры и наши
отправки срок жизни пира не продлевают. После истечения последнего линка транспорт отправки срок жизни пира не продлевают. Пробуждение сразу сокращает deadline до normal timeout.
После истечения последнего линка транспорт
становится DOWN, затем удаляется через 30 секунд. `test_etcp_server_lifecycle` становится DOWN, затем удаляется через 30 секунд. `test_etcp_server_lifecycle`
проверяет сроки, несколько путей, восстановление, владение, сон и CLOSE/KEEP_ALIVE проверяет сроки, несколько путей, восстановление, владение, сон и CLOSE/KEEP_ALIVE
с управляемыми часами и контролем освобождения памяти/таймеров. с управляемыми часами и контролем освобождения памяти/таймеров.

9
src/transport_layer/etcp_connections.c

@ -2610,6 +2610,15 @@ int etcp_packet_decrypted(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt,
link->last_recv_timestamp=pkt->timestamp; link->last_recv_timestamp=pkt->timestamp;
link->last_recv_updated=1; link->last_recv_updated=1;
link->total_decrypted += pkt->data_len; link->total_decrypted += pkt->data_len;
if (was_up && !link->link_status) {
struct ETCP_CONN* conn = link->etcp;
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "[%s] peer reports link DOWN id=%u remote_ka=%u", conn->log_name,
link->local_link_id, link->remote_keepalive);
etcp_on_link_down(conn, link);
int alive = 0;
for (struct ETCP_LINK* current = conn->links; current; current = current->next) if (current == link) { alive = 1; break; }
if (conn->close_requested || !alive) { memory_pool_free(conn->instance->pkt_pool, pkt); return 0; }
}
if (pkt->data[0] != ETCP_KEEPALIVE) etcp_keepalive_watch_rx(link); if (pkt->data[0] != ETCP_KEEPALIVE) etcp_keepalive_watch_rx(link);
uint8_t pkt_code = pkt->data[0]; uint8_t pkt_code = pkt->data[0];

14
tests/test_etcp_server_lifecycle.c

@ -158,6 +158,19 @@ static void check_sleep(void) {
teardown(); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS sleeping peer deadline, FIN_WAIT and disappearance"); teardown(); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS sleeping peer deadline, FIN_WAIT and disappearance");
} }
/* UDP flag_up=0 переводит весь транспорт в DOWN, обратный переход отменяет удаление. */
static void check_remote_down(void) {
setup(); struct ETCP_CONN* conn = ready_conn(0); struct ETCP_LINK* link = conn->links;
for (int up = 0; up <= 1; up++) {
struct ETCP_DGRAM* pkt = memory_pool_alloc(inst.pkt_pool); CHECK(pkt);
memset(pkt, 0, sizeof(*pkt) + 4); pkt->flag_up = up;
pkt->data[0] = ETCP_KEEPALIVE; pkt->data[2] = 200;
CHECK(etcp_packet_decrypted(&sock, pkt, link, 7) == 0);
CHECK(conn->links_up == up && !!conn->down_timer == !up);
}
teardown(); DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS remote DOWN flag and recovered UDP transport");
}
/* Пробуждение сокращает RX timeout сразу, не оставляя таймер прежнего длинного сна. */ /* Пробуждение сокращает RX timeout сразу, не оставляя таймер прежнего длинного сна. */
static void check_wake_deadline(void) { static void check_wake_deadline(void) {
setup(); struct ETCP_CONN* conn = ready_conn(1); struct ETCP_LINK* link = conn->links; setup(); struct ETCP_CONN* conn = ready_conn(1); struct ETCP_LINK* link = conn->links;
@ -205,6 +218,7 @@ int main(void) {
check_silent_peer(1); CHECK(u_get_allocated_count() == baseline); check_silent_peer(1); CHECK(u_get_allocated_count() == baseline);
check_sleep(); CHECK(u_get_allocated_count() == baseline); check_sleep(); CHECK(u_get_allocated_count() == baseline);
check_wake_deadline(); CHECK(u_get_allocated_count() == baseline); check_wake_deadline(); CHECK(u_get_allocated_count() == baseline);
check_remote_down(); CHECK(u_get_allocated_count() == baseline);
check_graceful(); CHECK(u_get_allocated_count() == baseline); check_graceful(); CHECK(u_get_allocated_count() == baseline);
test_clock_finish(); return 0; test_clock_finish(); return 0;
} }

Loading…
Cancel
Save