diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/bridges.c | 2 | ||||
-rw-r--r-- | src/or/channel.c | 1 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 75 | ||||
-rw-r--r-- | src/or/circuitbuild.h | 6 | ||||
-rw-r--r-- | src/or/circuitlist.c | 42 | ||||
-rw-r--r-- | src/or/circuitlist.h | 2 | ||||
-rw-r--r-- | src/or/circuituse.c | 2 | ||||
-rw-r--r-- | src/or/connection.c | 1 | ||||
-rw-r--r-- | src/or/connection_or.c | 6 | ||||
-rw-r--r-- | src/or/directory.c | 74 | ||||
-rw-r--r-- | src/or/directory.h | 6 | ||||
-rw-r--r-- | src/or/entrynodes.c | 60 | ||||
-rw-r--r-- | src/or/entrynodes.h | 2 | ||||
-rw-r--r-- | src/or/main.c | 5 | ||||
-rw-r--r-- | src/or/or.h | 4 | ||||
-rw-r--r-- | src/or/rendclient.c | 2 | ||||
-rw-r--r-- | src/or/rendservice.c | 2 | ||||
-rw-r--r-- | src/or/routerlist.c | 4 |
18 files changed, 262 insertions, 34 deletions
diff --git a/src/or/bridges.c b/src/or/bridges.c index 508c77fc9e..2170cc668a 100644 --- a/src/or/bridges.c +++ b/src/or/bridges.c @@ -724,6 +724,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache) from_cache ? "cached" : "fresh", router_describe(ri)); /* set entry->made_contact so if it goes down we don't drop it from * our entry node list */ + // XXXX prop271 use new interface here when we hit bridges? entry_guard_register_connect_status(ri->cache_info.identity_digest, 1, 0, now); if (first) { @@ -743,6 +744,7 @@ int any_bridge_descriptors_known(void) { tor_assert(get_options()->UseBridges); + // XXXX prop271 this needs to get fixed. -- bridges return choose_random_entry(NULL) != NULL; } diff --git a/src/or/channel.c b/src/or/channel.c index af5810788c..1e3e99c51d 100644 --- a/src/or/channel.c +++ b/src/or/channel.c @@ -2538,6 +2538,7 @@ channel_do_open_actions(channel_t *chan) if (started_here) { circuit_build_times_network_is_live(get_circuit_build_times_mutable()); rep_hist_note_connect_succeeded(chan->identity_digest, now); + // XXXX prop271 this call is no longer useful with the new algorithm. if (entry_guard_register_connect_status( chan->identity_digest, 1, 0, now) < 0) { /* Close any circuits pending on this channel. We leave it in state 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); +} + diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index 56f66a19d6..2c83a16550 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -64,8 +64,12 @@ int extend_info_has_preferred_onion_key(const extend_info_t* ei); const node_t *build_state_get_exit_node(cpath_build_state_t *state); const char *build_state_get_exit_nickname(cpath_build_state_t *state); +struct circuit_guard_state_t; + const node_t *choose_good_entry_server(uint8_t purpose, - cpath_build_state_t *state); + cpath_build_state_t *state, + struct circuit_guard_state_t **guard_state_out); +void circuit_upgrade_circuits_from_guard_wait(void); #ifdef CIRCUITBUILD_PRIVATE STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan); diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index c274534759..2a03f8a0d9 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -92,6 +92,10 @@ static smartlist_t *global_origin_circuit_list = NULL; /** A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT. */ static smartlist_t *circuits_pending_chans = NULL; +/** List of all the (origin) circuits whose state is + * CIRCUIT_STATE_GUARD_WAIT. */ +static smartlist_t *circuits_pending_other_guards = NULL; + /** A list of all the circuits that have been marked with * circuit_mark_for_close and which are waiting for circuit_about_to_free. */ static smartlist_t *circuits_pending_close = NULL; @@ -433,8 +437,10 @@ circuit_set_state(circuit_t *circ, uint8_t state) tor_assert(circ); if (state == circ->state) return; - if (!circuits_pending_chans) + if (PREDICT_UNLIKELY(!circuits_pending_chans)) circuits_pending_chans = smartlist_new(); + if (PREDICT_UNLIKELY(!circuits_pending_other_guards)) + circuits_pending_other_guards = smartlist_new(); if (circ->state == CIRCUIT_STATE_CHAN_WAIT) { /* remove from waiting-circuit list. */ smartlist_remove(circuits_pending_chans, circ); @@ -1022,6 +1028,9 @@ circuit_free_all(void) smartlist_free(circuits_pending_close); circuits_pending_close = NULL; + smartlist_free(circuits_pending_other_guards); + circuits_pending_other_guards = NULL; + { chan_circid_circuit_map_t **elt, **next, *c; for (elt = HT_START(chan_circid_map, &chan_circid_map); @@ -1721,6 +1730,37 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, return best; } +/** + * Check whether any of the origin circuits that are waiting to see if + * their guard is good enough to use can be upgraded to "ready". If so, + * return a new smartlist containing them. Otherwise return NULL. + */ +smartlist_t * +circuit_find_circuits_to_upgrade_from_guard_wait(void) +{ + /* Only if some circuit is actually waiting on an upgrade should we + * run the algorithm. */ + if (! circuits_pending_other_guards || + smartlist_len(circuits_pending_other_guards)==0) + return NULL; + /* Only if we have some origin circuiuts should we run the algorithm. + */ + if (!global_origin_circuit_list) + return NULL; + + /* Okay; we can pass our circuit list to entrynodes.c.*/ + smartlist_t *result = smartlist_new(); + int r = entry_guards_upgrade_waiting_circuits(get_guard_selection_info(), + global_origin_circuit_list, + result); + if (r && smartlist_len(result)) { + return result; + } else { + smartlist_free(result); + return NULL; + } +} + /** Return the number of hops in circuit's path. If circ has no entries, * or is NULL, returns 0. */ int diff --git a/src/or/circuitlist.h b/src/or/circuitlist.h index 989c02afd5..73039cc06e 100644 --- a/src/or/circuitlist.h +++ b/src/or/circuitlist.h @@ -77,6 +77,8 @@ void channel_note_destroy_pending(channel_t *chan, circid_t id); MOCK_DECL(void, channel_note_destroy_not_pending, (channel_t *chan, circid_t id)); +smartlist_t *circuit_find_circuits_to_upgrade_from_guard_wait(void); + #ifdef CIRCUITLIST_PRIVATE STATIC void circuit_free(circuit_t *circ); STATIC size_t n_cells_in_circ_queues(const circuit_t *c); diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 2f972d1a28..d2a7f20aa2 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1633,6 +1633,8 @@ circuit_build_failed(origin_circuit_t *circ) "Our circuit died before the first hop with no connection"); } if (n_chan_id && !already_marked) { + entry_guard_failed(get_guard_selection_info(), &circ->guard_state); + /* XXXX prop271 -- old API */ entry_guard_register_connect_status(n_chan_id, 0, 1, time(NULL)); /* if there are any one-hop streams waiting on this circuit, fail * them now so they can retry elsewhere. */ diff --git a/src/or/connection.c b/src/or/connection.c index 2964c30f73..c2a7a87d41 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -634,6 +634,7 @@ connection_free_(connection_t *conn) cached_dir_decref(dir_conn->cached_dir); rend_data_free(dir_conn->rend_data); + circuit_guard_state_free(dir_conn->guard_state); } if (SOCKET_OK(conn->s)) { diff --git a/src/or/connection_or.c b/src/or/connection_or.c index ecc5a4511a..fefcc86932 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -735,6 +735,9 @@ connection_or_about_to_close(or_connection_t *or_conn) const or_options_t *options = get_options(); connection_or_note_state_when_broken(or_conn); rep_hist_note_connect_failed(or_conn->identity_digest, now); + entry_guard_chan_failed(get_guard_selection_info(), + TLS_CHAN_TO_BASE(or_conn->chan)); + /* XXXX prop271 -- old API */ entry_guard_register_connect_status(or_conn->identity_digest,0, !options->HTTPSProxy, now); if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) { @@ -1673,6 +1676,9 @@ connection_or_client_learned_peer_id(or_connection_t *conn, "Tried connecting to router at %s:%d, but identity key was not " "as expected: wanted %s but got %s.%s", conn->base_.address, conn->base_.port, expected, seen, extra_log); + entry_guard_chan_failed(get_guard_selection_info(), + TLS_CHAN_TO_BASE(conn->chan)); + /* XXXX prop271 old API */ entry_guard_register_connect_status(conn->identity_digest, 0, 1, time(NULL)); control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, diff --git a/src/or/directory.c b/src/or/directory.c index efa5a3126a..4164672f10 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -128,7 +128,8 @@ static void directory_initiate_command_rend( const char *payload, size_t payload_len, time_t if_modified_since, - const rend_data_t *rend_query); + const rend_data_t *rend_query, + circuit_guard_state_t *guard_state); static void connection_dir_close_consensus_fetches( dir_connection_t *except_this_one, const char *resource); @@ -422,7 +423,8 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose, indirection, - NULL, payload, upload_len, 0); + NULL, payload, upload_len, 0, + NULL); } SMARTLIST_FOREACH_END(ds); if (!found) { char *s = authdir_type_to_string(type); @@ -458,7 +460,8 @@ should_use_directory_guards(const or_options_t *options) * information of type <b>type</b>, and return its routerstatus. */ static const routerstatus_t * directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags, - uint8_t dir_purpose) + uint8_t dir_purpose, + circuit_guard_state_t **guard_state_out) { const routerstatus_t *rs = NULL; const or_options_t *options = get_options(); @@ -467,7 +470,7 @@ directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags, log_warn(LD_BUG, "Called when we have UseBridges set."); if (should_use_directory_guards(options)) { - const node_t *node = choose_random_dirguard(type); + const node_t *node = guards_choose_dirguard(type, guard_state_out); if (node) rs = node->rs; } else { @@ -548,6 +551,7 @@ MOCK_IMPL(void, directory_get_from_dirserver, ( if (!options->FetchServerDescriptors) return; + circuit_guard_state_t *guard_state = NULL; if (!get_via_tor) { if (options->UseBridges && !(type & BRIDGE_DIRINFO)) { /* We want to ask a running bridge for which we have a descriptor. @@ -556,6 +560,7 @@ MOCK_IMPL(void, directory_get_from_dirserver, ( * sort of dir fetch we'll be doing, so it won't return a bridge * that can't answer our question. */ + // XXXX prop271 update this for bridge support. const node_t *node = choose_random_dirguard(type); if (node && node->ri) { /* every bridge has a routerinfo. */ @@ -605,9 +610,9 @@ MOCK_IMPL(void, directory_get_from_dirserver, ( } } if (!rs && !(type & BRIDGE_DIRINFO)) { - /* */ rs = directory_pick_generic_dirserver(type, pds_flags, - dir_purpose); + dir_purpose, + &guard_state); if (!rs) get_via_tor = 1; /* last resort: try routing it via Tor */ } @@ -630,7 +635,8 @@ MOCK_IMPL(void, directory_get_from_dirserver, ( router_purpose, indirection, resource, NULL, 0, - if_modified_since); + if_modified_since, + guard_state); } else { log_notice(LD_DIR, "While fetching directory info, " @@ -664,7 +670,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose, rs = &ds->fake_status; directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose, DIRIND_ONEHOP, resource, NULL, - 0, 0); + 0, 0, NULL); } SMARTLIST_FOREACH_END(ds); } @@ -775,7 +781,8 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status, const char *payload, size_t payload_len, time_t if_modified_since, - const rend_data_t *rend_query) + const rend_data_t *rend_query, + circuit_guard_state_t *guard_state) { const or_options_t *options = get_options(); const node_t *node; @@ -830,7 +837,8 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status, dir_purpose, router_purpose, indirection, resource, payload, payload_len, if_modified_since, - rend_query); + rend_query, + guard_state); } /** Launch a new connection to the directory server <b>status</b> to @@ -855,13 +863,15 @@ MOCK_IMPL(void, directory_initiate_command_routerstatus, const char *resource, const char *payload, size_t payload_len, - time_t if_modified_since)) + time_t if_modified_since, + circuit_guard_state_t *guard_state)) { directory_initiate_command_routerstatus_rend(status, dir_purpose, router_purpose, indirection, resource, payload, payload_len, - if_modified_since, NULL); + if_modified_since, NULL, + guard_state); } /** Return true iff <b>conn</b> is the client side of a directory connection @@ -889,6 +899,11 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn) static void connection_dir_request_failed(dir_connection_t *conn) { + if (conn->guard_state) { + /* We haven't seen a success on this guard state, so consider it to have + * failed. */ + entry_guard_failed(get_guard_selection_info(), &conn->guard_state); + } if (directory_conn_is_self_reachability_test(conn)) { return; /* this was a test fetch. don't retry. */ } @@ -1136,7 +1151,7 @@ directory_initiate_command(const tor_addr_t *or_addr, uint16_t or_port, digest, dir_purpose, router_purpose, indirection, resource, payload, payload_len, - if_modified_since, NULL); + if_modified_since, NULL, NULL); } /** Same as directory_initiate_command(), but accepts rendezvous data to @@ -1151,7 +1166,8 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port, const char *resource, const char *payload, size_t payload_len, time_t if_modified_since, - const rend_data_t *rend_query) + const rend_data_t *rend_query, + circuit_guard_state_t *guard_state) { tor_assert(or_addr_port); tor_assert(dir_addr_port); @@ -1246,12 +1262,18 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port, if (!anonymized_connection && !use_begindir) { /* then we want to connect to dirport directly */ + // XXXX prop271 I think that we never use guards in this case. if (options->HTTPProxy) { tor_addr_copy(&addr, &options->HTTPProxyAddr); port = options->HTTPProxyPort; } + // In this case we should not have picked a directory guard. + if (BUG(guard_state)) { + entry_guard_cancel(get_guard_selection_info(), &guard_state); + } + switch (connection_connect(TO_CONN(conn), conn->base_.address, &addr, port, &socket_error)) { case -1: @@ -1288,6 +1310,14 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port, else if (anonymized_connection && !use_begindir) rep_hist_note_used_port(time(NULL), conn->base_.port); + // In this case we should not have a directory guard; we'll + // get a regular guard later when we build the circuit. + if (BUG(anonymized_connection && guard_state)) { + entry_guard_cancel(get_guard_selection_info(), &guard_state); + } + + conn->guard_state = guard_state; + /* make an AP connection * populate it and add it at the right state * hook up both sides @@ -2540,6 +2570,22 @@ connection_dir_process_inbuf(dir_connection_t *conn) tor_assert(conn); tor_assert(conn->base_.type == CONN_TYPE_DIR); + if (conn->guard_state) { + /* we count the connection as successful once we can read from it. We do + * not, however, delay use of the circuit here, since it's just for a + * one-hop directory request. */ + /* XXXXprop271 note that this will not do the right thing for other + * waiting circuits that would be triggered by this circuit becoming + * complete/usable. But that's ok, I think. + */ + /* XXXXprop271 should we count this as only a partial success somehow? + */ + entry_guard_succeeded(get_guard_selection_info(), + &conn->guard_state); + circuit_guard_state_free(conn->guard_state); + conn->guard_state = NULL; + } + /* Directory clients write, then read data until they receive EOF; * directory servers read data until they get an HTTP command, then * write their response (when it's finished flushing, they mark for diff --git a/src/or/directory.h b/src/or/directory.h index 589df7b70d..ee0a198c52 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -49,7 +49,8 @@ MOCK_DECL(void, directory_initiate_command_routerstatus, const char *resource, const char *payload, size_t payload_len, - time_t if_modified_since)); + time_t if_modified_since, + struct circuit_guard_state_t *guard_state)); void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, @@ -59,7 +60,8 @@ void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, const char *payload, size_t payload_len, time_t if_modified_since, - const rend_data_t *rend_query); + const rend_data_t *rend_query, + struct circuit_guard_state_t *guard_state); int parse_http_response(const char *headers, int *code, time_t *date, compress_method_t *compression, char **response); diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 24a3448969..eca88a947c 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -89,7 +89,7 @@ * [x] Whenever a guard becomes reachable or maybe-reachable, if its filtered * flag is set, set its usable_filtered flag. * - * [ ] Whenever we get a new consensus, call update_from_consensus(). (LATER.) + * [x] Whenever we get a new consensus, call update_from_consensus(). (LATER.) * * [ ] Whenever the configuration changes in a relevant way, update the * filtered/usable flags. (LATER.) @@ -1203,8 +1203,6 @@ entry_guards_note_guard_success(guard_selection_t *gs, if (last_time_on_internet + INTERNET_LIKELY_DOWN_INTERVAL < approx_time()) { mark_primary_guards_maybe_reachable(gs); - } else { - // update_waiting_circuits(gs); // XXXX prop271 write this function. } } @@ -1475,7 +1473,7 @@ circ_state_has_higher_priority(origin_circuit_t *a, */ int entry_guards_upgrade_waiting_circuits(guard_selection_t *gs, - smartlist_t *all_circuits, + const smartlist_t *all_circuits, smartlist_t *newly_complete_out) { tor_assert(gs); @@ -2274,7 +2272,7 @@ add_an_entry_guard(guard_selection_t *gs, return NULL; } } else if (!for_directory) { - node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL); + node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL, NULL); if (!node) return NULL; } else { @@ -3779,6 +3777,58 @@ entries_retry_all(const or_options_t *options) entries_retry_helper(options, 1); } +/** Helper: Update the status of all entry guards, in whatever algorithm + is used. */ +void +guards_update_all(void) +{ + if (get_options()->UseDeprecatedGuardAlgorithm) { + entry_guards_compute_status(get_options(), approx_time()); + } else { + entry_guards_update_all(get_guard_selection_info()); + } +} + +/** Helper: pick a guard for a circuit, with whatever algorithm is + used. */ +const node_t * +guards_choose_guard(cpath_build_state_t *state, + circuit_guard_state_t **guard_state_out) +{ + if (get_options()->UseDeprecatedGuardAlgorithm) { + return choose_random_entry(state); + } else { + // XXXX prop271 we need to look at the chosen exit node if any, and + // not duplicate it. + const node_t *r = NULL; + if (entry_guard_pick_for_circuit(get_guard_selection_info(), + &r, + guard_state_out) < 0) { + tor_assert(r == NULL); + } + return r; + } +} + +/** Helper: pick a directory guard, with whatever algorithm is used. */ +const node_t * +guards_choose_dirguard(dirinfo_type_t info, + circuit_guard_state_t **guard_state_out) +{ + if (get_options()->UseDeprecatedGuardAlgorithm) { + return choose_random_dirguard(info); + } else { + // XXXX prop271 look at info? + const node_t *r = NULL; + if (entry_guard_pick_for_circuit(get_guard_selection_info(), + &r, + guard_state_out) < 0) { + tor_assert(r == NULL); + } + return r; + } +} + /** Free one guard selection context */ STATIC void guard_selection_free(guard_selection_t *gs) diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h index 60191ab8b9..7dcedd6066 100644 --- a/src/or/entrynodes.h +++ b/src/or/entrynodes.h @@ -328,7 +328,7 @@ void entry_guard_chan_failed(guard_selection_t *gs, channel_t *chan); void entry_guards_update_all(guard_selection_t *gs); int entry_guards_upgrade_waiting_circuits(guard_selection_t *gs, - smartlist_t *all_circuits, + const smartlist_t *all_circuits, smartlist_t *newly_complete_out); void entry_guards_note_internet_connectivity(guard_selection_t *gs); diff --git a/src/or/main.c b/src/or/main.c index a508003f97..65d1c1fd79 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -979,7 +979,7 @@ directory_info_has_arrived(time_t now, int from_cache, int suppress_logs) /* if we have enough dir info, then update our guard status with * whatever we just learned. */ - entry_guards_compute_status(options, now); + guards_update_all(); /* Don't even bother trying to get extrainfo until the rest of our * directory info is up-to-date */ if (options->DownloadExtraInfo) @@ -1376,6 +1376,9 @@ run_scheduled_events(time_t now) /* 0c. If we've deferred log messages for the controller, handle them now */ flush_pending_log_callbacks(); + /* Maybe enough time elapsed for us to reconsider a circuit. */ + circuit_upgrade_circuits_from_guard_wait(); + if (options->UseBridges && !options->DisableNetwork) { fetch_bridge_descriptors(options, now); } diff --git a/src/or/or.h b/src/or/or.h index c8f39f90d9..8b9ede3607 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1786,6 +1786,10 @@ typedef struct dir_connection_t { /** What rendezvous service are we querying for? */ rend_data_t *rend_data; + /** If this is a one-hop connection, tracks the state of the directory guard + * for this connection (if any). */ + struct circuit_guard_state_t *guard_state; + char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for * the directory server's signing key. */ diff --git a/src/or/rendclient.c b/src/or/rendclient.c index b0dcf52507..06744ad795 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -762,7 +762,7 @@ directory_get_from_hs_dir(const char *desc_id, how_to_fetch, desc_id_base32, NULL, 0, 0, - rend_query); + rend_query, NULL); log_info(LD_REND, "Sending fetch request for v2 descriptor for " "service '%s' with descriptor ID '%s', auth type %d, " "and descriptor cookie '%s' to hidden service " diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 8ffd0bc319..cf57c7d061 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -3452,7 +3452,7 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, DIRIND_ANONYMOUS, NULL, desc->desc_str, strlen(desc->desc_str), - 0, rend_data); + 0, rend_data, NULL); rend_data_free(rend_data); base32_encode(desc_id_base32, sizeof(desc_id_base32), desc->desc_id, DIGEST_LEN); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index f51b50e8e5..d2f360a63f 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -971,7 +971,7 @@ authority_certs_fetch_resource_impl(const char *resource, directory_initiate_command_routerstatus(rs, DIR_PURPOSE_FETCH_CERTIFICATE, 0, indirection, resource, NULL, - 0, 0); + 0, 0, NULL); return; } @@ -4946,7 +4946,7 @@ MOCK_IMPL(STATIC void, initiate_descriptor_downloads, directory_initiate_command_routerstatus(source, purpose, ROUTER_PURPOSE_GENERAL, DIRIND_ONEHOP, - resource, NULL, 0, 0); + resource, NULL, 0, 0, NULL); } else { directory_get_from_dirserver(purpose, ROUTER_PURPOSE_GENERAL, resource, pds_flags, DL_WANT_ANY_DIRSERVER); |