|
|
|
|
@ -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 <stdio.h> |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
@ -11,6 +11,7 @@
|
|
|
|
|
#include <arpa/inet.h> |
|
|
|
|
#include <sys/wait.h> |
|
|
|
|
#include <sys/stat.h> |
|
|
|
|
#include <fcntl.h> |
|
|
|
|
#include <time.h> |
|
|
|
|
#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); } |
|
|
|
|
|