diff --git a/changes/ticket40228 b/changes/ticket40228 new file mode 100644 index 0000000000..297204decd --- /dev/null +++ b/changes/ticket40228 @@ -0,0 +1,4 @@ + o Minor features (dormant mode): + - Add a new 'DormantTimeoutEnabled' option to allow coarse-grained + control over whether the client ever becomes dormant from inactivity. + Most people won't need this. Closes ticket 40228. diff --git a/doc/man/tor.1.txt b/doc/man/tor.1.txt index f5dd1ec6f7..a8436f7446 100644 --- a/doc/man/tor.1.txt +++ b/doc/man/tor.1.txt @@ -1879,6 +1879,12 @@ The following options control when Tor enters and leaves dormant mode: counts as client activity for the purpose of DormantClientTimeout. If false, then only network activity counts. (Default: 1) +[[DormantTimeoutEnabled]] **DormantTimeoutEnabled** **0**|**1**:: + If false, then no amount of time without activity is sufficient to + make Tor go dormant. Setting this option to zero is only recommended for + special-purpose applications that need to use the Tor binary for + something other than sending or receiving Tor traffic. (Default: 1) + == NODE SELECTION OPTIONS // These options are in alphabetical order, with exceptions as noted. diff --git a/src/app/config/config.c b/src/app/config/config.c index f9f09dcd63..e0eb0dac13 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -422,8 +422,9 @@ static const config_var_t option_vars_[] = { OBSOLETE("DynamicDHGroups"), VPORT(DNSPort), OBSOLETE("DNSListenAddress"), - V(DormantClientTimeout, INTERVAL, "24 hours"), - V(DormantTimeoutDisabledByIdleStreams, BOOL, "1"), + V(DormantClientTimeout, INTERVAL, "24 hours"), + V(DormantTimeoutEnabled, BOOL, "1"), + V(DormantTimeoutDisabledByIdleStreams, BOOL, "1"), V(DormantOnFirstStartup, BOOL, "0"), V(DormantCanceledByStartup, BOOL, "0"), V(DownloadExtraInfo, BOOL, "0"), diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h index 0a0b6483ff..641d276ff3 100644 --- a/src/app/config/or_options_st.h +++ b/src/app/config/or_options_st.h @@ -1033,6 +1033,13 @@ struct or_options_t { **/ int DormantClientTimeout; + /** + * Boolean: If enabled, then we consider the timeout when deciding whether + * to be dormant. If not enabled, then only the SIGNAL ACTIVE/DORMANT + * controls can change our status. + **/ + int DormantTimeoutEnabled; + /** Boolean: true if having an idle stream is sufficient to prevent a client * from becoming dormant. **/ diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c index ddd612bd74..69606c0d53 100644 --- a/src/core/mainloop/mainloop.c +++ b/src/core/mainloop/mainloop.c @@ -1820,6 +1820,12 @@ check_network_participation_callback(time_t now, const or_options_t *options) goto found_activity; } + /* If we aren't allowed to become dormant, then participation doesn't + matter */ + if (! options->DormantTimeoutEnabled) { + goto found_activity; + } + /* If we're running an onion service, we can't become dormant. */ /* XXXX this would be nice to change, so that we can be dormant with a * service. */ diff --git a/src/core/mainloop/netstatus.c b/src/core/mainloop/netstatus.c index e8755e07a8..b833149151 100644 --- a/src/core/mainloop/netstatus.c +++ b/src/core/mainloop/netstatus.c @@ -154,6 +154,9 @@ netstatus_load_from_state(const mainloop_state_t *state, time_t now) last_activity = now; participating_on_network = true; } + if (! get_options()->DormantTimeoutEnabled) { + participating_on_network = true; + } reset_user_activity(last_activity); } diff --git a/src/test/test_mainloop.c b/src/test/test_mainloop.c index 5af01ed512..ccd3378be5 100644 --- a/src/test/test_mainloop.c +++ b/src/test/test_mainloop.c @@ -231,6 +231,8 @@ test_mainloop_check_participation(void *arg) const time_t start = 1542658829; const time_t ONE_DAY = 24*60*60; + options->DormantTimeoutEnabled = 1; + // Suppose we've been idle for a day or two reset_user_activity(start - 2*ONE_DAY); set_network_participation(true);