[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] Make the NET_PARTICIPANT role dependent on user activity
commit 2c15b6538123047c258987b00475fa658ca14878
Author: Nick Mathewson <nickm@xxxxxxxxxxxxxx>
Date: Tue Nov 13 15:33:46 2018 -0500
Make the NET_PARTICIPANT role dependent on user activity
This patch implements all of 28337, except for the part where we
turn off the role if we've been idle for a long time.
---
src/app/main/main.c | 15 +++++++++
src/core/mainloop/connection.c | 3 ++
src/core/mainloop/mainloop.c | 34 +++++++++++++++++--
src/core/mainloop/mainloop.h | 1 +
src/core/mainloop/netstatus.c | 73 +++++++++++++++++++++++++++++++++++++++++
src/core/mainloop/netstatus.h | 7 ++++
src/core/or/or.h | 2 ++
src/feature/client/dnsserv.c | 4 +++
src/feature/control/control.c | 2 ++
src/test/test_compat_libevent.c | 1 -
src/test/test_periodic_event.c | 11 ++++++-
11 files changed, 149 insertions(+), 4 deletions(-)
diff --git a/src/app/main/main.c b/src/app/main/main.c
index b8dcb852d..03b3a95d0 100644
--- a/src/app/main/main.c
+++ b/src/app/main/main.c
@@ -303,6 +303,19 @@ process_signal(int sig)
log_heartbeat(time(NULL));
control_event_signal(sig);
break;
+ case SIGACTIVE:
+ /* "SIGACTIVE" counts as ersatz user activity. */
+ note_user_activity(approx_time());
+ control_event_signal(sig);
+ break;
+ case SIGDORMANT:
+ /* "SIGDORMANT" means to ignore past user activity */
+ log_notice(LD_GENERAL, "Going dormant because of controller request.");
+ reset_user_activity(0);
+ set_network_participation(false);
+ schedule_rescan_periodic_events();
+ control_event_signal(sig);
+ break;
}
}
@@ -472,6 +485,8 @@ static struct {
{ SIGNEWNYM, 0, NULL },
{ SIGCLEARDNSCACHE, 0, NULL },
{ SIGHEARTBEAT, 0, NULL },
+ { SIGACTIVE, 0, NULL },
+ { SIGDORMANT, 0, NULL },
{ -1, -1, NULL }
};
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 1198a01ad..e0f1680c9 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -1874,6 +1874,9 @@ connection_init_accepted_conn(connection_t *conn,
TO_ENTRY_CONN(conn)->nym_epoch = get_signewnym_epoch();
TO_ENTRY_CONN(conn)->socks_request->listener_type = listener->base_.type;
+ /* Any incoming connection on an entry port counts as user activity. */
+ note_user_activity(approx_time());
+
switch (TO_CONN(listener)->type) {
case CONN_TYPE_AP_LISTENER:
conn->state = AP_CONN_STATE_SOCKS_WAIT;
diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c
index e67ebdb4a..f18db2898 100644
--- a/src/core/mainloop/mainloop.c
+++ b/src/core/mainloop/mainloop.c
@@ -1513,8 +1513,7 @@ get_my_roles(const or_options_t *options)
options->ControlPort_set ||
options->OwningControllerFD != UINT64_MAX;
- /* We actually want a better definition here for our work on dormancy. */
- int is_net_participant = ! net_is_disabled();
+ int is_net_participant = is_participating_on_network();
if (is_bridge) roles |= PERIODIC_EVENT_ROLE_BRIDGE;
if (is_client) roles |= PERIODIC_EVENT_ROLE_CLIENT;
@@ -1592,6 +1591,30 @@ teardown_periodic_events(void)
periodic_events_initialized = 0;
}
+static mainloop_event_t *rescan_periodic_events_ev = NULL;
+
+/** Callback: rescan the periodic event list. */
+static void
+rescan_periodic_events_cb(mainloop_event_t *event, void *arg)
+{
+ (void)event;
+ (void)arg;
+ rescan_periodic_events(get_options());
+}
+
+/**
+ * Schedule an event that will rescan which periodic events should run.
+ **/
+void
+schedule_rescan_periodic_events(void)
+{
+ if (!rescan_periodic_events_ev) {
+ rescan_periodic_events_ev =
+ mainloop_event_new(rescan_periodic_events_cb, NULL);
+ }
+ mainloop_event_activate(rescan_periodic_events_ev);
+}
+
/** Do a pass at all our periodic events, disable those we don't need anymore
* and enable those we need now using the given options. */
void
@@ -2714,6 +2737,12 @@ initialize_mainloop_events(void)
int
do_main_loop(void)
{
+ /* For now, starting Tor always counts as user activity. Later, we might
+ * have an option to control this.
+ */
+ reset_user_activity(approx_time());
+ set_network_participation(true);
+
/* initialize the periodic events first, so that code that depends on the
* events being present does not assert.
*/
@@ -2912,6 +2941,7 @@ tor_mainloop_free_all(void)
mainloop_event_free(postloop_cleanup_ev);
mainloop_event_free(handle_deferred_signewnym_ev);
mainloop_event_free(scheduled_shutdown_ev);
+ mainloop_event_free(rescan_periodic_events_ev);
#ifdef HAVE_SYSTEMD_209
periodic_timer_free(systemd_watchdog_timer);
diff --git a/src/core/mainloop/mainloop.h b/src/core/mainloop/mainloop.h
index be642d81f..7f27ef9a5 100644
--- a/src/core/mainloop/mainloop.h
+++ b/src/core/mainloop/mainloop.h
@@ -65,6 +65,7 @@ void reschedule_or_state_save(void);
void reschedule_dirvote(const or_options_t *options);
void mainloop_schedule_postloop_cleanup(void);
void rescan_periodic_events(const or_options_t *options);
+void schedule_rescan_periodic_events(void);
void update_current_time(time_t now);
diff --git a/src/core/mainloop/netstatus.c b/src/core/mainloop/netstatus.c
index f02647449..ed7c952dc 100644
--- a/src/core/mainloop/netstatus.c
+++ b/src/core/mainloop/netstatus.c
@@ -6,6 +6,7 @@
#include "core/or/or.h"
#include "core/mainloop/netstatus.h"
+#include "core/mainloop/mainloop.h"
#include "app/config/config.h"
#include "feature/hibernate/hibernate.h"
@@ -26,3 +27,75 @@ net_is_completely_disabled(void)
{
return get_options()->DisableNetwork || we_are_fully_hibernating();
}
+
+/**
+ * The time at which we've last seen "user activity" -- that is, any activity
+ * that should keep us as a participant on the network.
+ */
+static time_t last_user_activity_seen = 0;
+
+/**
+ * True iff we are currently a "network participant" -- that is, we
+ * are building circuits, fetching directory information, and so on.
+ **/
+static bool participating_on_network = false;
+
+/**
+ * Record the fact that we have seen "user activity" at the time now. Move
+ * "last activity seen" time forwards, but never backwards.
+ *
+ * If we were previously not participating on the network, set our
+ * participation status to true, and launch periodic events as appropriate.
+ **/
+void
+note_user_activity(time_t now)
+{
+ last_user_activity_seen = MAX(now, last_user_activity_seen);
+
+ if (! participating_on_network) {
+ log_notice(LD_GENERAL, "Tor is no longer dormant.");
+ set_network_participation(true);
+ schedule_rescan_periodic_events();
+ }
+}
+
+/**
+ * Change the time at which "user activitiy" was last seen to <b>now</b>.
+ *
+ * Unlike note_user_actity, this function sets the time without checking
+ * whether it is in the past, and without causing any rescan of periodic events
+ * or change in participation status.
+ */
+void
+reset_user_activity(time_t now)
+{
+ last_user_activity_seen = now;
+}
+
+/**
+ * Return the most recent time at which we recorded "user activity".
+ **/
+time_t
+get_last_user_activity_time(void)
+{
+ return last_user_activity_seen;
+}
+
+/**
+ * Set the field that remembers whether we are currently participating on the
+ * network. Does not schedule or un-schedule periodic events.
+ **/
+void
+set_network_participation(bool participation)
+{
+ participating_on_network = participation;
+}
+
+/**
+ * Return true iff we are currently participating on the network.
+ **/
+bool
+is_participating_on_network(void)
+{
+ return participating_on_network;
+}
diff --git a/src/core/mainloop/netstatus.h b/src/core/mainloop/netstatus.h
index e9310c292..58c994fd1 100644
--- a/src/core/mainloop/netstatus.h
+++ b/src/core/mainloop/netstatus.h
@@ -10,4 +10,11 @@
int net_is_disabled(void);
int net_is_completely_disabled(void);
+void note_user_activity(time_t now);
+void reset_user_activity(time_t now);
+time_t get_last_user_activity_time(void);
+
+void set_network_participation(bool participation);
+bool is_participating_on_network(void);
+
#endif
diff --git a/src/core/or/or.h b/src/core/or/or.h
index acf092c8d..e4b374b12 100644
--- a/src/core/or/or.h
+++ b/src/core/or/or.h
@@ -97,6 +97,8 @@ struct curve25519_public_key_t;
#define SIGNEWNYM 129
#define SIGCLEARDNSCACHE 130
#define SIGHEARTBEAT 131
+#define SIGACTIVE 132
+#define SIGDORMANT 133
#if (SIZEOF_CELL_T != 0)
/* On Irix, stdlib.h defines a cell_t type, so we need to make sure
diff --git a/src/feature/client/dnsserv.c b/src/feature/client/dnsserv.c
index ea4951f91..e5abe5c6a 100644
--- a/src/feature/client/dnsserv.c
+++ b/src/feature/client/dnsserv.c
@@ -28,6 +28,7 @@
#include "core/or/connection_edge.h"
#include "feature/control/control.h"
#include "core/mainloop/mainloop.h"
+#include "core/mainloop/netstatus.h"
#include "core/or/policies.h"
#include "feature/control/control_connection_st.h"
@@ -213,6 +214,9 @@ dnsserv_launch_request(const char *name, int reverse,
edge_connection_t *conn;
char *q_name;
+ /* Launching a request for a user counts as user activity. */
+ note_user_activity(approx_time());
+
/* Make a new dummy AP connection, and attach the request to it. */
entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
entry_conn->entry_cfg.dns_request = 1;
diff --git a/src/feature/control/control.c b/src/feature/control/control.c
index a5b6ab3bf..1344d66a3 100644
--- a/src/feature/control/control.c
+++ b/src/feature/control/control.c
@@ -1681,6 +1681,8 @@ static const struct signal_t signal_table[] = {
{ SIGNEWNYM, "NEWNYM" },
{ SIGCLEARDNSCACHE, "CLEARDNSCACHE"},
{ SIGHEARTBEAT, "HEARTBEAT"},
+ { SIGACTIVE, "ACTIVE" },
+ { SIGDORMANT, "DORMANT" },
{ 0, NULL },
};
diff --git a/src/test/test_compat_libevent.c b/src/test/test_compat_libevent.c
index 3f505d013..ade76bdb0 100644
--- a/src/test/test_compat_libevent.c
+++ b/src/test/test_compat_libevent.c
@@ -187,4 +187,3 @@ struct testcase_t compat_libevent_tests[] = {
TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
-
diff --git a/src/test/test_periodic_event.c b/src/test/test_periodic_event.c
index 6a3e320b2..f3d518eb7 100644
--- a/src/test/test_periodic_event.c
+++ b/src/test/test_periodic_event.c
@@ -51,6 +51,8 @@ test_pe_initialize(void *arg)
* need to run the main loop and then wait for a second delaying the unit
* tests. Instead, we'll test the callback work indepedently elsewhere. */
initialize_periodic_events();
+ set_network_participation(false);
+ rescan_periodic_events(get_options());
/* Validate that all events have been set up. */
for (int i = 0; periodic_events[i].name; ++i) {
@@ -82,6 +84,8 @@ test_pe_launch(void *arg)
* network gets enabled. */
consider_hibernation(time(NULL));
+ set_network_participation(true);
+
/* Hack: We'll set a dumb fn() of each events so they don't get called when
* dispatching them. We just want to test the state of the callbacks, not
* the whole code path. */
@@ -93,6 +97,7 @@ test_pe_launch(void *arg)
options = get_options_mutable();
options->SocksPort_set = 1;
periodic_events_on_new_options(options);
+
#if 0
/* Lets make sure that before intialization, we can't scan the periodic
* events list and launch them. Lets try by being a Client. */
@@ -148,6 +153,7 @@ test_pe_launch(void *arg)
options->SocksPort_set = 0;
options->ORPort_set = 0;
options->DisableNetwork = 1;
+ set_network_participation(false);
periodic_events_on_new_options(options);
for (int i = 0; periodic_events[i].name; ++i) {
@@ -162,6 +168,7 @@ test_pe_launch(void *arg)
options->BridgeRelay = 1; options->AuthoritativeDir = 1;
options->V3AuthoritativeDir = 1; options->BridgeAuthoritativeDir = 1;
options->DisableNetwork = 0;
+ set_network_participation(true);
register_dummy_hidden_service(&service);
periodic_events_on_new_options(options);
/* Note down the reference because we need to remove this service from the
@@ -195,8 +202,10 @@ test_pe_get_roles(void *arg)
or_options_t *options = get_options_mutable();
tt_assert(options);
+ set_network_participation(true);
- const int ALL = PERIODIC_EVENT_ROLE_ALL;
+ const int ALL = PERIODIC_EVENT_ROLE_ALL |
+ PERIODIC_EVENT_ROLE_NET_PARTICIPANT;
/* Nothing configured, should be no roles. */
tt_assert(net_is_disabled());
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits