From 189c61c3de7d352f47d2acc6665f55da893fbd0d Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 4 Nov 2026 01:56:40 +0100 Subject: [PATCH] Run call path regression with admitted CHAT members over shared transport --- tests/test_conn_mgr_phases.c | 42 ++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/tests/test_conn_mgr_phases.c b/tests/test_conn_mgr_phases.c index dec7d3584..fdff76a34 100644 --- a/tests/test_conn_mgr_phases.c +++ b/tests/test_conn_mgr_phases.c @@ -39,6 +39,7 @@ #include "../lib/mem.h" #include "test_clock.h" #include "test_net.h" +#include "test_membership.h" #define POLL_MS 5 #define LINK_TIMEOUT_MS 8000 @@ -48,6 +49,7 @@ static struct UASYNC* ua = NULL; static struct UTUN_INSTANCE *inst_a = NULL, *inst_b = NULL, *inst_c = NULL; static uint64_t nid_a = 0, nid_b = 0, nid_c = 0; +static uint64_t scenario_group = TOPO_GROUP_UTUN; static volatile int ev_a = -1, ev_b = -1; static struct CONN_MGR_HANDLE *h_a = NULL, *h_b = NULL; @@ -142,7 +144,7 @@ static int has_initialized_link(struct UTUN_INSTANCE* inst) { return 0; } -static struct TOPO_GROUP* defgrp(struct UTUN_INSTANCE* inst) { return topo_groups_get_default(inst->topo_groups); } +static struct TOPO_GROUP* defgrp(struct UTUN_INSTANCE* inst) { return topo_groups_find(inst->topo_groups, scenario_group); } static int learned(struct UTUN_INSTANCE* inst, uint64_t node_id) { return defgrp(inst) && topo_node_find_by_id(defgrp(inst), node_id) != NULL; @@ -253,6 +255,30 @@ static int scenario_setup(void) { return 0; } +/* CALL принадлежит CHAT: отдельная подписанная группа поверх тех же A-C/B-C транспортов. + * Остальные сценарии продолжают проверять UTUN без изменений его политики. */ +static int scenario_chat_group(void) { + const char* channel = "1337"; struct UTUN_INSTANCE* nodes[] = {inst_a, inst_b, inst_c}; + uint8_t signature[64]; + if (sc_ed25519_sign(inst_c->my_ed25519_privkey, (const uint8_t*)channel, strlen(channel), signature) != SC_OK) return -1; + for (unsigned i = 0; i < 3; i++) { + if (topo_node_sqlite_channel_put(nodes[i]->topo_sqlite_db, channel, "call paths", nid_c, + inst_c->my_keys.public_key, NULL, inst_c->my_ed25519_pubkey, NULL, signature)) return -1; + for (unsigned j = 0; j < 3; j++) if (test_member_seed(nodes[i], channel, nodes[j]->my_keys.public_key, + nodes[j]->my_ed25519_pubkey, nodes[j]->my_ed25519_privkey, inst_c->my_ed25519_privkey, "{}", NULL, NULL) < 0) return -1; + if (!topo_groups_create_group(nodes[i]->topo_groups, 1337, TOPO_GROUP_TYPE_CHAT, channel)) return -1; + } + scenario_group = 1337; + for (unsigned i = 0; i < 2; i++) { + if (topo_group_new_conn(defgrp(nodes[i]), instance_find_conn(nodes[i], nid_c)) + || topo_group_new_conn(defgrp(inst_c), instance_find_conn(inst_c, nodes[i]->node_id))) return -1; + } + if (!poll_until(learned_ab, BGP_TIMEOUT_MS)) { fail("CHAT: A/B did not learn each other"); return -1; } + DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "CALL path fixture uses admitted CHAT members group=%llu over shared UTUN transports", + (unsigned long long)scenario_group); + return 0; +} + static void scenario_teardown(void) { if (h_a) { conn_mgr_close(h_a); h_a = NULL; } if (h_b) { conn_mgr_close(h_b); h_b = NULL; } @@ -265,6 +291,7 @@ static void scenario_teardown(void) { up_count = down_count = timeout_count = data_count = expected_marker = 0; close_on_timeout = 0; ev_a = ev_b = -1; + scenario_group = TOPO_GROUP_UTUN; } /* ─── Сценарий 1: DIRECT ─── */ @@ -351,13 +378,13 @@ static void data_recv(struct ETCP_CONN* conn, struct ll_entry* e) { } static int send_data(uint8_t marker, uint64_t hop) { data_count = 0; - struct ETCP_ROUTER_PATH path = etcp_router_get_path(inst_a, TOPO_GROUP_UTUN, nid_b, ETCP_RT_ID_CALL); + struct ETCP_ROUTER_PATH path = etcp_router_get_path(inst_a, scenario_group, nid_b, ETCP_RT_ID_CALL); if (path.next_hop_node_id != (hop == nid_a ? nid_b : hop) || path.type == CONN_TYPE_NONE || (hop == nid_c && path.type != CONN_TYPE_INDIRECT)) { fail("DATA: call path snapshot differs from route"); return -1; } struct ll_entry* e = ll_alloc_lldgram(2); if (!e) return -1; e->dgram[0] = TEST_CM_SERVICE; e->dgram[1] = marker; e->len = 2; - if (etcp_route_send(inst_a, TOPO_GROUP_UTUN, nid_b, e, 1, 0) < 0) { fail("DATA: send failed"); return -1; } + if (etcp_route_send(inst_a, scenario_group, nid_b, e, 1, 0) < 0) { fail("DATA: send failed"); return -1; } uint64_t end = get_time_tb() + 30000; while (!data_count && get_time_tb() < end) test_clock_poll(ua, POLL_MS); if (!data_count || data_hop != hop || expected_marker != marker) { fail("DATA: wrong delivery/hop"); return -1; } @@ -403,15 +430,16 @@ static int run_schedule(void) { static int run_upgrade(void) { fprintf(stderr, "\n=== Scenario 5: one-sided INDIRECT -> late DIRECT ===\n"); if (create_configs("nat", "nat") || scenario_setup()) return -1; + if (scenario_chat_group()) { fail("CALL PATH: signed CHAT fixture initialization failed"); return -1; } if (!poll_until(candidates_a_and_b, 8000)) { fail("UPGRADE: no relay candidates"); return -1; } - struct ETCP_ROUTER_PATH fallback = etcp_router_get_path(inst_a, TOPO_GROUP_UTUN, nid_b, ETCP_RT_ID_CALL); + struct ETCP_ROUTER_PATH fallback = etcp_router_get_path(inst_a, scenario_group, nid_b, ETCP_RT_ID_CALL); if (fallback.type != CONN_TYPE_INDIRECT || fallback.next_hop_node_id != nid_c || cm_find_entry(defgrp(inst_a)->conn_mgr, nid_b)) { fail("UPGRADE: missing BGP fallback snapshot before CM open"); return -1; } mangle_addrs(inst_a, nid_b, wrong_port); mangle_addrs(inst_b, nid_a, wrong_port); inst_a->etcp_connect_timeout_tb = 1000; - if (conn_mgr_open(inst_a, TOPO_GROUP_UTUN, nid_b, conn_cb_a, NULL, &h_a)) return -1; + if (conn_mgr_open(inst_a, scenario_group, nid_b, conn_cb_a, NULL, &h_a)) return -1; struct CONN_MGR_ENTRY* entry = h_a->entry; if (!entry->indirect_started || entry->reverse_started || entry->local_scan_state == CM_TRY_NONE) { fail("UPGRADE: NAT/NAT must start DIRECT/LOCAL/INDIRECT immediately"); return -1; @@ -432,7 +460,7 @@ static int run_upgrade(void) { fail("UPGRADE: missing ownerless incoming relay path"); return -1; } uint64_t owner_start = get_time_tb(); - if (conn_mgr_open(inst_b, TOPO_GROUP_UTUN, nid_a, conn_cb_b, NULL, &h_b)) return -1; + if (conn_mgr_open(inst_b, scenario_group, nid_a, conn_cb_b, NULL, &h_b)) return -1; if (h_b->entry != inbound || inbound->start_tb < owner_start || !inbound->ncd_handle || inbound->reverse_start_tb != inbound->start_tb + CONN_MGR_REVERSE_DELAY_MS * 10 || inbound->conn_type != CONN_TYPE_INDIRECT || !inbound->indirect_confirmed) { @@ -457,7 +485,7 @@ static int run_upgrade(void) { chat_event_set_handler(inst_a, call_event_recv); chat_event_set_handler(inst_b, call_event_recv); call_set_media_recv_cb(inst_b, call_media_recv, NULL); uint64_t call_id = UINT64_C(0x123456789abcdef); - char group_id[32]; snprintf(group_id, sizeof(group_id), "%llu", (unsigned long long)TOPO_GROUP_UTUN); + char group_id[32]; snprintf(group_id, sizeof(group_id), "%llu", (unsigned long long)scenario_group); call_start(inst_a, group_id, nid_b, call_id); if (!poll_until(call_incoming_ready, 3000) || incoming_call != call_id) { fail("CALL PATH: no incoming call"); return -1; } call_accept(inst_b, call_id);