Run call path regression with admitted CHAT members over shared transport

This commit is contained in:
evgeny committed 2026-11-04 01:56:40 +01:00
1 parent 9b4ef4d83b
commit 189c61c3de
1 file changed
+35 -7
+35 -7
View File
@@ -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);