/* add to waiting-circuit list. */
smartlist_add(circuits_pending_or_conns, circ);
}
-
- circ->state = state;
-
- if (state == CIRCUIT_STATE_OPEN) {
+ if (state == CIRCUIT_STATE_OPEN)
tor_assert(!circ->n_conn_onionskin);
- if (CIRCUIT_IS_ORIGIN(circ)) {
- origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
- if (origin_circ->isolation_values_set &&
- !origin_circ->isolation_any_streams_attached) {
- /* If we have any isolation information set on this circuit,
- * but we never attached any streams to it, then all of the
- * isolation information was hypothetical. Clear it.
- */
- circuit_clear_isolation(origin_circ);
- }
- }
- }
+ circ->state = state;
}
/** Add <b>circ</b> to the global list of circuits. This is called only from
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
* 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:
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:
* 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.
* it, and whose isolation settings are hypothetical. (We set hypothetical
* isolation settings on circuits as we're launching them, so that we
* know whether they can handle more streams or whether we need to launch
- * even more circuits. We clear the flags once the circuits are open,
- * in case the streams that made us launch the circuits have closed
- * since we began launching the circuits.)
+ * even more circuits. Once the circuit is open, if it turns out that
+ * we no longer have any streams to attach to it, we clear the isolation flags
+ * and data so that other streams can have a chance.)
*/
void
circuit_clear_isolation(origin_circuit_t *circ)