aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bug32965
-rw-r--r--src/or/circuitbuild.c4
-rw-r--r--src/or/rephist.c20
-rw-r--r--src/or/rephist.h1
4 files changed, 30 insertions, 0 deletions
diff --git a/changes/bug3296 b/changes/bug3296
new file mode 100644
index 000000000..31c9eacb6
--- /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 5481838cc..3b82ed745 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 0cd60eeb8..c3f059839 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 0a3e46ae1..800b957d5 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);