Browse Source

Defer automatic retries until Android standby wakes

master
evgeny 1 day ago
parent
commit
7ec5f931bb
  1. 5
      src/routing_layer/topo_group_connect.c
  2. 5
      tests/Makefile.am
  3. 44
      tests/test_group_connect.c

5
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) { static int tgc_pause(struct TOPO_GROUP_CONNECT* gc) {
#ifdef UTUN_HAVE_STANDBY #ifdef UTUN_HAVE_STANDBY
if (standby_is_enabled()) { if (standby_get_sleep_tb() > 0) {
gc->pause_wait = standby_wait(gc, tgc_resume); gc->pause_wait = standby_wait(gc, tgc_resume);
if (gc->pause_wait) { gc->paused = 1; return 1; } if (gc->pause_wait) { gc->paused = 1; return 1; }
DEBUG_WARN(DEBUG_CATEGORY_BGP, "cannot wait for standby; using group retry timer"); 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; 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++) { for (int kind = TGC_SUPER; !gc->paused && kind < TGC_CLASSES; kind++) {
if (!allowed[kind]) continue; if (!allowed[kind]) continue;
int limit = gc->self_super && kind == TGC_SUPER ? TGC_PARALLEL : TGC_TARGET - up[kind]; int limit = gc->self_super && kind == TGC_SUPER ? TGC_PARALLEL : TGC_TARGET - up[kind];

5
tests/Makefile.am

@ -119,7 +119,7 @@ check_PROGRAMS = \
# Linux-only: test_auto_socket_dynamic требует root + dummy-интерфейсы + iproute2/netlink. # Linux-only: test_auto_socket_dynamic требует root + dummy-интерфейсы + iproute2/netlink.
if OS_LINUX 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 check_PROGRAMS += test_uasync_regressions test_ll_queue_regressions
endif 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_CPPFLAGS = $(standby_test_cppflags)
test_standby_transport_LDADD = $(LIBUTUN) $(COMMON_LIBS) test_standby_transport_LDADD = $(LIBUTUN) $(COMMON_LIBS)
test_standby_transport_LDFLAGS = -Wl,--wrap=etcp_encrypt_send -Wl,--wrap=uasync_set_timeout 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_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_LDADD = $(COMMON_LIBS)
test_android_udp_log_LDFLAGS = -Wl,--wrap=uasync_set_timeout -Wl,--wrap=uasync_cancel_timeout test_android_udp_log_LDFLAGS = -Wl,--wrap=uasync_set_timeout -Wl,--wrap=uasync_cancel_timeout

44
tests/test_group_connect.c

@ -1,6 +1,7 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <openssl/sha.h>
#include "utun_instance.h" #include "utun_instance.h"
#include "routing_layer/topo_group.h" #include "routing_layer/topo_group.h"
#include "routing_layer/topo_group_connect.h" #include "routing_layer/topo_group_connect.h"
@ -11,6 +12,9 @@
#include "../lib/mem.h" #include "../lib/mem.h"
#include "../lib/memory_pool.h" #include "../lib/memory_pool.h"
#include "../lib/debug_config.h" #include "../lib/debug_config.h"
#ifdef UTUN_HAVE_STANDBY
#include "standby.h"
#endif
#define PEERS 8 #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) { static void create(struct fixture* f, int device, int supernode) {
memset(f, 0, sizeof(*f)); memset(f, 0, sizeof(*f));
f->ua = uasync_create(); assert(f->ua); f->ua = uasync_create(); assert(f->ua);
#ifdef UTUN_HAVE_STANDBY
standby_init(f->ua);
#endif
char config[512]; char config[512];
snprintf(config, sizeof(config), "[global]\nclient_type=%d\n" snprintf(config, sizeof(config), "[global]\nclient_type=%d\n"
"my_private_key=704f2e012c8fa8768130cb0f988a997dccb628372bc5ceccacc78dcbfec5916f\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 }; .protocol = TOPO_PROTO_UDP, .type = TOPO_ADDR_INTERFACE };
uint8_t message[TOPO_SIG_MSG_MAX_SIZE]; uint8_t message[TOPO_SIG_MSG_MAX_SIZE];
int size = topo_node_build_sig_msg(node, message, sizeof(message)); assert(size > 0); 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_verify(node) == 0);
assert(topo_node_registry_store(f->inst->topo_groups, node)); 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, 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) { static void destroy(struct fixture* f) {
#ifdef UTUN_HAVE_STANDBY
standby_deinit();
#endif
topo_groups_remove_group(f->inst->topo_groups, 42); topo_groups_remove_group(f->inst->topo_groups, 42);
for (int i = 0; i < PEERS; i++) { for (int i = 0; i < PEERS; i++) {
node_conn_direct_close(f->owners[i]); node_conn_direct_close(f->owners[i]);
@ -212,6 +224,33 @@ static void persisted_classification(void) {
destroy(&f); 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) { int main(void) {
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
debug_set_category_level(DEBUG_CATEGORY_BGP, DEBUG_LEVEL_INFO); debug_set_category_level(DEBUG_CATEGORY_BGP, DEBUG_LEVEL_INFO);
@ -221,6 +260,9 @@ int main(void) {
fallback(CLIENT_TYPE_DESKTOP); fallback(CLIENT_TYPE_DESKTOP);
fallback(CLIENT_TYPE_MOBILE); fallback(CLIENT_TYPE_MOBILE);
all_supernodes(); 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"); DEBUG_INFO(DEBUG_CATEGORY_BGP, "group connect tests passed: UP, two/all supernodes, desktop/mobile fallback, retries, ownership");
return 0; return 0;
} }

Loading…
Cancel
Save