Browse Source

Remember in our state file how long we've spent since user activity

Rather than initializing the "Dormant" status to "off" and the "last
activity" count to "now", initialize them based on our state file:
stay dormant if we were dormant, or remember the amount of time
we've spent inactive.
Nick Mathewson 5 years ago
parent
commit
b25b8150c2

+ 7 - 0
src/app/config/or_state_st.h

@@ -87,6 +87,13 @@ struct or_state_t {
 
   /** When did we last rotate our onion key?  "0" for 'no idea'. */
   time_t LastRotatedOnionKey;
+
+  /** Number of minutes since the last user-initiated request (as defined by
+   * the dormant net-status system.) Set to zero if we are dormant. */
+  int MinutesSinceUserActivity;
+  /** True if we were dormant when we last wrote the file; false if we
+   * weren't.  "auto" on initial startup. */
+  int Dormant;
 };
 
 #endif

+ 8 - 0
src/app/config/statefile.c

@@ -34,6 +34,7 @@
 #include "app/config/config.h"
 #include "app/config/confparse.h"
 #include "core/mainloop/mainloop.h"
+#include "core/mainloop/netstatus.h"
 #include "core/mainloop/connection.h"
 #include "feature/control/control.h"
 #include "feature/client/entrynodes.h"
@@ -132,6 +133,9 @@ static config_var_t state_vars_[] = {
   VAR("CircuitBuildTimeBin",          LINELIST_S, BuildtimeHistogram, NULL),
   VAR("BuildtimeHistogram",           LINELIST_V, BuildtimeHistogram, NULL),
 
+  V(MinutesSinceUserActivity,         UINT,     NULL),
+  V(Dormant,                          AUTOBOOL, "auto"),
+
   END_OF_CONFIG_VARS
 };
 
@@ -309,6 +313,8 @@ or_state_set(or_state_t *new_state)
       get_circuit_build_times_mutable(),global_state) < 0) {
     ret = -1;
   }
+  netstatus_load_from_state(global_state, time(NULL));
+
   return ret;
 }
 
@@ -500,6 +506,8 @@ or_state_save(time_t now)
   entry_guards_update_state(global_state);
   rep_hist_update_state(global_state);
   circuit_build_times_update_state(get_circuit_build_times(), global_state);
+  netstatus_flush_to_state(global_state, now);
+
   if (accounting_is_enabled(get_options()))
     accounting_run_housekeeping(now);
 

+ 1 - 6
src/core/mainloop/mainloop.c

@@ -1627,6 +1627,7 @@ schedule_rescan_periodic_events,(void))
 void
 rescan_periodic_events(const or_options_t *options)
 {
+  puts("RESCAN");
   tor_assert(options);
 
   /* Avoid scanning the event list if we haven't initialized it yet. This is
@@ -2818,12 +2819,6 @@ 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.
    */

+ 41 - 0
src/core/mainloop/netstatus.c

@@ -10,6 +10,8 @@
 #include "app/config/config.h"
 #include "feature/hibernate/hibernate.h"
 
+#include "app/config/or_state_st.h"
+
 /** Return true iff our network is in some sense disabled or shutting down:
  * either we're hibernating, entering hibernation, or the network is turned
  * off with DisableNetwork. */
@@ -31,6 +33,10 @@ net_is_completely_disabled(void)
 /**
  * The time at which we've last seen "user activity" -- that is, any activity
  * that should keep us as a participant on the network.
+ *
+ * This is not actually the true time.  We will adjust this forward if
+ * our clock jumps, or if Tor is shut down for a while, so that the time
+ * since our last activity remains as it was before the jump or shutdown.
  */
 static time_t last_user_activity_seen = 0;
 
@@ -99,3 +105,38 @@ is_participating_on_network(void)
 {
   return participating_on_network;
 }
+
+/**
+ * Update 'state' with the last time at which we were active on the network.
+ **/
+void
+netstatus_flush_to_state(or_state_t *state, time_t now)
+{
+  state->Dormant = ! participating_on_network;
+  if (participating_on_network) {
+    time_t sec_since_activity = MAX(0, now - last_user_activity_seen);
+    state->MinutesSinceUserActivity = (int)(sec_since_activity / 60);
+  } else {
+    state->MinutesSinceUserActivity = 0;
+  }
+}
+
+/**
+ * Update our current view of network participation from an or_state_t object.
+ **/
+void
+netstatus_load_from_state(const or_state_t *state, time_t now)
+{
+  time_t last_activity;
+  if (state->Dormant == -1) { // Initial setup.
+    last_activity = now;
+    participating_on_network = true;
+  } else if (state->Dormant) {
+    last_activity = 0;
+    participating_on_network = false;
+  } else {
+    last_activity = now - 60 * state->MinutesSinceUserActivity;
+    participating_on_network = true;
+  }
+  reset_user_activity(last_activity);
+}

+ 3 - 0
src/core/mainloop/netstatus.h

@@ -17,4 +17,7 @@ time_t get_last_user_activity_time(void);
 void set_network_participation(bool participation);
 bool is_participating_on_network(void);
 
+void netstatus_flush_to_state(or_state_t *state, time_t now);
+void netstatus_load_from_state(const or_state_t *state, time_t now);
+
 #endif