From 1b659335b9b89ad899a16ac074060941ebbc29f4 Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 12 Oct 2026 20:33:03 +0200 Subject: [PATCH] Test failure recheck eligibility and coalescing on a blocked UDP peer --- doc/nat_detection.txt | 3 +++ tests/test_nat_detection.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/doc/nat_detection.txt b/doc/nat_detection.txt index 857b08d3..d4312a79 100644 --- a/doc/nat_detection.txt +++ b/doc/nat_detection.txt @@ -160,6 +160,9 @@ round, аутентичный PONG чужого ключа, старое пок test_nat_detection: разные socket ID, два рабочих UDP endpoint, TCP listener, замена помощника с тем же IP, повтор по старому контакту, подпись/SQLite профиля, закрытие S посреди раунда и повторный ID/порт. Утечки/таймеры/сокеты проверяются. +Недостаточная UTUN-группа и достаточная CHAT-группа проверяются отдельно с TCP next hop +и отсутствием прямого транспорта A-C. Неудачные native INIT проверяют отсутствие +лишних перепроверок для UNKNOWN, ожидание reverse для CONTACT и пятиминутный лимит. test_sock_match: независимость политики от фактов, UNKNOWN, CONTACT, давность, частные адреса и разрешённая попытка hairpin; профили не протухают по времени. diff --git a/tests/test_nat_detection.c b/tests/test_nat_detection.c index 178385d8..f95fa957 100644 --- a/tests/test_nat_detection.c +++ b/tests/test_nat_detection.c @@ -100,6 +100,39 @@ static void test_all_groups_tcp(void) { assert(!nat_detection_get_status(owner->nat_det, socket, &status) && status.group_id == 42 && status.helper == helper->node_id); for (struct ETCP_LINK *link = bc->links; link; link = link->next) if (link->link_status) assert(link->is_tcp); assert(!instance_find_conn(owner, helper->node_id)); + /* Реально заблокированный UDP endpoint: UNKNOWN не запускает лишних проверок, подписанный OPEN запускает одну. */ + uint64_t verified_round = status.round; + struct NODE_CONN_DIRECT **failed_handle = &fixture.handles[fixture.handle_count++]; + node = topo_node_registry_find(owner->topo_groups, helper->node_id); + assert(node_conn_direct_open_node(owner, helper->node_id, NULL, NULL, failed_handle, node, socket) != NCD_ERR); + struct ETCP_CONN *failed = node_conn_direct_get_conn(*failed_handle); + end = get_time_tb() + owner->etcp_connect_timeout_tb + 1000; + while (get_time_tb() < end) uasync_poll(fixture.ua, 10); + assert(failed && !failed->links_up && failed->links && failed->links->init_retry_count); + assert(!nat_detection_get_status(owner->nat_det, socket, &status) && status.round == verified_round); + helper_socket->address_profile = (struct address_profile){ADDRESS_MAP_UNCHANGED, ADDRESS_IN_CONTACT, ADDRESS_SOURCE_ETCP}; + topo_group_update_my_nodeinfo(groups[2]); + const struct TOPO_SOCKMETA4 *meta = NULL; + end = get_time_tb() + 30000; + do { + uasync_poll(fixture.ua, 10); node = topo_node_registry_find(owner->topo_groups, helper->node_id); + meta = node ? node->v4_sock_meta : NULL; + while (meta && meta->id != helper_socket->sock_id) meta = meta->next; + } while (get_time_tb() < end && (!meta || meta->address_profile.inbound != ADDRESS_IN_CONTACT)); + assert(meta && meta->address_profile.inbound == ADDRESS_IN_CONTACT); + nat_detection_connection_failed(owner->nat_det, failed, 0); + assert(!nat_detection_get_status(owner->nat_det, socket, &status) && status.round == verified_round); + nat_detection_connection_failed(owner->nat_det, failed, 1); + end = get_time_tb() + 50000; + do { uasync_poll(fixture.ua, 10); assert(!nat_detection_get_status(owner->nat_det, socket, &status)); } + while (get_time_tb() < end && (status.round == verified_round || status.phase || status.cycling)); + assert(status.round != verified_round && !status.phase && !status.cycling); + assert(socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && socket->address_profile.inbound == ADDRESS_IN_OPEN); + verified_round = status.round; + nat_detection_connection_failed(owner->nat_det, failed, 1); + end = get_time_tb() + 10000; + while (get_time_tb() < end) uasync_poll(fixture.ua, 10); + assert(!nat_detection_get_status(owner->nat_det, socket, &status) && status.round == verified_round); uint64_t old_round = status.round; assert(!nat_detection_request_check_socket(owner->nat_det, socket, observer->node_id)); end = get_time_tb() + 30000;