From b16da44e42c75fffeec0251e3ec192703c64bffa Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 10 Oct 2026 16:54:56 +0200 Subject: [PATCH] tests: assign STCP ping and REALITY fallback ports at bind --- tests/test_reality_fallback.c | 15 ++++++++------- tests/test_stcp_ping.c | 35 ++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/tests/test_reality_fallback.c b/tests/test_reality_fallback.c index cc3ad23b..32db4f41 100644 --- a/tests/test_reality_fallback.c +++ b/tests/test_reality_fallback.c @@ -61,14 +61,15 @@ int main(void) { socket_set_nonblocking(dest.sock); CHECK(uasync_add_socket_t(ua, dest.sock, destination_accept, NULL, NULL, "reality_test_listener", &dest)); snprintf(cfg.dest, sizeof(cfg.dest), "127.0.0.1:%u", ntohs(address.sin_port)); - uint16_t port = 32000 + (uint16_t)(time(NULL) % 1000); - struct stcp_server *sa = stcp_server_create(ua, port, &keys, NULL, &a, unexpected_stcp, NULL, NULL, NULL, AF_INET); - struct stcp_server *sb = stcp_server_create(ua, port + 1, &keys, NULL, &b, unexpected_stcp, NULL, NULL, NULL, AF_INET); + struct stcp_server *sa = stcp_server_create(ua, 0, &keys, NULL, &a, unexpected_stcp, NULL, NULL, NULL, AF_INET); + struct stcp_server *sb = stcp_server_create(ua, 0, &keys, NULL, &b, unexpected_stcp, NULL, NULL, NULL, AF_INET); CHECK(sa && sb); stcp_server_set_reality(sa, &cfg); stcp_server_set_reality(sb, &cfg); + uint16_t port_a = stcp_server_get_port(sa), port_b = stcp_server_get_port(sb); + CHECK(port_a && port_b && port_a != port_b); uint8_t ch[REALITY_MAX_CH_SIZE], answer[4096]; size_t cn; fake_now = (uint32_t)time(NULL); CHECK(!reality_client_hello_build_at(&cc, fake_now + 30, ch, sizeof(ch), &cn)); - socket_t first = connect_to(port); CHECK(first != SOCKET_INVALID && send(first, ch, cn, 0) == (ssize_t)cn); + socket_t first = connect_to(port_a); CHECK(first != SOCKET_INVALID && send(first, ch, cn, 0) == (ssize_t)cn); poll_some(ua); CHECK(recv(first, answer, sizeof(answer), 0) >= 127 && answer[0] == 22); /* Через 31 секунду тот же future timestamp ещё допустим: replay обязан оставаться в кеше. */ @@ -82,18 +83,18 @@ int main(void) { pos += 5 + rest; const uint8_t tail[] = {20, 3, 3, 0, 1, 1, 23, 3, 3, 0, 4, 1, 2, 3, 4}; memcpy(split + pos, tail, sizeof(tail)); pos += sizeof(tail); - socket_t replay = connect_to(port); CHECK(replay != SOCKET_INVALID); + socket_t replay = connect_to(port_a); CHECK(replay != SOCKET_INVALID); CHECK(send(replay, split, 7, 0) == 7); poll_some(ua); CHECK(send(replay, split + 7, pos - 7, 0) == (ssize_t)(pos - 7)); poll_some(ua); CHECK(dest.count == 1 && dest.peers[0].len == pos && !memcmp(dest.peers[0].data, split, pos)); CHECK(a.reality_owner.relay_count == 1); - socket_t other = connect_to(port + 1); CHECK(other != SOCKET_INVALID && send(other, ch, cn, 0) == (ssize_t)cn); + socket_t other = connect_to(port_b); CHECK(other != SOCKET_INVALID && send(other, ch, cn, 0) == (ssize_t)cn); poll_some(ua); CHECK(recv(other, answer, sizeof(answer), 0) >= 127 && answer[0] == 22 && dest.count == 1); cc.short_id[0] = 1; CHECK(!reality_client_hello_build_at(&cc, fake_now, ch, sizeof(ch), &cn)); - socket_t unauthorized = connect_to(port + 1); + socket_t unauthorized = connect_to(port_b); CHECK(unauthorized != SOCKET_INVALID && send(unauthorized, ch, cn, 0) == (ssize_t)cn); poll_some(ua); CHECK(dest.count == 2 && b.reality_owner.relay_count == 1); stcp_server_destroy(sb); reality_owner_cleanup(&b.reality_owner); poll_some(ua); diff --git a/tests/test_stcp_ping.c b/tests/test_stcp_ping.c index 2962f74f..62e42459 100644 --- a/tests/test_stcp_ping.c +++ b/tests/test_stcp_ping.c @@ -9,10 +9,10 @@ #include "../lib/u_async.h" #include "../lib/debug_config.h" #include "../lib/mem.h" +#include "test_net.h" #include #include #include -#include static int ping_ok = -1, ping_rtt = 0; static void ping_cb(int success, uint16_t rtt, void *arg, uint64_t nonce, @@ -28,7 +28,7 @@ static void unexpected_ready(struct stcp_conn *c, void *arg) { ping_ok = 0; } -static char *build_config(const char *node_id, const char *priv, const char *pub, int port) { +static char *build_config(const char *node_id, const char *priv, const char *pub) { static char buf[512]; snprintf(buf, sizeof(buf), "[global]\n" @@ -37,10 +37,10 @@ static char *build_config(const char *node_id, const char *priv, const char *pub "my_public_key=%s\n" "\n" "[server: stcp]\n" - "addr=127.0.0.1:%d\n" + "addr=127.0.0.1:0\n" "type=public\n" "transport=tcp\n", - node_id, priv, pub, port); + node_id, priv, pub); return buf; } @@ -50,22 +50,20 @@ int main(void) { debug_set_categories(DEBUG_CATEGORY_GENERAL | DEBUG_CATEGORY_ETCP | DEBUG_CATEGORY_CONNECTION); DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "=== TCP ping (etcp_send_tcp_ping) ==="); - srand((unsigned)time(NULL)); struct UASYNC *ua = uasync_create(); if (!ua) return 1; utun_instance_set_tun_init_enabled(0); - int port = 27000 + rand() % 1000; struct UTUN_INSTANCE *srv = utun_instance_create_from_str(ua, build_config( "AAAAAAAAAAAAAAAA", "38240cb82199e504686507f11f6eaa4f740fde6f0c425c495e49a523019a5d68", - "ce8871f07fa056c636d297115f231b08c29cdf94e0d440fce83a07c34416d36a", port)); + "ce8871f07fa056c636d297115f231b08c29cdf94e0d440fce83a07c34416d36a")); if (!srv || utun_instance_init(srv) < 0) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "srv init failed"); return 1; } struct UTUN_INSTANCE *cli = utun_instance_create_from_str(ua, build_config( "BBBBBBBBBBBBBBBB", "704f2e012c8fa8768130cb0f988a997dccb628372bc5ceccacc78dcbfec5916f", - "b3193173def895bd0fcea6f86af077c7d77216f10395275f627ac18242ec0f01", port + 1)); + "b3193173def895bd0fcea6f86af077c7d77216f10395275f627ac18242ec0f01")); if (!cli || utun_instance_init(cli) < 0) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "cli init failed"); return 1; } uint8_t srv_pub[SC_PUBKEY_SIZE]; @@ -74,9 +72,7 @@ int main(void) { srv->padding.min = srv->padding.max = ETCP_PADDING_MAX; /* success path: ping listening STCP server */ - struct sockaddr_storage addr; memset(&addr, 0, sizeof(addr)); - struct sockaddr_in *sin = (struct sockaddr_in *)&addr; - sin->sin_family = AF_INET; sin->sin_addr.s_addr = htonl(0x7f000001); sin->sin_port = htons(port); + struct sockaddr_storage addr = test_etcp_bound_socket(srv, "stcp")->local_addr; int rc = etcp_send_tcp_ping(cli, srv_pub, &addr, 2000, ping_cb, NULL, NULL, NULL); if (rc != 0) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "etcp_send_tcp_ping failed rc=%d", rc); return 1; } @@ -97,14 +93,23 @@ int main(void) { if (ping_ok != 1) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "TCP ping zero server padding failed"); return 1; } DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "=== reversed padding boundary PASSED ==="); - /* failure path: port with no listener */ + /* Отрицательный endpoint удерживаем привязанным сокетом без listen(). */ ping_ok = -1; ping_rtt = 0; struct sockaddr_storage bad_addr; memset(&bad_addr, 0, sizeof(bad_addr)); struct sockaddr_in *bsin = (struct sockaddr_in *)&bad_addr; - bsin->sin_family = AF_INET; bsin->sin_addr.s_addr = htonl(0x7f000001); bsin->sin_port = htons(port + 5000); + bsin->sin_family = AF_INET; bsin->sin_addr.s_addr = htonl(0x7f000001); + socket_t refused = socket(AF_INET, SOCK_STREAM, 0); + if (refused == SOCKET_INVALID || bind(refused, (struct sockaddr*)bsin, sizeof(*bsin)) != 0) { + DEBUG_ERROR(DEBUG_CATEGORY_SOCKET, "TCP ping: cannot reserve refused endpoint: %s", socket_strerror(socket_get_error())); + if (refused != SOCKET_INVALID) socket_close_wrapper(refused); + return 1; + } + bsin->sin_port = htons(test_bound_port(refused)); + DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "TCP ping: reserved non-listening port=%u", ntohs(bsin->sin_port)); rc = etcp_send_tcp_ping(cli, srv_pub, &bad_addr, 1000, ping_cb, NULL, NULL, NULL); ticks = 0; while (ping_ok < 0 && ticks < 3000) { uasync_poll(ua, 10); ticks++; } + socket_close_wrapper(refused); if (ping_ok != 0) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "=== FAILED (failure path): success=%d rtt=%u rc=%d ===", ping_ok, ping_rtt, rc); return 1; } DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "=== failure path PASSED: success=%d ===", ping_ok); @@ -113,11 +118,11 @@ int main(void) { reality.enabled = 1; reality.short_id_count = 1; if (reality_generate_keypair(reality.private_key, cc.server_static_pubkey)) return 1; strcpy(cc.server_name, "www.microsoft.com"); - struct stcp_server *rs = stcp_server_create(ua, port + 2, &srv->my_keys, srv->my_ed25519_pubkey, + struct stcp_server *rs = stcp_server_create(ua, 0, &srv->my_keys, srv->my_ed25519_pubkey, srv, unexpected_ready, NULL, NULL, NULL, AF_INET); if (!rs) return 1; stcp_server_set_reality(rs, &reality); - sin->sin_port = htons(port + 2); + ((struct sockaddr_in*)&addr)->sin_port = htons(stcp_server_get_port(rs)); /* Одноразовый TCP-пинг не удерживает instance: длина выбирается до асинхронного connect. */ ping_ok = -1;