diff --git a/lib/u_async.c b/lib/u_async.c index 6bb2fdb8..63bf3726 100644 --- a/lib/u_async.c +++ b/lib/u_async.c @@ -924,7 +924,6 @@ static void process_epoll_events(struct UASYNC* ua, struct epoll_event* events, int fd = (int)(events[i].data.u64 & 0xFFFFFFFF); uint16_t ev_gen = (uint16_t)(events[i].data.u64 >> 32); - if (fd == 0) struct socket_node* node = socket_array_get(ua->sockets, fd); if (!node || !node->active) continue; if (node->gen != ev_gen) { DEBUG_ERROR(DEBUG_CATEGORY_UASYNC, "EPOLL STALE fd=%d ev_gen=%u node_gen=%u — skipped", fd, ev_gen, node->gen); continue; } diff --git a/tests/test_socks_http_proxy.c b/tests/test_socks_http_proxy.c index b8c02168..928d8c17 100644 --- a/tests/test_socks_http_proxy.c +++ b/tests/test_socks_http_proxy.c @@ -1,5 +1,5 @@ -// test_socks_http_proxy.c — стресс-тест SOCKS5 + HTTP CONNECT proxy, многопоточная прокачка -// 4 worker'а параллельно: 2×SOCKS + 2×HTTP, каждый по 50 запросов (1KB..1MB), всего 200 запросов +// test_socks_http_proxy.c — SOCKS5 + HTTP CONNECT proxy integration test +// 2 workers (1 SOCKS + 1 HTTP), 25 reqs each, files up to 100KB #include #include #include @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "../lib/platform_compat.h" #include "test_utils.h" @@ -27,25 +28,25 @@ #include "../src/routing.h" #include "../src/tun_if.h" -#define TIMEOUT_MS 60000 -#define WORKERS 2 // 1 SOCKS + 1 HTTP +#define TIMEOUT_MS 120000 +#define WORKERS 2 #define REQS_PER_WORKER 25 -// Размеры тестовых файлов и сколько запросов каждого на одного worker'а (sum = 25) static const int file_sizes[] = { 1024, 10*1024, 50*1024, 100*1024 }; -static const int file_counts[] = { 8, 7, 5, 5 }; +static const int file_counts[] = { 8, 7, 5, 5 }; // sum = 25 +static const char* file_names[] = { "f_1k.bin", "f_10k.bin", "f_50k.bin", "f_100k.bin" }; +static const int num_files = 4; static struct UTUN_INSTANCE* g_cli = NULL; static struct UTUN_INSTANCE* g_srv = NULL; static struct UASYNC* g_ua = NULL; -static int g_ok = 0, g_done = 0; +static int g_ok = 0, g_done = 0, g_phase = 0; static pid_t g_http_pid = 0; static pid_t g_workers[WORKERS]; static int g_http_port = 0, g_cli_port = 0, g_srv_port = 0; static int g_socks_port = 0, g_http_proxy_port = 0; static char g_tmpdir[256]; static void* g_mon_id = NULL; -static int g_phase = 0; static int alloc_port(void) { int s = socket(AF_INET, SOCK_STREAM, 0); @@ -59,7 +60,6 @@ static int alloc_port(void) { close(s); return -1; } -// Генерация детерминированного файла (инкрементальный паттерн с сидом) static void gen_file(const char* path, int size, int seed) { FILE* f = fopen(path, "wb"); if (!f) return; @@ -122,41 +122,33 @@ static int conn_ready(struct UTUN_INSTANCE* inst) { return 0; } -// ==================================================================== -// Worker: дочерний процесс, делает curl-запросы через прокси и сверяет -// ==================================================================== static int worker_main(const char* type, const char* proxy, const char* url_base, const char* tmpdir) { - for (int fi = 0; fi < 4; fi++) { - int size = file_sizes[fi], count = file_counts[fi]; - char fname[32], expected[512], outfile[512]; - snprintf(fname, sizeof(fname), "f_%d.bin", size); - snprintf(expected, sizeof(expected), "%s/%s", tmpdir, fname); - snprintf(outfile, sizeof(outfile), "%s/out_%d_%s_%%d.bin", tmpdir, (int)getpid(), fname); + for (int fi = 0; fi < num_files; fi++) { + int count = file_counts[fi]; + char expected[512]; + snprintf(expected, sizeof(expected), "%s/%s", tmpdir, file_names[fi]); for (int i = 0; i < count; i++) { char cmd[1024], out[512], url[512]; - snprintf(out, sizeof(out), "%s/out_%d_%s_%d.bin", tmpdir, (int)getpid(), fname, i); - snprintf(url, sizeof(url), "%s/%s", url_base, fname); + snprintf(out, sizeof(out), "%s/out_%d_%s_%d.bin", tmpdir, (int)getpid(), file_names[fi], i); + snprintf(url, sizeof(url), "%s/%s", url_base, file_names[fi]); if (strcmp(type, "socks") == 0) - snprintf(cmd, sizeof(cmd), "curl -s --connect-timeout 5 --max-time 5 --socks5-hostname %s -o %s %s 2>/dev/null", proxy, out, url); + snprintf(cmd, sizeof(cmd), "curl -s --connect-timeout 10 --max-time 30 --socks5-hostname %s -o %s %s 2>/dev/null", proxy, out, url); else - snprintf(cmd, sizeof(cmd), "curl -s --connect-timeout 5 --max-time 5 --proxytunnel -x %s -o %s %s 2>/dev/null", proxy, out, url); + snprintf(cmd, sizeof(cmd), "curl -s --connect-timeout 10 --max-time 30 --proxytunnel -x %s -o %s %s 2>/dev/null", proxy, out, url); int rc = system(cmd); - if (rc != 0) { fprintf(stderr, "[FAIL] worker %s %s iter %d curl exit %d\n", type, fname, i, WEXITSTATUS(rc)); return 1; } + if (rc != 0) { fprintf(stderr, "[FAIL] worker %s %s iter %d curl exit %d\n", type, file_names[fi], i, WEXITSTATUS(rc)); return 1; } char cmp_cmd[1024]; snprintf(cmp_cmd, sizeof(cmp_cmd), "cmp -s %s %s", out, expected); - if (system(cmp_cmd) != 0) { fprintf(stderr, "[FAIL] worker %s %s iter %d mismatch\n", type, fname, i); return 1; } + if (system(cmp_cmd) != 0) { fprintf(stderr, "[FAIL] worker %s %s iter %d mismatch\n", type, file_names[fi], i); return 1; } unlink(out); } } return 0; } -// ==================================================================== -// Монитор-таймер -// ==================================================================== static void monitor(void* arg) { (void)arg; if (g_done) return; @@ -181,7 +173,6 @@ static void monitor(void* arg) { } } - // Проверяем завершение worker'ов if (g_phase == 1) { int done_count = 0, fail = 0; for (int i = 0; i < WORKERS; i++) { @@ -208,6 +199,9 @@ static void test_timeout(void* arg) { int main(void) { printf("=== test_socks_http_proxy ===\n"); fflush(stdout); + // Резервируем fd 0 + { int fd = open("/dev/null", O_RDONLY); if (fd > 0 && fd != 0) { dup2(fd, 0); close(fd); } else if (fd < 0) { close(0); open("/dev/null", O_RDONLY); } } + debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR); debug_set_categories(DEBUG_CATEGORY_ALL); utun_instance_set_tun_init_enabled(0); srand((unsigned)time(NULL)); @@ -222,16 +216,14 @@ int main(void) { strcpy(g_tmpdir, "/tmp/utun_test_XXXXXX"); if (test_mkdtemp(g_tmpdir) < 0) { printf("[FAIL] mkdtemp: %s\n", strerror(errno)); return 1; } - // Генерируем тестовые файлы (детерминированный паттерн) int seed = (int)time(NULL) ^ (int)getpid(); - for (int fi = 0; fi < 4; fi++) { - char path[512]; snprintf(path, sizeof(path), "%s/f_%d.bin", g_tmpdir, file_sizes[fi]); + for (int fi = 0; fi < num_files; fi++) { + char path[512]; snprintf(path, sizeof(path), "%s/%s", g_tmpdir, file_names[fi]); gen_file(path, file_sizes[fi], seed + fi); } - printf(" test files generated: 1k, 10k, 50k, 100k\n"); + printf(" test files: 1k, 10k, 50k, 100k\n"); fflush(stdout); if (start_http_server(g_http_port, g_tmpdir) < 0) { printf("[FAIL] start http server\n"); goto cleanup; } - printf(" python3 http.server on :%d\n", g_http_port); g_ua = uasync_create(); if (!g_ua) { printf("[FAIL] uasync_create\n"); goto cleanup; } @@ -250,11 +242,10 @@ int main(void) { if (to_id) uasync_cancel_timeout(g_ua, to_id); - if (g_ok) printf("[PASS] test_socks_http_proxy — %d reqs, 2 workers (socks+http), up to 100KB\n", WORKERS * REQS_PER_WORKER); + if (g_ok) printf("[PASS] test_socks_http_proxy — %d reqs, %d workers, up to 100KB\n", WORKERS * REQS_PER_WORKER, WORKERS); else printf("[FAIL] test_socks_http_proxy\n"); cleanup: - // Убиваем оставшихся workers for (int i = 0; i < WORKERS; i++) if (g_workers[i] > 0) { kill(g_workers[i], SIGKILL); waitpid(g_workers[i], NULL, 0); } if (g_mon_id) uasync_cancel_timeout(g_ua, g_mon_id); if (g_http_pid > 0) { kill(g_http_pid, SIGKILL); waitpid(g_http_pid, NULL, 0); }