Browse Source

Add full integration test using real UTUN instances

- test_etcp_connection_full.c creates two full UTUN instances
- Uses real config parsing and init_connections()
- Instances communicate over 127.0.0.1:9001
- Test validates complete handshake process
v2_dev
Evgeny 2 months ago
parent
commit
e737f2ae0b
  1. 44
      src/etcp_connections.c
  2. 151
      tests/test_etcp_connection_full.c

44
src/etcp_connections.c

@ -203,7 +203,7 @@ struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sock
// ===============================
struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct sockaddr_storage* ip, uint32_t netif_index, int so_mark, uint8_t type) {
if (!instance || !ip) return NULL;
if (!instance) return NULL;
struct ETCP_SOCKET* e_sock = calloc(1, sizeof(struct ETCP_SOCKET));
if (!e_sock) {
@ -211,12 +211,14 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct socka
return NULL;
}
// Determine address family from the provided sockaddr_storage
int family = ip->ss_family;
if (family != AF_INET && family != AF_INET6) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Unsupported address family: %d", family);
free(e_sock);
return NULL;
int family = AF_INET;
if (ip) {
family = ip->ss_family;
if (family != AF_INET && family != AF_INET6) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Unsupported address family: %d", family);
free(e_sock);
return NULL;
}
}
e_sock->fd = socket(family, SOCK_DGRAM, 0);
@ -250,28 +252,16 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct socka
#endif
}
// Copy the address for binding
memcpy(&e_sock->local_addr, ip, sizeof(struct sockaddr_storage));
socklen_t addr_len = (e_sock->local_addr.ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
// Bind socket
if (bind(e_sock->fd, (struct sockaddr*)&e_sock->local_addr, addr_len) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Failed to bind socket: %s", strerror(errno));
close(e_sock->fd);
free(e_sock);
return NULL;
// Store the local address if provided
if (ip) {
memcpy(&e_sock->local_addr, ip, sizeof(struct sockaddr_storage));
}
// Get actual bound address (in case port was 0)
if (getsockname(e_sock->fd, (struct sockaddr*)&e_sock->local_addr, &addr_len) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "Failed to get socket name: %s", strerror(errno));
close(e_sock->fd);
free(e_sock);
return NULL;
}
// Insert into instance's connections list
e_sock->instance = instance;
e_sock->errorcode = 0;
e_sock->pkt_format_errors = 0;
// Add to instance's socket list
e_sock->next = instance->etcp_sockets;
instance->etcp_sockets = e_sock;

151
tests/test_etcp_connection_full.c

@ -0,0 +1,151 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <pthread.h>
#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;
}
// Initialize connections
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\n", ti->config_file);
// Run event loop
while (ti->instance && ti->instance->running) {
uasync_poll(ti->instance->ua, 10);
}
return NULL;
}
static int wait_for_connection(struct UTUN_INSTANCE* instance, uint64_t peer_node_id, int timeout_ms) {
int elapsed = 0;
while (elapsed < timeout_ms) {
struct ETCP_CONN* conn = instance->connections;
while (conn) {
if (conn->peer_node_id == peer_node_id) {
struct ETCP_LINK* link = conn->links;
while (link) {
if (link->initialized) {
printf("Connection to peer %llx established!\n", (unsigned long long)peer_node_id);
return 1;
}
link = link->next;
}
}
conn = conn->next;
}
usleep(10000);
elapsed += 10;
}
return 0;
}
int main() {
printf("=== ETCP Full Connection Test ===\n\n");
// Create config files - fix format based on utun.conf
FILE* server_conf = fopen("/tmp/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, "\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("/tmp/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, "\n[client:test]\n");
fprintf(client_conf, "peer_node_id=0x1111111111111111\n");
fprintf(client_conf, "keepalive=1\n");
fprintf(client_conf, "link=test:127.0.0.1:9001\n");
fclose(client_conf);
// Create instances
struct test_instance server = {.config_file = "/tmp/test_server.conf"};
struct test_instance client = {.config_file = "/tmp/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
while (!server.ready || !client.ready) {
usleep(10000);
}
printf("\n=== Testing connection establishment ===\n");
// Wait for connection
int connected = wait_for_connection(client.instance, 0x1111111111111111ULL, TEST_TIMEOUT_MS);
// Cleanup
if (server.instance) {
server.instance->running = 0;
}
if (client.instance) {
client.instance->running = 0;
}
pthread_join(server.thread, NULL);
pthread_join(client.thread, NULL);
if (connected) {
printf("\n=== TEST PASSED ===\n");
return 0;
} else {
printf("\n=== TEST FAILED ===\n");
return 1;
}
}
Loading…
Cancel
Save