|
|
|
|
@ -48,6 +48,67 @@ static void check_snapshot(struct UTUN_INSTANCE *owner, struct ETCP_SOCKET *sock
|
|
|
|
|
sqlite3_finalize(statement); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Недостаточная UTUN-группа и достаточная CHAT-группа; helper доступен только через TCP next hop. */ |
|
|
|
|
static void test_all_groups_tcp(void) { |
|
|
|
|
struct nat_fixture fixture; nat_fixture_init(&fixture); |
|
|
|
|
struct UTUN_INSTANCE *owner = nat_fixture_node(&fixture, "127.0.0.2", NULL, "[chatserver]\ngroup_autoconnect=0\n"); |
|
|
|
|
struct UTUN_INSTANCE *observer = nat_fixture_node(&fixture, "127.0.0.3", NULL, |
|
|
|
|
"[server:tcp]\naddr=127.0.0.3:0\ntype=public\ntransport=tcp\n[chatserver]\ngroup_autoconnect=0\n"); |
|
|
|
|
struct UTUN_INSTANCE *helper = nat_fixture_node(&fixture, "127.0.0.4", NULL, |
|
|
|
|
"[server:tcp]\naddr=127.0.0.4:0\ntype=public\ntransport=tcp\n[chatserver]\ngroup_autoconnect=0\n"); |
|
|
|
|
nat_detection_set_automatic(observer->nat_det, 0); nat_detection_set_automatic(helper->nat_det, 0); |
|
|
|
|
struct ETCP_CONN *ab = nat_fixture_connect(&fixture, owner, "udp", observer); |
|
|
|
|
struct ETCP_SOCKET *socket = test_etcp_bound_socket(owner, "udp"); |
|
|
|
|
nat_detection_request_check_all(owner->nat_det); |
|
|
|
|
struct nat_check_status status = {0}; uint64_t end = get_time_tb() + 30000; |
|
|
|
|
do { uasync_poll(fixture.ua, 10); assert(!nat_detection_get_status(owner->nat_det, socket, &status)); } |
|
|
|
|
while (get_time_tb() < end && status.reason != NAT_REASON_NO_HELPER); |
|
|
|
|
assert(status.reason == NAT_REASON_NO_HELPER && !socket->address_profile.source); |
|
|
|
|
|
|
|
|
|
struct UTUN_INSTANCE *nodes[] = {owner, observer, helper}; |
|
|
|
|
struct TOPO_GROUP *groups[3]; uint8_t signature[64] = {1}; |
|
|
|
|
for (unsigned i = 0; i < 3; i++) { |
|
|
|
|
sqlite3 *db = nodes[i]->topo_sqlite_db; |
|
|
|
|
assert(!topo_node_sqlite_channel_put(db, "42", "NAT group test", owner->node_id, owner->my_keys.public_key, |
|
|
|
|
NULL, owner->my_ed25519_pubkey, NULL, signature)); |
|
|
|
|
for (unsigned j = 0; j < 3; j++) |
|
|
|
|
assert(!topo_node_sqlite_member_block_put(db, "42", nodes[j]->node_id, signature, 1, signature, 1, |
|
|
|
|
nodes[j]->my_keys.public_key, nodes[j]->my_ed25519_pubkey, "{}", NULL, 0, signature)); |
|
|
|
|
groups[i] = topo_groups_create_group(nodes[i]->topo_groups, 42, TOPO_GROUP_TYPE_CHAT, "42"); |
|
|
|
|
assert(groups[i]); |
|
|
|
|
} |
|
|
|
|
assert(!topo_group_new_conn(groups[0], ab)); |
|
|
|
|
struct TOPO_NODE *node = topo_node_registry_find(helper->topo_groups, helper->node_id); |
|
|
|
|
struct NODE_CONN_DIRECT **handle = &fixture.handles[fixture.handle_count++]; |
|
|
|
|
assert(node_conn_direct_open_node(observer, helper->node_id, NULL, NULL, handle, node, |
|
|
|
|
test_etcp_bound_socket(observer, "tcp")) != NCD_ERR); |
|
|
|
|
struct ETCP_CONN *bc = NULL; end = get_time_tb() + 50000; |
|
|
|
|
do { uasync_poll(fixture.ua, 10); bc = node_conn_direct_get_conn(*handle); } |
|
|
|
|
while (get_time_tb() < end && (!bc || !bc->links_up)); |
|
|
|
|
assert(bc && bc->links_up && !topo_group_new_conn(groups[1], bc)); |
|
|
|
|
for (struct ETCP_LINK *link = bc->links; link; link = link->next) assert(link->is_tcp); |
|
|
|
|
end = get_time_tb() + 50000; |
|
|
|
|
while (get_time_tb() < end && (!topo_group_peer_ready(groups[0], observer->node_id) || |
|
|
|
|
!topo_group_peer_ready(groups[1], helper->node_id) || !topo_node_best_path(topo_node_find_by_id(groups[0], helper->node_id)))) |
|
|
|
|
uasync_poll(fixture.ua, 10); |
|
|
|
|
assert(topo_group_peer_ready(groups[0], observer->node_id) && topo_group_peer_ready(groups[1], helper->node_id)); |
|
|
|
|
assert(!instance_find_conn(owner, helper->node_id)); |
|
|
|
|
wait_profile(&fixture, socket, ADDRESS_MAP_UNCHANGED, ADDRESS_IN_OPEN); |
|
|
|
|
assert(!nat_detection_get_status(owner->nat_det, socket, &status) && status.group_id == 42 && status.helper == helper->node_id); |
|
|
|
|
assert(!instance_find_conn(owner, helper->node_id)); |
|
|
|
|
uint64_t old_round = status.round; |
|
|
|
|
assert(!nat_detection_request_check_socket(owner->nat_det, socket, observer->node_id)); |
|
|
|
|
end = get_time_tb() + 30000; |
|
|
|
|
do { uasync_poll(fixture.ua, 10); assert(!nat_detection_get_status(owner->nat_det, socket, &status)); } |
|
|
|
|
while (get_time_tb() < end && (status.round == old_round || !status.phase)); |
|
|
|
|
assert(status.phase && status.group_id == 42); |
|
|
|
|
topo_groups_remove_group(owner->topo_groups, 42); |
|
|
|
|
assert(!nat_detection_get_status(owner->nat_det, socket, &status) && !status.phase && !status.group_id); |
|
|
|
|
assert(socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && socket->address_profile.inbound == ADDRESS_IN_OPEN); |
|
|
|
|
assert(ab->links_up && topo_group_peer_ready(topo_groups_find(owner->topo_groups, TOPO_GROUP_UTUN), observer->node_id)); |
|
|
|
|
nat_fixture_cleanup(&fixture); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int main(void) { |
|
|
|
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_NAT, DEBUG_LEVEL_DEBUG); |
|
|
|
|
debug_set_category_level(DEBUG_CATEGORY_BGP, DEBUG_LEVEL_DEBUG); |
|
|
|
|
@ -129,5 +190,6 @@ int main(void) {
|
|
|
|
|
assert(socket->address_profile.mapping == ADDRESS_MAP_UNKNOWN && socket->address_profile.inbound == ADDRESS_IN_UNKNOWN); |
|
|
|
|
|
|
|
|
|
nat_fixture_cleanup(&fixture); |
|
|
|
|
test_all_groups_tcp(); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|