You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
7.1 KiB
158 lines
7.1 KiB
/** |
|
* @file test_conn_mgr_already_connected.c |
|
* @brief conn_mgr: подключение к уже-соединённому узлу через instance_find_conn |
|
* |
|
* Проверяет, что conn_mgr_connect_node находит существующее ETCP-соединение |
|
* и сразу вызывает callback с CONN_MGR_OK, а не уходит в фазы установки нового соединения. |
|
*/ |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <stdarg.h> |
|
#include "../lib/platform_compat.h" |
|
#include "test_utils.h" |
|
#ifndef _WIN32 |
|
#include <unistd.h> |
|
#endif |
|
|
|
#include "etcp.h" |
|
#include "etcp_connections.h" |
|
#include "../src/config_parser.h" |
|
#include "../src/config_updater.h" |
|
#include "../src/utun_instance.h" |
|
#include "topo_group.h" |
|
#include "conn_mgr.h" |
|
#include "../lib/u_async.h" |
|
#include "../lib/debug_config.h" |
|
#include "../lib/mem.h" |
|
|
|
#define TOTAL_TIMEOUT_TB 10000 /* 1 sec */ |
|
#define POLL_MS 5 |
|
static struct UTUN_INSTANCE *g_a = NULL, *g_b = NULL; |
|
static struct UASYNC *ua = NULL; |
|
static volatile int result = 0, cb_fired = 0, cb_ok = 0; |
|
static char tdir[] = "/tmp/utun_cm2_XXXXXX"; |
|
static char ca[256], cb[256]; |
|
static int pa = 0, pb = 0; |
|
|
|
static int wf(const char* p, const char* f, ...) { |
|
va_list ap; FILE* fp = fopen(p, "w"); if (!fp) return -1; |
|
va_start(ap, f); vfprintf(fp, f, ap); va_end(ap); fclose(fp); return 0; |
|
} |
|
static char* gv(const char* p, const char* k) { |
|
struct utun_config* c = parse_config(p); if (!c) return NULL; |
|
char* r = (strcmp(k, "pub") == 0) ? u_strdup(c->global.my_public_key_hex) : u_strdup(c->global.my_private_key_hex); |
|
free_config(c); return r; |
|
} |
|
static void fail(const char* msg) { fprintf(stderr, "FAIL: %s\n", msg); fflush(stderr); result = 2; } |
|
static void done(void) { if (result == 0) result = 1; } |
|
static void test_mgr_connect(void* arg); |
|
static void test_check(void* arg); |
|
static void test3_preconnect(void* arg); |
|
static void test3_check(void* arg); |
|
|
|
static void conn_cb(int r, uint64_t id, void* arg) { |
|
(void)arg; |
|
cb_fired = 1; cb_ok = (r == CONN_MGR_OK); |
|
fprintf(stderr, "conn_cb: result=%d node=0x%llx ok=%d\n", r, (unsigned long long)id, cb_ok); fflush(stderr); |
|
} |
|
|
|
static void test_find_conn(void* arg) { |
|
(void)arg; |
|
struct ETCP_CONN* c = instance_find_conn(g_a, g_b->node_id); |
|
if (!c || !c->links) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test_find_conn, "t1w"); return; } |
|
int has = 0; struct ETCP_LINK* l = c->links; |
|
while (l) { if (l->link_state == 3 && l->initialized) { has = 1; break; } l = l->next; } |
|
if (!has) { uasync_set_timeout(ua, 50, NULL, (timeout_callback_t)test_find_conn, "t1w2"); return; } |
|
fprintf(stderr, "Test 1: instance_find_conn OK (link_state=%d)\n", l->link_state); fflush(stderr); |
|
uasync_call_soon(ua, NULL, test_mgr_connect); |
|
} |
|
|
|
static void test_mgr_connect(void* arg) { |
|
(void)arg; |
|
cb_fired = 0; cb_ok = 0; |
|
struct CONN_MGR* mgr = g_a->conn_mgr; |
|
struct TOPO_NODEQ* nq = topo_node_find_by_id(mgr->group, g_b->node_id); |
|
if (nq) { fprintf(stderr, "node already in UTUN group\n"); fflush(stderr); } |
|
fprintf(stderr, "Test 2: conn_mgr_connect_node(B)\n"); fflush(stderr); |
|
conn_mgr_connect_node(mgr, g_b->node_id, 0, conn_cb, NULL); |
|
uasync_call_soon(ua, NULL, test_check); |
|
} |
|
|
|
static void test_check(void* arg) { |
|
(void)arg; |
|
if (!cb_fired) { fail("callback not fired"); done(); return; } |
|
if (!cb_ok) { fail("callback result != CONN_MGR_OK"); done(); return; } |
|
uint8_t st, ty; |
|
conn_mgr_get_status(g_a->conn_mgr, g_b->node_id, &st, &ty); |
|
if (st != CONN_MGR_STATE_CONNECTED) { fail("state != CONNECTED"); done(); return; } |
|
fprintf(stderr, "Test 2: OK state=%d type=%d\n", st, ty); fflush(stderr); |
|
fprintf(stderr, "=== ALL DONE ===\n"); fflush(stderr); |
|
done(); |
|
} |
|
|
|
static void test3_preconnect(void* arg) { |
|
/* Test 3: conn_mgr_connect_node BEFORE ETCP link is up (no instance_find_conn match) */ |
|
(void)arg; |
|
struct CONN_MGR* mgr = g_a->conn_mgr; |
|
cb_fired = 0; cb_ok = 0; |
|
struct ETCP_CONN* c = instance_find_conn(g_a, g_b->node_id); |
|
if (c) { fprintf(stderr, "Test3: SKIP — conn already established\n"); return; } |
|
fprintf(stderr, "Test 3: conn_mgr_connect_node BEFORE link up\n"); fflush(stderr); |
|
conn_mgr_connect_node(mgr, g_b->node_id, 0, conn_cb, NULL); |
|
uasync_call_soon(ua, NULL, test3_check); |
|
} |
|
|
|
static void test3_check(void* arg) { |
|
(void)arg; |
|
if (cb_fired) { |
|
if (cb_ok) { fprintf(stderr, "Test 3: OK — callback CONN_MGR_OK\n"); fflush(stderr); return; } |
|
fail("callback fired with error"); done(); return; |
|
} |
|
/* no callback yet — check if conn_mgr gave up (state reset) */ |
|
uint8_t st, ty; |
|
if (conn_mgr_get_status(g_a->conn_mgr, g_b->node_id, &st, &ty) == CONN_MGR_OK && st == CONN_MGR_STATE_DISCONNECTED) { |
|
/* entry was cleaned up — conn not possible in this test setup with this timing */ |
|
fprintf(stderr, "Test 3: SKIP — entry cleaned up (conn not yet established in time)\n"); fflush(stderr); |
|
return; |
|
} |
|
uasync_set_timeout(ua, 30, NULL, (timeout_callback_t)test3_check, "t3w"); |
|
} |
|
|
|
static void to_cb(void* arg) { (void)arg; fail("timeout"); done(); } |
|
|
|
int main(void) { |
|
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); |
|
utun_instance_set_tun_init_enabled(0); |
|
|
|
test_mkdtemp(tdir); |
|
int base = 49000 + (getpid() % 10000); pa = base; pb = base + 1; |
|
snprintf(ca, sizeof(ca), "%s/a.conf", tdir); snprintf(cb, sizeof(cb), "%s/b.conf", tdir); |
|
wf(ca, "[global]\ntun_ip=10.97.0.1/24\ntun_ifname=tun95\n[server: s1]\naddr=127.0.0.1:%d\ntype=public\n[allowed_keys]\nallow_all=1\n", pa); |
|
wf(cb, "[global]\ntun_ip=10.97.0.2/24\ntun_ifname=tun94\n[server: s1]\naddr=127.0.0.1:%d\ntype=public\n[allowed_keys]\nallow_all=1\n", pb); |
|
config_ensure_keys_and_node_id(ca); config_ensure_keys_and_node_id(cb); |
|
{ struct utun_config* cfa = parse_config(ca); struct utun_config* cfb = parse_config(cb); |
|
free_config(cfa); free_config(cfb); } |
|
char *r0 = gv(ca,"priv"), *p0 = gv(ca,"pub"), *p1 = gv(cb,"pub"); |
|
wf(ca, "[global]\nmy_private_key=%s\nmy_public_key=%s\ntun_ip=10.97.0.1/24\ntun_ifname=tun95\n[server: s1]\naddr=127.0.0.1:%d\ntype=public\n[client: to_b]\nkeepalive=1\npeer_public_key=%s\nlink=s1:127.0.0.1:%d\n[allowed_keys]\nallow_all=1\n", r0, p0, pa, p1, pb); |
|
u_free(r0); u_free(p0); u_free(p1); |
|
|
|
ua = uasync_create(); |
|
g_a = utun_instance_create(ua, ca); g_b = utun_instance_create(ua, cb); |
|
if (!g_a || !g_b) { fprintf(stderr,"create failed\n"); result=2; goto done; } |
|
utun_instance_init(g_a); utun_instance_init(g_b); |
|
|
|
/* Test 3: call conn_mgr BEFORE link is up */ |
|
uasync_call_soon(ua, NULL, test3_preconnect); |
|
/* Test 1+2: run after link is established */ |
|
uasync_call_soon(ua, NULL, test_find_conn); |
|
uasync_set_timeout(ua, TOTAL_TIMEOUT_TB, NULL, to_cb, "to"); |
|
{ int el = 0; while (!result && el < TOTAL_TIMEOUT_TB / 10 + 500) { uasync_poll(ua, POLL_MS); el += POLL_MS; } } |
|
|
|
done: |
|
if (g_a) { g_a->running = 0; utun_instance_destroy(g_a); } |
|
if (g_b) { g_b->running = 0; utun_instance_destroy(g_b); } |
|
if (ua) uasync_destroy(ua, 0); |
|
test_unlink(ca); test_unlink(cb); test_rmdir(tdir); |
|
return (result == 1) ? 0 : 1; |
|
}
|
|
|