[tor-commits] [tor/master] When no usable exit satisfies a predicted port, stop predicting it.

nickm at torproject.org nickm at torproject.org
Wed May 16 14:44:31 UTC 2012


commit 0888c2f8f55037b49fead49091013f2cc7de17c5
Author: Nick Mathewson <nickm at torproject.org>
Date:   Fri May 11 12:52:21 2012 -0400

    When no usable exit satisfies a predicted port, stop predicting it.
    
    Fix for bug 3296.
---
 changes/bug3296       |    5 +++++
 src/or/circuitbuild.c |    4 ++++
 src/or/rephist.c      |   20 ++++++++++++++++++++
 src/or/rephist.h      |    1 +
 4 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/changes/bug3296 b/changes/bug3296
new file mode 100644
index 0000000..31c9eac
--- /dev/null
+++ b/changes/bug3296
@@ -0,0 +1,5 @@
+  o Major bugfixes:
+    - If we are unable to find any exit that supports our predicted
+      ports, stop calling them predicted, so that we don't loop and
+      build hopeless circuits indefinitely. Fix for bug 3296; bugfix
+      on 0.0.9pre6, which introduced predicted ports.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 5481838..3b82ed7 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -2847,6 +2847,10 @@ choose_good_exit_server_general(int need_uptime, int need_capacity)
       if (node)
         break;
       smartlist_clear(supporting);
+      /* If we reach this point, we can't actually support any unhandled
+       * predicted ports, so clear all the remaining ones. */
+      if (smartlist_len(needed_ports))
+        rep_hist_remove_predicted_ports(needed_ports);
     }
     SMARTLIST_FOREACH(needed_ports, uint16_t *, cp, tor_free(cp));
     smartlist_free(needed_ports);
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 0cd60ee..c3f0598 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -1868,6 +1868,26 @@ rep_hist_get_predicted_ports(time_t now)
   return out;
 }
 
+/**
+ * Take a list of uint16_t *, and remove every port in the list from the
+ * current list of predicted ports.
+ */
+void
+rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports)
+{
+  /* Let's do this on O(N), not O(N^2). */
+  bitarray_t *remove_ports = bitarray_init_zero(UINT16_MAX);
+  SMARTLIST_FOREACH(rmv_ports, const uint16_t *, p,
+                    bitarray_set(remove_ports, *p));
+  SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
+    if (bitarray_is_set(remove_ports, pp->port)) {
+      tor_free(pp);
+      SMARTLIST_DEL_CURRENT(predicted_ports_list, pp);
+    }
+  } SMARTLIST_FOREACH_END(pp);
+  bitarray_free(remove_ports);
+}
+
 /** The user asked us to do a resolve. Rather than keeping track of
  * timings and such of resolves, we fake it for now by treating
  * it the same way as a connection to port 80. This way we will continue
diff --git a/src/or/rephist.h b/src/or/rephist.h
index 0a3e46a..800b957 100644
--- a/src/or/rephist.h
+++ b/src/or/rephist.h
@@ -49,6 +49,7 @@ const char *rep_hist_get_router_stability_doc(time_t now);
 
 void rep_hist_note_used_port(time_t now, uint16_t port);
 smartlist_t *rep_hist_get_predicted_ports(time_t now);
+void rep_hist_remove_predicted_ports(const smartlist_t *rmv_ports);
 void rep_hist_note_used_resolve(time_t now);
 void rep_hist_note_used_internal(time_t now, int need_uptime,
                                  int need_capacity);





More information about the tor-commits mailing list