diff options
author | Roger Dingledine <arma@torproject.org> | 2007-11-04 00:15:42 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2007-11-04 00:15:42 +0000 |
commit | e9af56cf2f3adc88e11280d2e6fafc3ce6d0f371 (patch) | |
tree | b548fa06bc3da6533f9c855fb6a12103f6f7c298 | |
parent | 8cc70addd7a33b266eba946203f373c5a8cfadc6 (diff) | |
download | tor-e9af56cf2f3adc88e11280d2e6fafc3ce6d0f371.tar.gz tor-e9af56cf2f3adc88e11280d2e6fafc3ce6d0f371.zip |
If bridge users set UpdateBridgesFromAuthority, but the digest
they ask for is a 404 from the bridge authority, they now fall
back to trying the bridge directly.
svn:r12368
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 78 | ||||
-rw-r--r-- | src/or/directory.c | 21 | ||||
-rw-r--r-- | src/or/or.h | 1 |
4 files changed, 77 insertions, 30 deletions
@@ -50,6 +50,13 @@ Changes in version 0.2.0.10-alpha - 2007-11-0? fix for bug 535. - Make the "not enough dir info yet" message better. + o Minor features (bridges): + - If bridge users set UpdateBridgesFromAuthority, but the digest + they ask for is a 404 from the bridge authority, they now fall + back to trying the bridge directly. + - Bridges now use begin_dir to publish their server descriptor to + the bridge authority, even when they haven't set TunnelDirConns. + o Minor features (controller): - When reporting clock skew, and we only have a lower bound on the amount of skew, amount anyway, marked as a lower bound. diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 9dc0bfd87b..761bcfe6a2 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -2825,20 +2825,6 @@ clear_bridge_list(void) smartlist_clear(bridge_list); } -#if 0 -/** Return 1 if <b>digest</b> is one of our known bridges. */ -int -identity_digest_is_a_bridge(const char *digest) -{ - SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, - { - if (!memcmp(bridge->identity, digest, DIGEST_LEN)) - return 1; - }); - return 0; -} -#endif - /** Return a bridge pointer if <b>ri</b> is one of our known bridges * (either by comparing keys if possible, else by comparing addr/port). * Else return NULL. */ @@ -2902,6 +2888,52 @@ bridge_fetch_status_arrived(bridge_info_t *bridge, time_t now) bridge->fetch_status.n_download_failures = 0; } +/** If <b>digest</b> is one of our known bridges, return it. */ +static bridge_info_t * +find_bridge_by_digest(char *digest) +{ + SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, + { + if (!memcmp(bridge->identity, digest, DIGEST_LEN)) + return bridge; + }); + return NULL; +} + +/** We need to ask <b>bridge</b> for its server descriptor. <b>address</b> + * is a helpful string describing this bridge. */ +static void +launch_direct_bridge_descriptor_fetch(char *address, bridge_info_t *bridge) +{ + if (connection_get_by_type_addr_port_purpose( + CONN_TYPE_DIR, bridge->addr, bridge->port, + DIR_PURPOSE_FETCH_SERVERDESC)) + return; /* it's already on the way */ + directory_initiate_command(address, bridge->addr, + bridge->port, 0, + 1, bridge->identity, + DIR_PURPOSE_FETCH_SERVERDESC, + ROUTER_PURPOSE_BRIDGE, + 0, "authority.z", NULL, 0, 0); +} + +/** Fetching the bridge descriptor from the bridge authority returned a + * "not found". Fall back to trying a direct fetch. */ +void +retry_bridge_descriptor_fetch_directly(char *digest) +{ + bridge_info_t *bridge = find_bridge_by_digest(digest); + char address_buf[INET_NTOA_BUF_LEN+1]; + struct in_addr in; + + if (!bridge) + return; /* not found? oh well. */ + + in.s_addr = htonl(bridge->addr); + tor_inet_ntoa(&in, address_buf, sizeof(address_buf)); + launch_direct_bridge_descriptor_fetch(address_buf, bridge); +} + /** For each bridge in our list for which we don't currently have a * descriptor, fetch a new copy of its descriptor -- either directly * from the bridge or via a bridge authority. */ @@ -2941,21 +2973,15 @@ fetch_bridge_descriptors(time_t now) "firewall policy. %s.", address_buf, bridge->port, num_bridge_auths ? "Asking bridge authority instead" : "Skipping"); - ask_bridge_directly = 0; + if (num_bridge_auths) + ask_bridge_directly = 0; + else + continue; } if (ask_bridge_directly) { - if (!connection_get_by_type_addr_port_purpose( - CONN_TYPE_DIR, bridge->addr, bridge->port, - DIR_PURPOSE_FETCH_SERVERDESC)) { - /* we need to ask the bridge itself for its descriptor. */ - directory_initiate_command(address_buf, bridge->addr, - bridge->port, 0, - 1, bridge->identity, - DIR_PURPOSE_FETCH_SERVERDESC, - ROUTER_PURPOSE_BRIDGE, - 0, "authority.z", NULL, 0, 0); - } + /* we need to ask the bridge itself for its descriptor. */ + launch_direct_bridge_descriptor_fetch(address_buf, bridge); } else { /* We have a digest and we want to ask an authority. We could * combine all the requests into one, but that may give more diff --git a/src/or/directory.c b/src/or/directory.c index c9b0de0ea9..778632922f 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -52,6 +52,7 @@ static void dir_networkstatus_download_failed(smartlist_t *failed, int status_code); static void dir_routerdesc_download_failed(smartlist_t *failed, int status_code, + int router_purpose, int was_extrainfo, int was_descriptor_digests); static void note_request(const char *key, size_t bytes); @@ -1582,6 +1583,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) connection_dir_download_routerdesc_failed(conn); } else { dir_routerdesc_download_failed(which, status_code, + conn->router_purpose, was_ei, descriptor_digests); SMARTLIST_FOREACH(which, char *, cp, tor_free(cp)); smartlist_free(which); @@ -1621,6 +1623,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) conn->_base.address, (int)conn->_base.port); if (smartlist_len(which)) { dir_routerdesc_download_failed(which, status_code, + conn->router_purpose, was_ei, descriptor_digests); } SMARTLIST_FOREACH(which, char *, cp, tor_free(cp)); @@ -2968,16 +2971,26 @@ download_status_reset(download_status_t *dls) * either as descriptor digests or as identity digests based on * <b>was_descriptor_digests</b>). */ -void +static void dir_routerdesc_download_failed(smartlist_t *failed, int status_code, + int router_purpose, int was_extrainfo, int was_descriptor_digests) { char digest[DIGEST_LEN]; time_t now = time(NULL); or_options_t *options = get_options(); int server = server_mode(options) && dirserver_mode(options); - if (!was_descriptor_digests) - return; /* FFFF should implement this someday */ + if (!was_descriptor_digests) { + if (router_purpose == ROUTER_PURPOSE_BRIDGE) { + tor_assert(!was_extrainfo); /* not supported yet */ + SMARTLIST_FOREACH(failed, const char *, cp, + { + base16_decode(digest, DIGEST_LEN, cp, strlen(cp)); + retry_bridge_descriptor_fetch_directly(digest); + }); + } + return; /* FFFF should implement for other-than-router-purpose someday */ + } SMARTLIST_FOREACH(failed, const char *, cp, { download_status_t *dls = NULL; @@ -2996,7 +3009,7 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code, }); /* No need to relaunch descriptor downloads here: we already do it - * every 10 seconds (DESCRIPTOR_RETRY_INTERVAL) in main.c. */ + * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */ } /** Given a directory <b>resource</b> request, containing zero diff --git a/src/or/or.h b/src/or/or.h index f6c80ce96c..c7a788ddaa 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2425,6 +2425,7 @@ int getinfo_helper_entry_guards(control_connection_t *conn, void clear_bridge_list(void); int routerinfo_is_a_configured_bridge(routerinfo_t *ri); void bridge_add_from_config(uint32_t addr, uint16_t port, char *digest); +void retry_bridge_descriptor_fetch_directly(char *digest); void fetch_bridge_descriptors(time_t now); void learned_bridge_descriptor(routerinfo_t *ri); int any_bridge_descriptors_known(void); |