case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
rend_client_rendcirc_has_opened(circ);
/* Start building an intro circ if we don't have one yet. */
- connection_ap_attach_pending();
+ connection_ap_attach_pending(1);
/* This isn't a call to circuit_try_attaching_streams because a
* circuit in _C_ESTABLISH_REND state isn't connected to its
* hidden service yet, thus we can't attach streams to it yet,
circuit_try_attaching_streams(origin_circuit_t *circ)
{
/* Attach streams to this circuit if we can. */
- connection_ap_attach_pending();
+ connection_ap_attach_pending(1);
/* The call to circuit_try_clearing_isolation_state here will do
* nothing and return 0 if we didn't attach any streams to circ
* above. */
if (circuit_try_clearing_isolation_state(circ)) {
/* Maybe *now* we can attach some streams to this circuit. */
- connection_ap_attach_pending();
+ connection_ap_attach_pending(1);
}
}
/* XXXXX Free this list on exit. */
static smartlist_t *pending_entry_connections = NULL;
+static int untried_pending_connections = 0;
+
/** Common code to connection_(ap|exit)_about_to_close. */
static void
connection_edge_about_to_close(edge_connection_t *edge_conn)
"in pending_entry_connections, but wasn't. No worries; "
"adding it.",
pending_entry_connections);
+ untried_pending_connections = 1;
smartlist_add(pending_entry_connections, entry_conn);
}
} SMARTLIST_FOREACH_END(conn);
- connection_ap_attach_pending();
+ connection_ap_attach_pending(1);
}
/** Tell any AP streams that are listed as waiting for a new circuit to try
* again, either attaching to an available circ or launching a new one.
+ *
+ * If <b>retry</b> is false, only check the list if it contains at least one
+ * streams that we have not yet tried to attach to a circuit.
*/
void
-connection_ap_attach_pending(void)
+connection_ap_attach_pending(int retry)
{
if (PREDICT_UNLIKELY(!pending_entry_connections)) {
return;
}
+ if (untried_pending_connections == 0 && !retry)
+ return;
+
SMARTLIST_FOREACH_BEGIN(pending_entry_connections,
entry_connection_t *, entry_conn) {
connection_t *conn = ENTRY_TO_CONN(entry_conn);
}
} SMARTLIST_FOREACH_END(entry_conn);
+
+ untried_pending_connections = 0;
}
/** Mark <b>entry_conn</b> as needing to get attached to a circuit.
return;
}
+ untried_pending_connections = 1;
smartlist_add(pending_entry_connections, entry_conn);
}
const node_t *exit);
void connection_ap_expire_beginning(void);
void connection_ap_rescan_and_attach_pending(void);
-void connection_ap_attach_pending(void);
+void connection_ap_attach_pending(int retry);
void connection_ap_mark_as_pending_circuit(entry_connection_t *entry_conn);
void connection_ap_fail_onehop(const char *failed_digest,
cpath_build_state_t *build_state);
}
}
- /* This should be pretty fast if nothing is pending. BUT... watch out;
- * we need to make sure it doesn't show up in the profiles. five times a
- * second would be enough, for instance. */
- connection_ap_attach_pending();
+ /* This will be pretty fast if nothing new is pending. Note that this gets
+ * called once per libevent loop, which will make it happen once per group
+ * of events that fire, or once per second. */
+ connection_ap_attach_pending(0);
return 1;
}
tor_assert(circ->cpath);
log_info(LD_REND,"introcirc is open");
- connection_ap_attach_pending();
+ connection_ap_attach_pending(1);
}
/** Send the establish-rendezvous cell along a rendezvous circuit. if
* than trying to attach them all. See comments bug 743. */
/* If we already have the introduction circuit built, make sure we send
* the INTRODUCE cell _now_ */
- connection_ap_attach_pending();
+ connection_ap_attach_pending(1);
return 0;
}