aboutsummaryrefslogtreecommitdiff
path: root/src/or/bridges.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/bridges.c')
-rw-r--r--src/or/bridges.c61
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;