diff options
Diffstat (limited to 'src/or/circuitbuild.c')
-rw-r--r-- | src/or/circuitbuild.c | 75 |
1 files changed, 70 insertions, 5 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index a33c2ca654..2f4ce7a727 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -964,7 +964,35 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) memset(&ec, 0, sizeof(ec)); if (!hop) { /* done building the circuit. whew. */ - circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN); + int r; + if (! circ->guard_state) { + if (circuit_get_cpath_len(circ) != 1) { + log_warn(LD_BUG, "%d-hop circuit %p with purpose %d has no " + "guard state", + circuit_get_cpath_len(circ), circ, circ->base_.purpose); + } + r = 1; + } else { + r = entry_guard_succeeded(get_guard_selection_info(), + &circ->guard_state); + } + const int is_usable_for_streams = (r == 1); + if (r == 1) { + circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN); + } else if (r == 0) { + // XXXX prop271 we might want to probe for whether this + // XXXX one is ready even before the next second rolls over. + circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_GUARD_WAIT); + } else { + return - END_CIRC_REASON_INTERNAL; + } + + /* XXXX prop271 -- the rest of this branch needs careful thought! + * Some of the things here need to happen when a circuit becomes + * mechanically open; some need to happen when it is actually usable. + * I think I got them right, but more checking would be wise. -NM + */ + if (circuit_timeout_want_to_count_circ(circ)) { struct timeval end; long timediff; @@ -1006,7 +1034,8 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) pathbias_count_build_success(circ); circuit_rep_hist_note_result(circ); - circuit_has_opened(circ); /* do other actions as necessary */ + if (is_usable_for_streams) + circuit_has_opened(circ); /* do other actions as necessary */ if (!have_completed_a_circuit() && !circ->build_state->onehop_tunnel) { const or_options_t *options = get_options(); @@ -2206,9 +2235,20 @@ choose_good_middle_server(uint8_t purpose, * * If <b>state</b> is NULL, we're choosing a router to serve as an entry * guard, not for any particular circuit. + * + * Set *<b>guard_state_out</b> to information about the guard that + * we're selecting, which we'll use later to remember whether the + * guard worked or not. + * + * XXXX prop271 this function is used in four ways: picking out guards for + * the old (pre-prop271) guard algorithm; picking out guards for circuits; + * picking out guards for testing circuits on non-bridgees; + * picking out entries when entry guards are disabled. These options + * should be disentangled. */ const node_t * -choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) +choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state, + circuit_guard_state_t **guard_state_out) { const node_t *choice; smartlist_t *excluded; @@ -2223,7 +2263,8 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) (purpose != CIRCUIT_PURPOSE_TESTING || options->BridgeRelay)) { /* This request is for an entry server to use for a regular circuit, * and we use entry guard nodes. Just return one of the guard nodes. */ - return choose_random_entry(state); + tor_assert(guard_state_out); + return guards_choose_guard(state, guard_state_out); } excluded = smartlist_new(); @@ -2306,7 +2347,8 @@ onion_extend_cpath(origin_circuit_t *circ) if (cur_len == state->desired_path_len - 1) { /* Picking last node */ info = extend_info_dup(state->chosen_exit); } else if (cur_len == 0) { /* picking first node */ - const node_t *r = choose_good_entry_server(purpose, state); + const node_t *r = choose_good_entry_server(purpose, state, + &circ->guard_state); if (r) { /* If we're a client, use the preferred address rather than the primary address, for potentially connecting to an IPv6 OR @@ -2574,3 +2616,26 @@ extend_info_has_preferred_onion_key(const extend_info_t* ei) return extend_info_supports_ntor(ei); } +/** Find the circuits that are waiting to find out whether their guards are + * usable, and if any are ready to become usable, mark them open and try + * attaching streams as appropriate. */ +void +circuit_upgrade_circuits_from_guard_wait(void) +{ + smartlist_t *to_upgrade = + circuit_find_circuits_to_upgrade_from_guard_wait(); + + if (to_upgrade == NULL) + return; + + log_info(LD_GUARD, "Upgrading %d circuits from 'waiting for better guard' " + "to 'open'.", smartlist_len(to_upgrade)); + + SMARTLIST_FOREACH_BEGIN(to_upgrade, origin_circuit_t *, circ) { + circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN); + circuit_has_opened(circ); + } SMARTLIST_FOREACH_END(circ); + + smartlist_free(to_upgrade); +} + |