|
|
|
|
@ -5,6 +5,7 @@
|
|
|
|
|
#include <string.h> |
|
|
|
|
#include "../lib/platform_compat.h" |
|
|
|
|
#include "test_utils.h" |
|
|
|
|
#include "test_net.h" |
|
|
|
|
|
|
|
|
|
#include "etcp.h" |
|
|
|
|
#include "etcp_api.h" |
|
|
|
|
@ -38,7 +39,8 @@ static char server_config_path[256];
|
|
|
|
|
static char client_config_path[256]; |
|
|
|
|
static int server_port = 0; |
|
|
|
|
static int client_port = 0; |
|
|
|
|
static int next_port = 0; |
|
|
|
|
static socket_t dead_sockets[3] = {SOCKET_INVALID, SOCKET_INVALID, SOCKET_INVALID}; |
|
|
|
|
static unsigned dead_socket_count; |
|
|
|
|
|
|
|
|
|
static uint32_t packets_sent = 0; |
|
|
|
|
static uint32_t packets_received = 0; |
|
|
|
|
@ -52,10 +54,6 @@ static int traffic_corrupt = 0;
|
|
|
|
|
|
|
|
|
|
static int create_temp_configs(void) { |
|
|
|
|
if (test_mkdtemp(temp_dir) != 0) { fprintf(stderr, "Failed to create temp directory\n"); return -1; } |
|
|
|
|
int base_port = 50000 + (getpid() % 15000); |
|
|
|
|
server_port = base_port; |
|
|
|
|
client_port = base_port + 1; |
|
|
|
|
next_port = base_port + 100; |
|
|
|
|
|
|
|
|
|
snprintf(server_config_path, sizeof(server_config_path), "%s/server.conf", temp_dir); |
|
|
|
|
snprintf(client_config_path, sizeof(client_config_path), "%s/client.conf", temp_dir); |
|
|
|
|
@ -73,12 +71,11 @@ static int create_temp_configs(void) {
|
|
|
|
|
"keepalive_adaptive=0\n" |
|
|
|
|
"\n" |
|
|
|
|
"[server: udp0]\n" |
|
|
|
|
"addr=127.0.0.1:%d\n" |
|
|
|
|
"addr=127.0.0.1:0\n" |
|
|
|
|
"type=public\n" |
|
|
|
|
"\n" |
|
|
|
|
"[allowed_keys]\n" |
|
|
|
|
"allow_all=1\n", |
|
|
|
|
server_port); |
|
|
|
|
"allow_all=1\n"); |
|
|
|
|
fclose(f); |
|
|
|
|
|
|
|
|
|
f = fopen(client_config_path, "w"); |
|
|
|
|
@ -94,17 +91,16 @@ static int create_temp_configs(void) {
|
|
|
|
|
"keepalive_adaptive=0\n" |
|
|
|
|
"\n" |
|
|
|
|
"[server: udp0]\n" |
|
|
|
|
"addr=127.0.0.1:%d\n" |
|
|
|
|
"addr=127.0.0.1:0\n" |
|
|
|
|
"type=public\n" |
|
|
|
|
"\n" |
|
|
|
|
"[client: test_client]\n" |
|
|
|
|
"keepalive=1\n" |
|
|
|
|
"peer_public_key=ce8871f07fa056c636d297115f231b08c29cdf94e0d440fce83a07c34416d36a\n" |
|
|
|
|
"link=udp0:127.0.0.1:%d\n" |
|
|
|
|
"link=udp0:127.0.0.1:0\n" |
|
|
|
|
"\n" |
|
|
|
|
"[allowed_keys]\n" |
|
|
|
|
"allow_all=1\n", |
|
|
|
|
client_port, server_port); |
|
|
|
|
"allow_all=1\n"); |
|
|
|
|
fclose(f); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
@ -148,15 +144,28 @@ static void mk_addr(struct sockaddr_storage* out, uint16_t port) {
|
|
|
|
|
sin->sin_port = htons(port); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int alloc_port(void) { return next_port++; } |
|
|
|
|
// Чёрная дыра не читает INIT; удерживаем её порт, чтобы другой параллельный тест не ответил вместо неё.
|
|
|
|
|
static int alloc_dead_port(void) { |
|
|
|
|
if (dead_socket_count == 3) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "test: too many dead endpoints"); abort(); } |
|
|
|
|
socket_t sock = socket_create_udp(AF_INET); |
|
|
|
|
if (sock == SOCKET_INVALID) { DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "test: dead socket creation failed"); abort(); } |
|
|
|
|
struct sockaddr_storage address; mk_addr(&address, 0); |
|
|
|
|
if (bind(sock, (struct sockaddr*)&address, sizeof(struct sockaddr_in)) != 0) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "test: dead socket bind failed err=%d", socket_get_error()); abort(); |
|
|
|
|
} |
|
|
|
|
dead_sockets[dead_socket_count++] = sock; |
|
|
|
|
return test_bound_port(sock); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static struct ETCP_SOCKET* add_udp_socket(struct UTUN_INSTANCE* inst, uint16_t port, const char* name) { |
|
|
|
|
static struct ETCP_SOCKET* add_udp_socket(struct UTUN_INSTANCE* inst, int* port, const char* name) { |
|
|
|
|
struct CFG_SERVER cfg; memset(&cfg, 0, sizeof(cfg)); |
|
|
|
|
snprintf(cfg.name, sizeof(cfg.name), "%s", name); |
|
|
|
|
cfg.type = CFG_SERVER_TYPE_PUBLIC; |
|
|
|
|
cfg.mtu = PACKET_DATA_MAX_MTU; |
|
|
|
|
mk_addr(&cfg.ip, port); |
|
|
|
|
return etcp_socket_add(inst, &cfg); |
|
|
|
|
mk_addr(&cfg.ip, 0); |
|
|
|
|
struct ETCP_SOCKET* sock = etcp_socket_add(inst, &cfg); |
|
|
|
|
if (sock) *port = ss_get_port(&sock->local_addr); |
|
|
|
|
return sock; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static struct ETCP_LINK* find_link_by_remote_port(struct ETCP_CONN* conn, uint16_t port) { |
|
|
|
|
@ -361,10 +370,13 @@ static int start_instances(void) {
|
|
|
|
|
printf("failed to create server\n"); return -1; |
|
|
|
|
} |
|
|
|
|
client_instance = utun_instance_create(ua, client_config_path); |
|
|
|
|
if (client_instance) test_etcp_set_peer(client_instance, "test_client", server_instance, "udp0"); |
|
|
|
|
if (!client_instance || utun_instance_init(client_instance) < 0) { |
|
|
|
|
printf("failed to create client\n"); return -1; |
|
|
|
|
} |
|
|
|
|
etcp_bind(server_instance, 0x7f, receive_test_packet); |
|
|
|
|
server_port = ss_get_port(&test_etcp_bound_socket(server_instance, "udp0")->local_addr); |
|
|
|
|
client_port = ss_get_port(&test_etcp_bound_socket(client_instance, "udp0")->local_addr); |
|
|
|
|
if (poll_until(c_conn_up_both, LINK_UP_TIMEOUT_MS, "initial connection") != 0) { |
|
|
|
|
printf("initial connection timeout\n"); dump_state(); return -1; |
|
|
|
|
} |
|
|
|
|
@ -411,8 +423,8 @@ static int session_a(void) {
|
|
|
|
|
CHECK(sc->reinit_count == srv_reinit0 && cc->reinit_count == cli_reinit0, "reinit during initial traffic"); |
|
|
|
|
|
|
|
|
|
// -- V1: клиент дозванивается до нового серверного сокета S1 --
|
|
|
|
|
int sp1 = alloc_port(); |
|
|
|
|
struct ETCP_SOCKET* s1 = add_udp_socket(server_instance, sp1, "dyn_s1"); |
|
|
|
|
int sp1 = 0; |
|
|
|
|
struct ETCP_SOCKET* s1 = add_udp_socket(server_instance, &sp1, "dyn_s1"); |
|
|
|
|
CHECK(s1, "V1: failed to add server socket S1"); |
|
|
|
|
struct sockaddr_storage s1_addr; mk_addr(&s1_addr, sp1); |
|
|
|
|
struct ETCP_LINK* lc1 = etcp_link_new(cc, c0, &s1_addr, 0); |
|
|
|
|
@ -426,8 +438,8 @@ static int session_a(void) {
|
|
|
|
|
CHECK(check_link_traffic(c0, sp1, "V1") == 0, "V1 link carried no traffic"); |
|
|
|
|
|
|
|
|
|
// -- V2: сервер дозванивается до клиента --
|
|
|
|
|
int sp2 = alloc_port(); |
|
|
|
|
struct ETCP_SOCKET* s2 = add_udp_socket(server_instance, sp2, "dyn_s2"); |
|
|
|
|
int sp2 = 0; |
|
|
|
|
struct ETCP_SOCKET* s2 = add_udp_socket(server_instance, &sp2, "dyn_s2"); |
|
|
|
|
CHECK(s2, "V2: failed to add server socket S2"); |
|
|
|
|
struct sockaddr_storage c0_addr; mk_addr(&c0_addr, client_port); |
|
|
|
|
struct ETCP_LINK* ls2 = etcp_link_new(sc, s2, &c0_addr, 0); |
|
|
|
|
@ -506,13 +518,12 @@ static int session_collision(int which) {
|
|
|
|
|
uint64_t srv_epoch = sc->reset_id, cli_epoch = cc->reset_id; |
|
|
|
|
CHECK(run_traffic(TRAFFIC_PACKETS, TRAFFIC_TIMEOUT_MS) == 0, "traffic before link add failed"); |
|
|
|
|
|
|
|
|
|
int sp3 = alloc_port(); |
|
|
|
|
int cp1 = alloc_port(); |
|
|
|
|
int dead = alloc_port(); |
|
|
|
|
int sp3 = 0, cp1 = 0; |
|
|
|
|
int dead = alloc_dead_port(); |
|
|
|
|
|
|
|
|
|
struct ETCP_SOCKET* s3 = add_udp_socket(server_instance, sp3, "dyn_s3"); |
|
|
|
|
struct ETCP_SOCKET* s3 = add_udp_socket(server_instance, &sp3, "dyn_s3"); |
|
|
|
|
CHECK(s3, "failed to add server socket S3"); |
|
|
|
|
struct ETCP_SOCKET* c1 = add_udp_socket(client_instance, cp1, "dyn_c1"); |
|
|
|
|
struct ETCP_SOCKET* c1 = add_udp_socket(client_instance, &cp1, "dyn_c1"); |
|
|
|
|
CHECK(c1, "failed to add client socket C1"); |
|
|
|
|
|
|
|
|
|
struct sockaddr_storage s3_addr; mk_addr(&s3_addr, sp3); |
|
|
|
|
@ -584,9 +595,9 @@ static int session_cross_socket(void) {
|
|
|
|
|
CHECK(run_traffic(TRAFFIC_PACKETS, TRAFFIC_TIMEOUT_MS) == 0, "initial traffic failed"); |
|
|
|
|
uint32_t srv_reinit = sc->reinit_count, cli_reinit = cc->reinit_count; |
|
|
|
|
uint64_t srv_epoch = sc->reset_id, cli_epoch = cc->reset_id; |
|
|
|
|
int sp1 = alloc_port(), cp1 = alloc_port(); |
|
|
|
|
struct ETCP_SOCKET* s1 = add_udp_socket(server_instance, sp1, "cross_s1"); |
|
|
|
|
struct ETCP_SOCKET* c1 = add_udp_socket(client_instance, cp1, "cross_c1"); |
|
|
|
|
int sp1 = 0, cp1 = 0; |
|
|
|
|
struct ETCP_SOCKET* s1 = add_udp_socket(server_instance, &sp1, "cross_s1"); |
|
|
|
|
struct ETCP_SOCKET* c1 = add_udp_socket(client_instance, &cp1, "cross_c1"); |
|
|
|
|
CHECK(s1 && c1, "failed to add sockets"); |
|
|
|
|
struct sockaddr_storage c1_addr, s0_addr, s1_addr; |
|
|
|
|
mk_addr(&c1_addr, cp1); mk_addr(&s0_addr, server_port); mk_addr(&s1_addr, sp1); |
|
|
|
|
@ -636,7 +647,7 @@ int main(void) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("=== ETCP Multilink Test ===\n"); |
|
|
|
|
printf("server_port=%d client_port=%d dyn_ports=%d..\n", server_port, client_port, next_port); |
|
|
|
|
printf("ports assigned by the operating system for each live socket\n"); |
|
|
|
|
|
|
|
|
|
utun_instance_set_tun_init_enabled(0); |
|
|
|
|
ua = uasync_create(); |
|
|
|
|
@ -651,6 +662,7 @@ int main(void) {
|
|
|
|
|
|
|
|
|
|
if (ua) { uasync_poll(ua, 0); uasync_destroy(ua, 0); ua = NULL; } |
|
|
|
|
cleanup_temp_configs(); |
|
|
|
|
for (unsigned i = 0; i < dead_socket_count; i++) socket_close_wrapper(dead_sockets[i]); |
|
|
|
|
|
|
|
|
|
if (rc == 0) { printf("\n=== ALL TESTS PASSED ===\n"); return 0; } |
|
|
|
|
printf("\n=== TESTS FAILED ===\n"); |
|
|
|
|
|