diff options
Diffstat (limited to 'src/or/bridges.c')
-rw-r--r-- | src/or/bridges.c | 61 |
1 files changed, 46 insertions, 15 deletions
diff --git a/src/or/bridges.c b/src/or/bridges.c index 0b4588307c..320f5ee632 100644 --- a/src/or/bridges.c +++ b/src/or/bridges.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2016, The Tor Project, Inc. */ + * Copyright (c) 2007-2017, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -54,6 +54,8 @@ struct bridge_info_t { }; static void bridge_free(bridge_info_t *bridge); +static void rewrite_node_address_for_bridge(const bridge_info_t *bridge, + node_t *node); /** A list of configured bridges. Whenever we actually get a descriptor * for one, we add it as an entry guard. Note that the order of bridges @@ -310,7 +312,7 @@ learned_router_identity(const tor_addr_t *addr, uint16_t port, memcpy(&bridge->ed25519_identity, ed_id, sizeof(*ed_id)); learned = 1; } -#endif +#endif /* 0 */ if (learned) { char *transport_info = NULL; const char *transport_name = @@ -454,6 +456,9 @@ bridge_add_from_config(bridge_line_t *bridge_line) b->transport_name = bridge_line->transport_name; b->fetch_status.schedule = DL_SCHED_BRIDGE; b->fetch_status.backoff = DL_SCHED_RANDOM_EXPONENTIAL; + b->fetch_status.increment_on = DL_SCHED_INCREMENT_ATTEMPT; + /* We can't reset the bridge's download status here, because UseBridges + * might be 0 now, and it might be changed to 1 much later. */ b->socks_args = bridge_line->socks_args; if (!bridge_list) bridge_list = smartlist_new(); @@ -571,15 +576,29 @@ launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge) return; } + /* If we already have a node_t for this bridge, rewrite its address now. */ + node_t *node = node_get_mutable_by_id(bridge->identity); + if (node) { + rewrite_node_address_for_bridge(bridge, node); + } + + tor_addr_port_t bridge_addrport; + memcpy(&bridge_addrport.addr, &bridge->addr, sizeof(tor_addr_t)); + bridge_addrport.port = bridge->port; + guard_state = get_guard_state_for_bridge_desc_fetch(bridge->identity); - directory_initiate_command(&bridge->addr, bridge->port, - NULL, 0, /*no dirport*/ - bridge->identity, - DIR_PURPOSE_FETCH_SERVERDESC, - ROUTER_PURPOSE_BRIDGE, - DIRIND_ONEHOP, "authority.z", NULL, 0, 0, - guard_state); + directory_request_t *req = + directory_request_new(DIR_PURPOSE_FETCH_SERVERDESC); + directory_request_set_or_addr_port(req, &bridge_addrport); + directory_request_set_directory_id_digest(req, bridge->identity); + directory_request_set_router_purpose(req, ROUTER_PURPOSE_BRIDGE); + directory_request_set_resource(req, "authority.z"); + if (guard_state) { + directory_request_set_guard_state(req, guard_state); + } + directory_initiate_request(req); + directory_request_free(req); } /** Fetching the bridge descriptor from the bridge authority returned a @@ -614,6 +633,7 @@ fetch_bridge_descriptors(const or_options_t *options, time_t now) SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) { + /* This resets the download status on first use */ if (!download_status_is_ready(&bridge->fetch_status, now, IMPOSSIBLE_TO_DOWNLOAD)) continue; /* don't bother, no need to retry yet */ @@ -624,8 +644,13 @@ fetch_bridge_descriptors(const or_options_t *options, time_t now) continue; } - /* schedule another fetch as if this one will fail, in case it does */ - download_status_failed(&bridge->fetch_status, 0); + /* schedule the next attempt + * we can't increment after a failure, because sometimes we use the + * bridge authority, and sometimes we use the bridge direct */ + download_status_increment_attempt( + &bridge->fetch_status, + safe_str_client(fmt_and_decorate_addr(&bridge->addr)), + now); can_use_bridge_authority = !tor_digest_is_zero(bridge->identity) && num_bridge_auths; @@ -779,8 +804,12 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache) if (bridge) { /* if we actually want to use this one */ node_t *node; /* it's here; schedule its re-fetch for a long time from now. */ - if (!from_cache) + if (!from_cache) { + /* This schedules the re-fetch at a constant interval, which produces + * a pattern of bridge traffic. But it's better than trying all + * configured briges several times in the first few minutes. */ download_status_reset(&bridge->fetch_status); + } node = node_get_mutable_by_id(ri->cache_info.identity_digest); tor_assert(node); @@ -812,10 +841,12 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache) * We use this function to decide if we're ready to start building * circuits through our bridges, or if we need to wait until the * directory "server/authority" requests finish. */ -int -any_bridge_descriptors_known(void) +MOCK_IMPL(int, +any_bridge_descriptors_known, (void)) { - tor_assert(get_options()->UseBridges); + if (BUG(!get_options()->UseBridges)) { + return 0; + } if (!bridge_list) return 0; |