Browse Source

Expire circuits that have been WAITING_FOR_BETTER_GUARD too long

(This is required by 3.9 in prop271, but is better done as a
separate function IMO)
Nick Mathewson 7 years ago
parent
commit
2ea5aa7182
7 changed files with 49 additions and 4 deletions
  1. 11 1
      src/or/circuitlist.c
  2. 1 0
      src/or/circuitlist.h
  3. 19 0
      src/or/circuituse.c
  4. 1 0
      src/or/circuituse.h
  5. 15 3
      src/or/entrynodes.c
  6. 1 0
      src/or/entrynodes.h
  7. 1 0
      src/or/main.c

+ 11 - 1
src/or/circuitlist.c

@@ -553,7 +553,7 @@ circuit_close_all_marked(void)
   smartlist_clear(circuits_pending_close);
 }
 
-/** Return the head of the global linked list of circuits. */
+/** Return a pointer to the global list of circuits. */
 MOCK_IMPL(smartlist_t *,
 circuit_get_global_list,(void))
 {
@@ -562,6 +562,16 @@ circuit_get_global_list,(void))
   return global_circuitlist;
 }
 
+/** */
+/** Return a pointer to the global list of origin circuits. */
+smartlist_t *
+circuit_get_global_origin_circuit_list(void)
+{
+  if (NULL == global_origin_circuit_list)
+    global_origin_circuit_list = smartlist_new();
+  return global_circuitlist;
+}
+
 /** Function to make circ-\>state human-readable */
 const char *
 circuit_state_to_string(int state)

+ 1 - 0
src/or/circuitlist.h

@@ -15,6 +15,7 @@
 #include "testsupport.h"
 
 MOCK_DECL(smartlist_t *, circuit_get_global_list, (void));
+smartlist_t *circuit_get_global_origin_circuit_list(void);
 const char *circuit_state_to_string(int state);
 const char *circuit_purpose_to_controller_string(uint8_t purpose);
 const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose);

+ 19 - 0
src/or/circuituse.c

@@ -800,6 +800,25 @@ circuit_expire_building(void)
   } SMARTLIST_FOREACH_END(victim);
 }
 
+/**
+ * Mark for close all circuits that start here, that were built through a
+ * guard we weren't sure if we wanted to use, and that have been waiting
+ * around for way too long.
+ */
+void
+circuit_expire_waiting_for_better_guard(void)
+{
+  SMARTLIST_FOREACH_BEGIN(circuit_get_global_origin_circuit_list(),
+                          origin_circuit_t *, circ) {
+    if (TO_CIRCUIT(circ)->marked_for_close)
+      continue;
+    if (circ->guard_state == NULL)
+      continue;
+    if (entry_guard_state_should_expire(circ->guard_state))
+      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_NONE);
+  } SMARTLIST_FOREACH_END(circ);
+}
+
 /** For debugging #8387: track when we last called
  * circuit_expire_old_circuits_clientside. */
 static time_t last_expired_clientside_circuits = 0;

+ 1 - 0
src/or/circuituse.h

@@ -13,6 +13,7 @@
 #define TOR_CIRCUITUSE_H
 
 void circuit_expire_building(void);
+void circuit_expire_waiting_for_better_guard(void);
 void circuit_remove_handled_ports(smartlist_t *needed_ports);
 int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port,
                                     int min);

+ 15 - 3
src/or/entrynodes.c

@@ -1605,9 +1605,6 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
                 "circuit had higher priority, so not upgrading.",
                 n_complete, n_waiting);
 
-      /* XXXX prop271 implement: "(Time them out after a
-         {NONPRIMARY_GUARD_IDLE_TIMEOUT} seconds.)"
-      */
       return 0;
     }
   }
@@ -1671,6 +1668,21 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
   return 1;
 }
 
+/**
+ * Return true iff the circuit whose state is <b>guard_state</b> should
+ * expire.
+ */
+int
+entry_guard_state_should_expire(circuit_guard_state_t *guard_state)
+{
+  if (guard_state == NULL)
+    return 0;
+  const time_t expire_if_waiting_since =
+    approx_time() - NONPRIMARY_GUARD_IDLE_TIMEOUT;
+  return (guard_state->state == GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD
+          && guard_state->state_set_at < expire_if_waiting_since);
+}
+
 /**
  * Update all derived pieces of the guard selection state in <b>gs</b>.
  * Return true iff we should stop using all previously generated circuits.

+ 1 - 0
src/or/entrynodes.h

@@ -337,6 +337,7 @@ int entry_guards_update_all(guard_selection_t *gs);
 int entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
                                           const smartlist_t *all_circuits,
                                           smartlist_t *newly_complete_out);
+int entry_guard_state_should_expire(circuit_guard_state_t *guard_state);
 void entry_guards_note_internet_connectivity(guard_selection_t *gs);
 
 /* Used by bridges.c only. */

+ 1 - 0
src/or/main.c

@@ -1402,6 +1402,7 @@ run_scheduled_events(time_t now)
   /* (If our circuit build timeout can ever become lower than a second (which
    * it can't, currently), we should do this more often.) */
   circuit_expire_building();
+  circuit_expire_waiting_for_better_guard();
 
   /* 3b. Also look at pending streams and prune the ones that 'began'
    *     a long time ago but haven't gotten a 'connected' yet.