aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-11-13 15:33:46 -0500
committerNick Mathewson <nickm@torproject.org>2018-11-15 11:17:22 -0500
commit2c15b6538123047c258987b00475fa658ca14878 (patch)
tree6a01a36619cd1df7228b9a50e20a15087d3e014e /src/core
parentccbb36048f5167b9d5011b7c8b0d2c346ce567e8 (diff)
downloadtor-2c15b6538123047c258987b00475fa658ca14878.tar.gz
tor-2c15b6538123047c258987b00475fa658ca14878.zip
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.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/mainloop/connection.c3
-rw-r--r--src/core/mainloop/mainloop.c34
-rw-r--r--src/core/mainloop/mainloop.h1
-rw-r--r--src/core/mainloop/netstatus.c73
-rw-r--r--src/core/mainloop/netstatus.h7
-rw-r--r--src/core/or/or.h2
6 files changed, 118 insertions, 2 deletions
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 1198a01ad9..e0f1680c91 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 e67ebdb4a8..f18db2898a 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 be642d81f9..7f27ef9a52 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 f026474494..ed7c952dcd 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 e9310c2929..58c994fd14 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 acf092c8dc..e4b374b122 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