commit ce6209cee4a113c6a224f0c98244852354ccdb40
Author: Nick Mathewson <ni...@torproject.org>
Date:   Tue Nov 13 15:51:53 2018 -0500

    Add a periodic event to become dormant.
    
    This event makes us become dormant if we have seen no activity in a
    long time.
    
    Note that being any kind of a server, or running an onion service,
    always counts as being active.
    
    Note that right now, just having an open stream that Tor
    did not open on its own (for a directory request) counts as "being
    active", so if you have an idle ssh connection, that will keep Tor
    from becoming dormant.
    
    Many of the features here should become configurable; I'd like
    feedback on which.
---
 src/core/mainloop/connection.c | 10 +++++++++
 src/core/mainloop/connection.h |  1 +
 src/core/mainloop/mainloop.c   | 50 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index e0f1680c9..25224fd99 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -4429,6 +4429,16 @@ connection_get_by_type_state(int type, int state)
   CONN_GET_TEMPLATE(conn, conn->type == type && conn->state == state);
 }
 
+/**
+ * Return a connection of type <b>type</b> that is not an internally linked
+ * connection, and is not marked for close.
+ **/
+connection_t *
+connection_get_by_type_nonlinked(int type)
+{
+  CONN_GET_TEMPLATE(conn, conn->type == type && !conn->linked);
+}
+
 /** Return a connection of type <b>type</b> that has rendquery equal
  * to <b>rendquery</b>, and that is not marked for close. If state
  * is non-zero, conn must be of that state too.
diff --git a/src/core/mainloop/connection.h b/src/core/mainloop/connection.h
index b569bb038..9f1a23c6f 100644
--- a/src/core/mainloop/connection.h
+++ b/src/core/mainloop/connection.h
@@ -240,6 +240,7 @@ size_t connection_get_outbuf_len(connection_t *conn);
 connection_t *connection_get_by_global_id(uint64_t id);
 
 connection_t *connection_get_by_type(int type);
+connection_t *connection_get_by_type_nonlinked(int type);
 MOCK_DECL(connection_t *,connection_get_by_type_addr_port_purpose,(int type,
                                                   const tor_addr_t *addr,
                                                   uint16_t port, int purpose));
diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c
index f18db2898..e6dee94fc 100644
--- a/src/core/mainloop/mainloop.c
+++ b/src/core/mainloop/mainloop.c
@@ -1367,6 +1367,7 @@ CALLBACK(write_bridge_ns);
 CALLBACK(write_stats_file);
 CALLBACK(control_per_second_events);
 CALLBACK(second_elapsed);
+CALLBACK(check_network_participation);
 
 #undef CALLBACK
 
@@ -1396,6 +1397,7 @@ STATIC periodic_event_item_t periodic_events[] = {
   CALLBACK(fetch_networkstatus, NET_PARTICIPANT, 0),
   CALLBACK(launch_descriptor_fetches, NET_PARTICIPANT, FL(NEED_NET)),
   CALLBACK(rotate_x509_certificate, NET_PARTICIPANT, 0),
+  CALLBACK(check_network_participation, NET_PARTICIPANT, 0),
 
   /* We need to do these if we're participating in the Tor network, and
    * immediately before we stop. */
@@ -1998,6 +2000,54 @@ add_entropy_callback(time_t now, const or_options_t 
*options)
   return ENTROPY_INTERVAL;
 }
 
+/** Periodic callback: if there has been no network usage in a while,
+ * enter a dormant state. */
+static int
+check_network_participation_callback(time_t now, const or_options_t *options)
+{
+  /* If we're a server, we can't become dormant. */
+  if (server_mode(options)) {
+    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. */
+  if (hs_service_get_num_services() || rend_num_services()) {
+    goto found_activity;
+  }
+
+  /* XXXX Add an option to never become dormant. */
+
+  /* If we have any currently open entry streams other than "linked"
+   * connections used for directory requests, those count as user activity.
+   */
+  /* XXXX make this configurable? */
+  if (connection_get_by_type_nonlinked(CONN_TYPE_AP) != NULL) {
+    goto found_activity;
+  }
+
+  /* XXXX Make this configurable? */
+/** How often do we check whether we have had network activity? */
+#define CHECK_PARTICIPATION_INTERVAL (5*60)
+
+  /** Become dormant if there has been no user activity in this long. */
+  /* XXXX make this configurable! */
+#define BECOME_DORMANT_AFTER_INACTIVITY (24*60*60)
+  if (get_last_user_activity_time() + BECOME_DORMANT_AFTER_INACTIVITY >= now) {
+    log_notice(LD_GENERAL, "No user activity in a long time: becoming"
+               " dormant.");
+    set_network_participation(false);
+    rescan_periodic_events(options);
+  }
+
+  return CHECK_PARTICIPATION_INTERVAL;
+
+ found_activity:
+  note_user_activity(now);
+  return CHECK_PARTICIPATION_INTERVAL;
+}
+
 /**
  * Periodic callback: if we're an authority, make sure we test
  * the routers on the network for reachability.



_______________________________________________
tor-commits mailing list
tor-commits@lists.torproject.org
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to