tests: hold OS-assigned HTTP and SOCKS listener ports
This commit is contained in:
1 parent
08865b2909
commit
4e2cc0e35a
4 files changed
+53
-51
No files matched your search
@@ -20,6 +20,9 @@
|
||||
#include <time.h>
|
||||
#include "../lib/platform_compat.h"
|
||||
#include "test_utils.h"
|
||||
#include "test_net.h"
|
||||
#include "../src/proxy/socks_proxy.h"
|
||||
#include "../src/proxy/tcp_proxy_client.h"
|
||||
#include "../lib/u_async.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include "../lib/ll_queue.h"
|
||||
@@ -58,18 +61,6 @@ static char g_cert[512], g_key[512];
|
||||
static void* g_mon_id = NULL;
|
||||
static int g_file_seed = 0;
|
||||
|
||||
static int alloc_port(void) {
|
||||
int s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0) return -1;
|
||||
struct sockaddr_in a; memset(&a, 0, sizeof(a));
|
||||
a.sin_family = AF_INET; a.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
for (int i = 0; i < 200; i++) {
|
||||
a.sin_port = htons((uint16_t)(20000 + (rand() % 40000)));
|
||||
if (bind(s, (struct sockaddr*)&a, sizeof(a)) == 0) { close(s); return ntohs(a.sin_port); }
|
||||
}
|
||||
close(s); return -1;
|
||||
}
|
||||
|
||||
static void gen_file(const char* path, int size, int seed) {
|
||||
FILE* f = fopen(path, "wb");
|
||||
if (!f) { fprintf(stderr, "gen_file: fopen(%s) failed\n", path); return; }
|
||||
@@ -83,7 +74,7 @@ static void gen_file(const char* path, int size, int seed) {
|
||||
}
|
||||
|
||||
// Сервер сообщает готовность после listen и настройки TLS; EOF обнаруживает ошибку запуска без паузы.
|
||||
static int wait_server_ready(int fd, int port, const char* name) {
|
||||
static int wait_server_ready(int fd, int* port, const char* name) {
|
||||
uint64_t start = get_time_us(), deadline = start + 5000000;
|
||||
struct pollfd pfd = {.fd = fd, .events = POLLIN};
|
||||
int result;
|
||||
@@ -91,21 +82,23 @@ static int wait_server_ready(int fd, int port, const char* name) {
|
||||
uint64_t now = get_time_us();
|
||||
result = poll(&pfd, 1, now < deadline ? (int)((deadline - now + 999) / 1000) : 0);
|
||||
} while (result < 0 && errno == EINTR);
|
||||
char marker = 0;
|
||||
ssize_t bytes = result > 0 ? read(fd, &marker, 1) : -1;
|
||||
uint8_t assigned[2] = {0};
|
||||
ssize_t bytes = result > 0 ? read(fd, assigned, sizeof(assigned)) : -1;
|
||||
int error = result < 0 || (result > 0 && bytes < 0) ? errno : 0;
|
||||
close(fd);
|
||||
if (result <= 0 || bytes != 1 || marker != 'R') {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "test %s server startup failed: port=%d poll=%d events=%x bytes=%ld marker=%d errno=%d",
|
||||
name, port, result, pfd.revents, (long)bytes, marker, error);
|
||||
int actual = ((int)assigned[0] << 8) | assigned[1];
|
||||
if (result <= 0 || bytes != sizeof(assigned) || !actual) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "test %s server startup failed: poll=%d events=%x bytes=%ld port=%d errno=%d",
|
||||
name, result, pfd.revents, (long)bytes, actual, error);
|
||||
return -1;
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "test %s server ready: port=%d elapsed=%lluus", name, port,
|
||||
*port = actual;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "test %s server ready: port=%d elapsed=%lluus", name, *port,
|
||||
(unsigned long long)(get_time_us() - start));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int start_http_server(int port, const char* dir) {
|
||||
static int start_http_server(int* port, const char* dir) {
|
||||
char script[512]; snprintf(script, sizeof(script), "%s/_srv.py", dir);
|
||||
FILE* sf = fopen(script, "w");
|
||||
if (!sf) return -1;
|
||||
@@ -130,7 +123,7 @@ static int start_http_server(int port, const char* dir) {
|
||||
"port=int(sys.argv[1])\n"
|
||||
"os.chdir(sys.argv[2])\n"
|
||||
"httpd=HTTPServer(('127.0.0.1',port),H)\n"
|
||||
"ready=int(sys.argv[3]);os.write(ready,b'R');os.close(ready)\n"
|
||||
"ready=int(sys.argv[3]);os.write(ready,httpd.server_port.to_bytes(2,'big'));os.close(ready)\n"
|
||||
"httpd.serve_forever()\n"
|
||||
);
|
||||
fclose(sf);
|
||||
@@ -144,9 +137,8 @@ static int start_http_server(int port, const char* dir) {
|
||||
}
|
||||
if (pid == 0) {
|
||||
close(ready[0]);
|
||||
char port_str[16], ready_str[16];
|
||||
snprintf(port_str, sizeof(port_str), "%d", port); snprintf(ready_str, sizeof(ready_str), "%d", ready[1]);
|
||||
execlp("python3", "python3", script, port_str, dir, ready_str, (char*)NULL);
|
||||
char ready_str[16]; snprintf(ready_str, sizeof(ready_str), "%d", ready[1]);
|
||||
execlp("python3", "python3", script, "0", dir, ready_str, (char*)NULL);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "test HTTP python exec: %s", strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
@@ -155,7 +147,7 @@ static int start_http_server(int port, const char* dir) {
|
||||
return wait_server_ready(ready[0], port, "HTTP");
|
||||
}
|
||||
|
||||
static int start_https_server(int port, const char* dir, const char* cert, const char* key) {
|
||||
static int start_https_server(int* port, const char* dir, const char* cert, const char* key) {
|
||||
char script[512]; snprintf(script, sizeof(script), "%s/_srv_https.py", dir);
|
||||
FILE* sf = fopen(script, "w");
|
||||
if (!sf) return -1;
|
||||
@@ -187,7 +179,7 @@ static int start_https_server(int port, const char* dir, const char* cert, const
|
||||
"httpd=HTTPServer(('127.0.0.1',int(sys.argv[4])),H)\n"
|
||||
"httpd.socket=ctx.wrap_socket(httpd.socket,server_side=True)\n"
|
||||
"httpd.timeout=None\n"
|
||||
"ready=int(sys.argv[5]);os.write(ready,b'R');os.close(ready)\n"
|
||||
"ready=int(sys.argv[5]);os.write(ready,httpd.server_port.to_bytes(2,'big'));os.close(ready)\n"
|
||||
"httpd.serve_forever()\n"
|
||||
);
|
||||
fclose(sf);
|
||||
@@ -201,9 +193,8 @@ static int start_https_server(int port, const char* dir, const char* cert, const
|
||||
}
|
||||
if (pid == 0) {
|
||||
close(ready[0]);
|
||||
char port_str[16], ready_str[16];
|
||||
snprintf(port_str, sizeof(port_str), "%d", port); snprintf(ready_str, sizeof(ready_str), "%d", ready[1]);
|
||||
execlp("python3", "python3", script, cert, key, dir, port_str, ready_str, (char*)NULL);
|
||||
char ready_str[16]; snprintf(ready_str, sizeof(ready_str), "%d", ready[1]);
|
||||
execlp("python3", "python3", script, cert, key, dir, "0", ready_str, (char*)NULL);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "test HTTPS python exec: %s", strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
@@ -487,14 +478,6 @@ int main(void) {
|
||||
utun_instance_set_tun_init_enabled(0);
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
g_http_port = alloc_port(); g_https_port = alloc_port();
|
||||
g_cli_port = alloc_port(); g_srv_port = alloc_port();
|
||||
g_socks_port = alloc_port(); g_http_proxy_port = alloc_port();
|
||||
if (g_http_port < 0 || g_https_port < 0 || g_cli_port < 0 || g_srv_port < 0 || g_socks_port < 0 || g_http_proxy_port < 0) {
|
||||
printf("[FAIL] port allocation\n"); return 1;
|
||||
}
|
||||
printf(" ports: http=%d https=%d socks=%d http_proxy=%d\n", g_http_port, g_https_port, g_socks_port, g_http_proxy_port);
|
||||
|
||||
strcpy(g_tmpdir, "/tmp/utun_test_XXXXXX");
|
||||
if (test_mkdtemp(g_tmpdir) < 0) { printf("[FAIL] mkdtemp: %s\n", strerror(errno)); return 1; }
|
||||
|
||||
@@ -509,8 +492,8 @@ int main(void) {
|
||||
}
|
||||
printf(" test files: 1KB, 100KB, 1MB, 10MB (total %.1fMB)\n", total_mb / (1024.0*1024.0)); fflush(stdout);
|
||||
|
||||
if (start_http_server(g_http_port, g_tmpdir) < 0) { printf("[FAIL] start http server\n"); goto cleanup; }
|
||||
if (start_https_server(g_https_port, g_tmpdir, g_cert, g_key) < 0) { printf("[FAIL] start https server\n"); goto cleanup; }
|
||||
if (start_http_server(&g_http_port, g_tmpdir) < 0) { printf("[FAIL] start http server\n"); goto cleanup; }
|
||||
if (start_https_server(&g_https_port, g_tmpdir, g_cert, g_key) < 0) { printf("[FAIL] start https server\n"); goto cleanup; }
|
||||
printf(" HTTP/HTTPS servers started\n");
|
||||
|
||||
g_ua = uasync_create();
|
||||
@@ -519,6 +502,16 @@ int main(void) {
|
||||
g_srv = utun_instance_create_from_str(g_ua, make_cfg_server());
|
||||
g_cli = utun_instance_create_from_str(g_ua, make_cfg_client());
|
||||
if (!g_srv || !g_cli) { printf("[FAIL] instance create\n"); goto cleanup; }
|
||||
test_etcp_set_peer(g_cli, "c1", g_srv, "s1");
|
||||
g_srv_port = ss_get_port(&test_etcp_bound_socket(g_srv, "s1")->local_addr);
|
||||
g_cli_port = ss_get_port(&test_etcp_bound_socket(g_cli, "s1")->local_addr);
|
||||
struct tcp_proxy_client* proxy = g_cli->tcp_proxy_client;
|
||||
if (!proxy) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "test: proxy client missing"); goto cleanup; }
|
||||
g_socks_port = socks_proxy_get_port(proxy->socks_listen);
|
||||
g_http_proxy_port = socks_proxy_get_port(proxy->http_listen);
|
||||
if (!g_socks_port || !g_http_proxy_port) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "test: proxy listeners missing"); goto cleanup; }
|
||||
printf(" ports: http=%d https=%d socks=%d http_proxy=%d udp_client=%d udp_server=%d\n",
|
||||
g_http_port, g_https_port, g_socks_port, g_http_proxy_port, g_cli_port, g_srv_port);
|
||||
|
||||
if (utun_instance_init(g_srv) < 0 || utun_instance_init(g_cli) < 0) { printf("[FAIL] instance init\n"); goto cleanup; }
|
||||
printf(" waiting for ETCP...\n"); fflush(stdout);
|
||||
|
||||
Reference in new issue
Block a user