From 7ec5f931bb025ade9871f3dcd489df04b068285d Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 2 Oct 2026 11:56:44 +0300 Subject: [PATCH] Defer automatic retries until Android standby wakes --- src/routing_layer/topo_group_connect.c | 5 ++- tests/Makefile.am | 5 ++- tests/test_group_connect.c | 44 +++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/routing_layer/topo_group_connect.c b/src/routing_layer/topo_group_connect.c index 6c0f65b9..1f57a480 100644 --- a/src/routing_layer/topo_group_connect.c +++ b/src/routing_layer/topo_group_connect.c @@ -179,7 +179,7 @@ static void tgc_resume(void* arg) { static int tgc_pause(struct TOPO_GROUP_CONNECT* gc) { #ifdef UTUN_HAVE_STANDBY - if (standby_is_enabled()) { + if (standby_get_sleep_tb() > 0) { gc->pause_wait = standby_wait(gc, tgc_resume); if (gc->pause_wait) { gc->paused = 1; return 1; } DEBUG_WARN(DEBUG_CATEGORY_BGP, "cannot wait for standby; using group retry timer"); @@ -265,6 +265,9 @@ static void tgc_step(void* arg) { topo_group_peer_close(request); pending[c->kind]--; c->retry_at = now; changed = 1; } } +#ifdef UTUN_HAVE_STANDBY + if (!gc->paused && standby_get_sleep_tb() > 0) tgc_pause(gc); +#endif for (int kind = TGC_SUPER; !gc->paused && kind < TGC_CLASSES; kind++) { if (!allowed[kind]) continue; int limit = gc->self_super && kind == TGC_SUPER ? TGC_PARALLEL : TGC_TARGET - up[kind]; diff --git a/tests/Makefile.am b/tests/Makefile.am index 99a1c077..22cad98f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -119,7 +119,7 @@ check_PROGRAMS = \ # Linux-only: test_auto_socket_dynamic требует root + dummy-интерфейсы + iproute2/netlink. if OS_LINUX -check_PROGRAMS += test_auto_socket_dynamic test_standby test_standby_transport test_android_udp_log test_pool_corruption_log +check_PROGRAMS += test_auto_socket_dynamic test_standby test_standby_transport test_group_connect_standby test_android_udp_log test_pool_corruption_log check_PROGRAMS += test_uasync_regressions test_ll_queue_regressions endif @@ -163,6 +163,9 @@ test_standby_transport_SOURCES = test_standby_transport.c $(standby_test_sources test_standby_transport_CPPFLAGS = $(standby_test_cppflags) test_standby_transport_LDADD = $(LIBUTUN) $(COMMON_LIBS) test_standby_transport_LDFLAGS = -Wl,--wrap=etcp_encrypt_send -Wl,--wrap=uasync_set_timeout +test_group_connect_standby_SOURCES = test_group_connect.c ../src/routing_layer/topo_group_connect.c $(standby_test_sources) +test_group_connect_standby_CPPFLAGS = $(standby_test_cppflags) +test_group_connect_standby_LDADD = $(LIBUTUN) $(COMMON_LIBS) test_android_udp_log_SOURCES = test_android_udp_log.c ../tools/chatgui-android/jni_bridge/android_udp_log.c test_android_udp_log_LDADD = $(COMMON_LIBS) test_android_udp_log_LDFLAGS = -Wl,--wrap=uasync_set_timeout -Wl,--wrap=uasync_cancel_timeout diff --git a/tests/test_group_connect.c b/tests/test_group_connect.c index 70e601a2..d2c0ed57 100644 --- a/tests/test_group_connect.c +++ b/tests/test_group_connect.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "utun_instance.h" #include "routing_layer/topo_group.h" #include "routing_layer/topo_group_connect.h" @@ -11,6 +12,9 @@ #include "../lib/mem.h" #include "../lib/memory_pool.h" #include "../lib/debug_config.h" +#ifdef UTUN_HAVE_STANDBY +#include "standby.h" +#endif #define PEERS 8 @@ -37,6 +41,9 @@ static void poll_events(struct fixture* f) { for (int i = 0; i < 8; i++) uasync_ static void create(struct fixture* f, int device, int supernode) { memset(f, 0, sizeof(*f)); f->ua = uasync_create(); assert(f->ua); +#ifdef UTUN_HAVE_STANDBY + standby_init(f->ua); +#endif char config[512]; snprintf(config, sizeof(config), "[global]\nclient_type=%d\n" "my_private_key=704f2e012c8fa8768130cb0f988a997dccb628372bc5ceccacc78dcbfec5916f\n" @@ -65,7 +72,9 @@ static void create(struct fixture* f, int device, int supernode) { .protocol = TOPO_PROTO_UDP, .type = TOPO_ADDR_INTERFACE }; uint8_t message[TOPO_SIG_MSG_MAX_SIZE]; int size = topo_node_build_sig_msg(node, message, sizeof(message)); assert(size > 0); - assert(sc_ed25519_sign(keys.private_key, message, (size_t)size, node->x25519_self_sig) == SC_OK); + uint8_t ed_private[SHA512_DIGEST_LENGTH]; + SHA512(keys.private_key, SC_PRIVKEY_SIZE, ed_private); + assert(sc_ed25519_sign(ed_private, message, (size_t)size, node->x25519_self_sig) == SC_OK); assert(topo_node_verify(node) == 0); assert(topo_node_registry_store(f->inst->topo_groups, node)); assert(topo_node_sqlite_node_update_verified(db, node->node_id, "peer", node->public_key, @@ -91,6 +100,9 @@ static void create(struct fixture* f, int device, int supernode) { } static void destroy(struct fixture* f) { +#ifdef UTUN_HAVE_STANDBY + standby_deinit(); +#endif topo_groups_remove_group(f->inst->topo_groups, 42); for (int i = 0; i < PEERS; i++) { node_conn_direct_close(f->owners[i]); @@ -212,6 +224,33 @@ static void persisted_classification(void) { destroy(&f); } +#ifdef UTUN_HAVE_STANDBY +/* DOWN в SLEEP меняет состояние сразу, а новые попытки ждут активной фазы. */ +static void standby_down(void) { + struct fixture f; create(&f, CLIENT_TYPE_MOBILE, 0); start(&f); + up(&f, 0); up(&f, 1); + standby_set_intervals_ms(100, 200, 0); + assert(standby_set_enabled(f.inst, 1) == 0); + while (!standby_get_sleep_tb()) uasync_poll(f.ua, 100); + down(&f, 0); + assert(topo_group_connect_active_count(f.group) == 1 && !peer(&f, 0) && !peer(&f, 2)); + assert(standby_set_enabled(f.inst, 0) == 0); poll_events(&f); + assert(peer(&f, 2)); + destroy(&f); + + create(&f, CLIENT_TYPE_MOBILE, 0); + standby_set_intervals_ms(100, 200, 0); + assert(standby_set_enabled(f.inst, 1) == 0); + while (!standby_get_sleep_tb()) uasync_poll(f.ua, 100); + assert(topo_group_connect_init(f.group) == 0); poll_events(&f); + assert(!peer(&f, 0) && !peer(&f, 1)); + while (standby_get_sleep_tb()) uasync_poll(f.ua, 100); + poll_events(&f); assert(peer(&f, 0) && peer(&f, 1)); + assert(standby_set_enabled(f.inst, 0) == 0); + destroy(&f); +} +#endif + int main(void) { debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_BGP, DEBUG_LEVEL_INFO); @@ -221,6 +260,9 @@ int main(void) { fallback(CLIENT_TYPE_DESKTOP); fallback(CLIENT_TYPE_MOBILE); all_supernodes(); +#ifdef UTUN_HAVE_STANDBY + standby_down(); +#endif DEBUG_INFO(DEBUG_CATEGORY_BGP, "group connect tests passed: UP, two/all supernodes, desktop/mobile fallback, retries, ownership"); return 0; }