summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/bridges.c2
-rw-r--r--src/or/channel.c1
-rw-r--r--src/or/circuitbuild.c75
-rw-r--r--src/or/circuitbuild.h6
-rw-r--r--src/or/circuitlist.c42
-rw-r--r--src/or/circuitlist.h2
-rw-r--r--src/or/circuituse.c2
-rw-r--r--src/or/connection.c1
-rw-r--r--src/or/connection_or.c6
-rw-r--r--src/or/directory.c74
-rw-r--r--src/or/directory.h6
-rw-r--r--src/or/entrynodes.c60
-rw-r--r--src/or/entrynodes.h2
-rw-r--r--src/or/main.c5
-rw-r--r--src/or/or.h4
-rw-r--r--src/or/rendclient.c2
-rw-r--r--src/or/rendservice.c2
-rw-r--r--src/or/routerlist.c4
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);