|
|
|
@ -371,8 +371,7 @@ static void wait_source(struct nat_fixture* nf, struct ETCP_SOCKET* socket, uint |
|
|
|
abort(); |
|
|
|
abort(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Настоящее ядро: нет узлов -> один наблюдатель -> независимый третий узел.
|
|
|
|
/* STUN другого порта не назначает профиль рабочему endpoint, даже без ETCP-наблюдателей. */ |
|
|
|
* Сервер сообщает translated EIM, реальный рабочий loopback endpoint — UNCHANGED. */ |
|
|
|
|
|
|
|
static void test_fallback(void) { |
|
|
|
static void test_fallback(void) { |
|
|
|
struct nat_fixture nf; nat_fixture_init(&nf); |
|
|
|
struct nat_fixture nf; nat_fixture_init(&nf); |
|
|
|
struct fixture server = {.ua = nf.ua, .rfc = 1, .mapping = STUN_MAP_EIM, |
|
|
|
struct fixture server = {.ua = nf.ua, .rfc = 1, .mapping = STUN_MAP_EIM, |
|
|
|
@ -384,22 +383,26 @@ static void test_fallback(void) { |
|
|
|
struct UTUN_INSTANCE* owner = nat_fixture_node(&nf, "127.0.0.1", NULL, config); |
|
|
|
struct UTUN_INSTANCE* owner = nat_fixture_node(&nf, "127.0.0.1", NULL, config); |
|
|
|
struct ETCP_SOCKET* socket = test_etcp_bound_socket(owner, "udp"); |
|
|
|
struct ETCP_SOCKET* socket = test_etcp_bound_socket(owner, "udp"); |
|
|
|
struct ETCP_SOCKET* duplicate = test_etcp_bound_socket(owner, "duplicate"); |
|
|
|
struct ETCP_SOCKET* duplicate = test_etcp_bound_socket(owner, "duplicate"); |
|
|
|
wait_source(&nf, socket, ADDRESS_SOURCE_STUN); wait_source(&nf, duplicate, ADDRESS_SOURCE_STUN); |
|
|
|
struct stun_nat_result diagnostic; |
|
|
|
assert(socket->address_profile.mapping == ADDRESS_MAP_EIM && socket->address_profile.inbound == ADDRESS_IN_OPEN); |
|
|
|
uint64_t end = get_time_tb() + 3000000; |
|
|
|
|
|
|
|
do { test_clock_poll(nf.ua, 10000); assert(!stun_nat_get_socket_result(owner, socket, &diagnostic)); } |
|
|
|
|
|
|
|
while (get_time_tb() < end && diagnostic.status == STUN_NAT_PENDING); |
|
|
|
|
|
|
|
assert(diagnostic.mapping == STUN_MAP_EIM && diagnostic.filtering == STUN_FILTER_EIF); |
|
|
|
|
|
|
|
assert(socket->address_profile.source == ADDRESS_SOURCE_NONE && !socket->address_profile.mapping && !socket->address_profile.inbound); |
|
|
|
assert(!memcmp(&socket->address_profile, &duplicate->address_profile, sizeof(socket->address_profile))); |
|
|
|
assert(!memcmp(&socket->address_profile, &duplicate->address_profile, sizeof(socket->address_profile))); |
|
|
|
assert(!socket->nat_addr.ss_family && !duplicate->nat_addr.ss_family); |
|
|
|
assert(!socket->nat_addr.ss_family && !duplicate->nat_addr.ss_family); |
|
|
|
struct nat_check_status status; assert(!nat_detection_get_status(owner->nat_det, socket, &status)); |
|
|
|
struct nat_check_status status; assert(!nat_detection_get_status(owner->nat_det, socket, &status)); |
|
|
|
assert(status.reason == NAT_REASON_NO_OBSERVER && status.fallback_allowed); |
|
|
|
assert(status.reason == NAT_REASON_NO_OBSERVER); |
|
|
|
struct TOPO_NODE* snapshot = topo_node_registry_find(owner->topo_groups, owner->node_id); |
|
|
|
struct TOPO_NODE* snapshot = topo_node_registry_find(owner->topo_groups, owner->node_id); |
|
|
|
assert(snapshot && !topo_node_verify(snapshot)); |
|
|
|
assert(snapshot && !topo_node_verify(snapshot)); |
|
|
|
for (const struct TOPO_ADDR4* address = snapshot->v4_addrs; address; address = address->next) |
|
|
|
for (const struct TOPO_ADDR4* address = snapshot->v4_addrs; address; address = address->next) |
|
|
|
assert(address->type != TOPO_ADDR_NAT); /* тестовый внешний порт не опубликован */ |
|
|
|
assert(address->type != TOPO_ADDR_NAT); /* тестовый внешний порт не опубликован */ |
|
|
|
struct UTUN_INSTANCE* observer = nat_fixture_node(&nf, "127.0.0.5", NULL, NULL); |
|
|
|
struct UTUN_INSTANCE* observer = nat_fixture_node(&nf, "127.0.0.5", NULL, NULL); |
|
|
|
nat_fixture_connect(&nf, owner, "udp", observer); nat_detection_request_check_all(owner->nat_det); |
|
|
|
nat_fixture_connect(&nf, owner, "udp", observer); nat_detection_request_check_all(owner->nat_det); |
|
|
|
uint64_t end = get_time_tb() + 300000; |
|
|
|
end = get_time_tb() + 300000; |
|
|
|
do { test_clock_poll(nf.ua, 10000); nat_detection_get_status(owner->nat_det, socket, &status); } |
|
|
|
do { test_clock_poll(nf.ua, 10000); nat_detection_get_status(owner->nat_det, socket, &status); } |
|
|
|
while (get_time_tb() < end && status.reason != NAT_REASON_NO_HELPER); |
|
|
|
while (get_time_tb() < end && status.reason != NAT_REASON_NO_HELPER); |
|
|
|
assert(status.reason == NAT_REASON_NO_HELPER && socket->address_profile.source == ADDRESS_SOURCE_STUN); |
|
|
|
assert(status.reason == NAT_REASON_NO_HELPER && socket->address_profile.source == ADDRESS_SOURCE_NONE); |
|
|
|
struct UTUN_INSTANCE* helper = nat_fixture_node(&nf, "127.0.0.6", NULL, NULL); |
|
|
|
struct UTUN_INSTANCE* helper = nat_fixture_node(&nf, "127.0.0.6", NULL, NULL); |
|
|
|
nat_fixture_connect(&nf, observer, "udp", helper); nat_detection_request_check_all(owner->nat_det); |
|
|
|
nat_fixture_connect(&nf, observer, "udp", helper); nat_detection_request_check_all(owner->nat_det); |
|
|
|
wait_source(&nf, socket, ADDRESS_SOURCE_ETCP); wait_source(&nf, duplicate, ADDRESS_SOURCE_ETCP); |
|
|
|
wait_source(&nf, socket, ADDRESS_SOURCE_ETCP); wait_source(&nf, duplicate, ADDRESS_SOURCE_ETCP); |
|
|
|
@ -427,7 +430,7 @@ static void test_fallback(void) { |
|
|
|
assert(!uasync_remove_socket_t(nf.ua, server.endpoints[i].fd)); socket_close_wrapper(server.endpoints[i].fd); |
|
|
|
assert(!uasync_remove_socket_t(nf.ua, server.endpoints[i].fd)); socket_close_wrapper(server.endpoints[i].fd); |
|
|
|
} |
|
|
|
} |
|
|
|
socket_close_wrapper(server.source.fd); nat_fixture_cleanup(&nf); |
|
|
|
socket_close_wrapper(server.source.fd); nat_fixture_cleanup(&nf); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_NAT, "PASS STUN fallback: no peers, no independent helper, ETCP priority, unchanged real endpoint"); |
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_NAT, "PASS STUN isolation: diagnostics never replace the measured working endpoint"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int main(void) { |
|
|
|
int main(void) { |
|
|
|
|