From 7144bbe6944e5870d7ede9126d6e73b19a803191 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sun, 11 Oct 2026 14:42:37 +0200 Subject: [PATCH] Verify deferred standby restoration and END-only automatic streams --- src/utun_instance.c | 2 ++ tests/test_stream_service.c | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/utun_instance.c b/src/utun_instance.c index adda712f..24a7f174 100644 --- a/src/utun_instance.c +++ b/src/utun_instance.c @@ -1160,7 +1160,9 @@ int utun_set_client_activity(struct UTUN_INSTANCE* instance, int active) { int held = stream_service_needs_activity(instance); int state = held ? CLIENT_ACTIVITY_ACTIVE : requested; int previous = instance->client_activity; +#ifdef UTUN_HAVE_STANDBY int previous_requested = instance->client_activity_requested; +#endif instance->client_activity_requested = requested; instance->client_activity = state; #ifdef UTUN_HAVE_STANDBY diff --git a/tests/test_stream_service.c b/tests/test_stream_service.c index 37b273ed..ccb17b68 100644 --- a/tests/test_stream_service.c +++ b/tests/test_stream_service.c @@ -647,6 +647,9 @@ static void test_automatic(void) { } while (!relay_announced && get_time_tb() < deadline); CHECK(relay_announced); CHECK(stream_subscribe_open(nodes[2], GROUP2, nodes[3]->node_id, &subscribers[2]) == STREAM_OK); + CHECK(stream_service_needs_activity(nodes[2]) && nodes[2]->client_activity == CLIENT_ACTIVITY_ACTIVE); + CHECK(utun_set_client_activity(nodes[2], 0) == 0 && nodes[2]->client_activity == CLIENT_ACTIVITY_ACTIVE); + CHECK(nodes[2]->client_activity_requested == CLIENT_ACTIVITY_STANDBY); struct stream_selection_settings settings = {200, 1000, 100}; for (unsigned i = 1; i < 3; i++) { CHECK(stream_selection_configure(subscribers[i], &settings) == STREAM_OK); @@ -697,6 +700,14 @@ static void test_automatic(void) { CHECK(automatic_data[2] == 400 && !automatic_gaps[2] && source_connection->links_up); CHECK(stream_publish_finish(publisher) == STREAM_OK); run_until(&automatic_end[1], 1); run_until(&automatic_end[2], 1); for (unsigned i = 1; i < 3; i++) stream_close(subscribers[i]); stream_close(publisher); + publisher = subscribers[1] = subscribers[2] = NULL; + CHECK(stream_publish_open(nodes[3], GROUP2, ¶meters, &publisher) == STREAM_OK); + CHECK(stream_get_info(publisher, &origin) == STREAM_OK); + wait_state(2, 3, GROUP2, origin.descriptor.source_epoch, 0); + CHECK(stream_subscribe_open(nodes[2], GROUP2, nodes[3]->node_id, &subscribers[2]) == STREAM_OK); + test_clock_run_for(ua, 5000); + CHECK(stream_publish_finish(publisher) == STREAM_OK); run_until(&automatic_end[2], 2); + CHECK(automatic_data[2] == 400); stream_close(subscribers[2]); stream_close(publisher); test_clock_run_for(ua, 1000); for (unsigned i = 1; i < 4; i++) CHECK(etcp_bind(nodes[i], ETCP_ID_STREAM, automatic_handlers[i]) == 0); stream_set_event_callback(nodes[1], on_stream, NULL); stream_set_event_callback(nodes[2], NULL, NULL); @@ -891,6 +902,7 @@ int main(void) { while ((stream_handle_active(mobile) || stream_handle_active(desktop)) && get_time_tb() < deadline) test_clock_poll(ua, 100); CHECK(!stream_handle_active(mobile) && !stream_handle_active(desktop)); CHECK(stream_handle_reason(mobile) == STREAM_CLOSE_SOURCE_CHANGED && stream_handle_reason(desktop) == STREAM_CLOSE_SOURCE_CHANGED); + CHECK(!stream_service_needs_activity(nodes[2]) && nodes[2]->client_activity == CLIENT_ACTIVITY_STANDBY); stream_close(mobile); stream_close(desktop); /* Повреждённое собственное членство удаляет обычная проверка Merkle; буфер не должен остаться активным. */ sqlite3_stmt *broken = NULL; uint8_t bad_signature[64]; memset(bad_signature, 1, sizeof(bad_signature));