summaryrefslogtreecommitdiff
path: root/src/or/circuituse.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-07-19 13:51:43 -0400
committerNick Mathewson <nickm@torproject.org>2011-07-19 13:51:43 -0400
commite8b9815711e7cd1ef0b83153aefcc0d05e817f4e (patch)
tree70bedadab8572d9333232e51c2b835006c7cd4d1 /src/or/circuituse.c
parent12dfb4f5d8cfb0f244b4a1ae3cc3af237a3034e7 (diff)
downloadtor-e8b9815711e7cd1ef0b83153aefcc0d05e817f4e.tar.gz
tor-e8b9815711e7cd1ef0b83153aefcc0d05e817f4e.zip
Take a smarter approach to clearing isolation info
Back when I added this logic in 20c0581a79, the rule was that whenever a circuit finished building, we cleared its isolation info. I did that so that we would still use the circuit even if all the streams that had previously led us to tentatively set its isolation info had closed. But there were problems with that approach: We could pretty easily get into a case where S1 had led us to launch C1 and S2 had led us to launch C2, but when C1 finished, we cleared its isolation and attached S2 first. Since C2 was still marked in a way that made S1 unattachable to it, we'd then launch another circuit needlessly. So instead, we try the following approach now: when a circuit is done building, we try to attach streams to it. If it remains unused after we try attaching streams, then we clear its isolation info, and try again to attach streams. Thanks to Sebastian for helping me figure this out.
Diffstat (limited to 'src/or/circuituse.c')
-rw-r--r--src/or/circuituse.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index dcb6bfa501..b4860440cb 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -998,6 +998,7 @@ circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
void
circuit_has_opened(origin_circuit_t *circ)
{
+ int can_try_clearing_isolation = 0, tried_clearing_isolation = 0;
control_event_circuit_status(circ, CIRC_EVENT_BUILT, 0);
/* Remember that this circuit has finished building. Now if we start
@@ -1005,9 +1006,12 @@ circuit_has_opened(origin_circuit_t *circ)
* to consider its build time. */
circ->has_opened = 1;
+ again:
+
switch (TO_CIRCUIT(circ)->purpose) {
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
rend_client_rendcirc_has_opened(circ);
+ can_try_clearing_isolation = 1;
connection_ap_attach_pending();
break;
case CIRCUIT_PURPOSE_C_INTRODUCING:
@@ -1016,6 +1020,7 @@ circuit_has_opened(origin_circuit_t *circ)
case CIRCUIT_PURPOSE_C_GENERAL:
/* Tell any AP connections that have been waiting for a new
* circuit that one is ready. */
+ can_try_clearing_isolation = 1;
connection_ap_attach_pending();
break;
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
@@ -1033,6 +1038,17 @@ circuit_has_opened(origin_circuit_t *circ)
* This won't happen in normal operation, but might happen if the
* controller did it. Just let it slide. */
}
+
+ if (can_try_clearing_isolation && !tried_clearing_isolation &&
+ circ->isolation_values_set &&
+ !circ->isolation_any_streams_attached) {
+ /* If we have any isolation information set on this circuit, and
+ * we didn't manage to attach any streams to it, then we can
+ * and should clear it and try again. */
+ circuit_clear_isolation(circ);
+ tried_clearing_isolation = 1;
+ goto again;
+ }
}
/** Called whenever a circuit could not be successfully built.