#include #include #include #include #include #include #include #include #include #include "../src/etcp.h" #include "../src/etcp_connections.h" #include "../src/config_parser.h" #include "../src/utun_instance.h" #include "../src/routing.h" #include "../src/tun_if.h" #include "../src/secure_channel.h" #include "../lib/u_async.h" #define TEST_TIMEOUT_MS 5000 struct test_instance { struct UTUN_INSTANCE* instance; const char* config_file; pthread_t thread; int ready; }; static void* instance_thread(void* arg) { struct test_instance* ti = (struct test_instance*)arg; // Create instance ti->instance = utun_instance_create(uasync_create(), ti->config_file, NULL); if (!ti->instance) { printf("Failed to create instance from %s\n", ti->config_file); return NULL; } printf("Instance %s created successfully\n", ti->config_file); // Debug: print config servers if (ti->instance->config) { printf("Config for %s has servers:\n", ti->config_file); struct CFG_SERVER* srv = ti->instance->config->servers; while (srv) { printf(" Server '%s'\n", srv->name); srv = srv->next; } } // Initialize instance (TUN, routing, etc) if (utun_instance_init(ti->instance) < 0) { printf("Failed to initialize instance %s\n", ti->config_file); utun_instance_destroy(ti->instance); ti->instance = NULL; return NULL; } // Register sockets with uasync if (utun_instance_register_sockets(ti->instance) < 0) { printf("Failed to register sockets for %s\n", ti->config_file); utun_instance_destroy(ti->instance); ti->instance = NULL; return NULL; } // Initialize connections (this will start handshake for clients) if (init_connections(ti->instance) < 0) { printf("Failed to init connections for %s\n", ti->config_file); utun_instance_destroy(ti->instance); ti->instance = NULL; return NULL; } ti->ready = 1; printf("Instance %s ready (node_id=%llx)\n", ti->config_file, (unsigned long long)ti->instance->node_id); // Run event loop while (ti->instance && ti->instance->running) { uasync_poll(ti->instance->ua, 10); } return NULL; } static void dump_connections(struct UTUN_INSTANCE* instance, const char* name) { printf("\n=== %s connections state ===\n", name); if (!instance->connections) { printf("No connections\n"); return; } struct ETCP_CONN* conn = instance->connections; int conn_idx = 0; while (conn) { printf("Connection %d: peer_node_id=%llx\n", conn_idx, (unsigned long long)conn->peer_node_id); struct ETCP_LINK* link = conn->links; int link_idx = 0; while (link) { printf(" Link %d: initialized=%d, is_server=%d, init_timer=%s, timeout=%dms, retry=%d\n", link_idx, link->initialized, link->is_server, link->init_timer ? "active" : "null", link->init_timeout, link->init_retry_count); link = link->next; link_idx++; } conn = conn->next; conn_idx++; } } int main() { printf("=== ETCP Full Connection Test with Real Instances ===\n\n"); // Create config files in test directory FILE* server_conf = fopen("test_server.conf", "w"); fprintf(server_conf, "[global]\n"); fprintf(server_conf, "my_node_id=0x1111111111111111\n"); fprintf(server_conf, "my_private_key=1313912e5d34768983b0e06530a48c77816d228a5b5605e1ab3dc443d107a3dc\n"); fprintf(server_conf, "my_public_key=dde6cec8a9023339a758f60883ef41534d24a1ffdc09bbb787a5c24ddfd891e3092461835a97d37944c681fc6b2c1f5acde8ad192f7d2cdc9920aa0d3ff78e99\n"); fprintf(server_conf, "tun_ip=10.99.0.1/24\n"); fprintf(server_conf, "tun_ifname=tun99\n"); fprintf(server_conf, "\n[server:test]\n"); fprintf(server_conf, "addr=127.0.0.1:9001\n"); fprintf(server_conf, "type=public\n"); fclose(server_conf); FILE* client_conf = fopen("test_client.conf", "w"); fprintf(client_conf, "[global]\n"); fprintf(client_conf, "my_node_id=0x2222222222222222\n"); fprintf(client_conf, "my_private_key=1313912e5d34768983b0e06530a48c77816d228a5b5605e1ab3dc443d107a3dc\n"); fprintf(client_conf, "my_public_key=dde6cec8a9023339a758f60883ef41534d24a1ffdc09bbb787a5c24ddfd891e3092461835a97d37944c681fc6b2c1f5acde8ad192f7d2cdc9920aa0d3ff78e99\n"); fprintf(client_conf, "tun_ip=10.99.0.2/24\n"); fprintf(client_conf, "tun_ifname=tun98\n"); fprintf(client_conf, "\n[client:test_client]\n"); fprintf(client_conf, "peer_node_id=0x1111111111111111\n"); fprintf(client_conf, "keepalive=1\n"); fprintf(client_conf, "link=127.0.0.1:9001\n"); fclose(client_conf); // Create test instances struct test_instance server = {.config_file = "test_server.conf"}; struct test_instance client = {.config_file = "test_client.conf"}; printf("Starting server instance...\n"); if (pthread_create(&server.thread, NULL, instance_thread, &server) != 0) { printf("Failed to create server thread\n"); return 1; } printf("Starting client instance...\n"); if (pthread_create(&client.thread, NULL, instance_thread, &client) != 0) { printf("Failed to create client thread\n"); return 1; } // Wait for instances to be ready int wait_count = 0; while ((!server.ready || !client.ready) && wait_count < 100) { usleep(50000); wait_count++; } if (!server.ready || !client.ready) { printf("Instances failed to initialize\n"); return 1; } printf("\n=== Monitoring connection state ===\n"); // Monitor connection state for 5 seconds int established = 0; int elapsed = 0; while (elapsed < TEST_TIMEOUT_MS) { // Check client connection to server struct ETCP_CONN* client_conn = client.instance->connections; while (client_conn) { if (client_conn->peer_node_id == 0x1111111111111111ULL) { struct ETCP_LINK* link = client_conn->links; while (link) { if (link->initialized && link->is_server == 0) { printf("SUCCESS: Client connection established!\n"); established = 1; break; } link = link->next; } } if (established) break; client_conn = client_conn->next; } if (established) break; // Dump state every second if (elapsed % 1000 == 0) { dump_connections(server.instance, "Server"); dump_connections(client.instance, "Client"); } usleep(100000); elapsed += 100; } // Cleanup printf("\n=== Cleaning up ===\n"); if (server.instance) { server.instance->running = 0; } if (client.instance) { client.instance->running = 0; } pthread_join(server.thread, NULL); pthread_join(client.thread, NULL); // Cleanup config files unlink("test_server.conf"); unlink("test_client.conf"); if (established) { printf("\n=== TEST PASSED ===\n"); return 0; } else { printf("\n=== TEST FAILED ===\n"); return 1; } }