summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2010-09-12 21:41:45 -0400
committerNick Mathewson <nickm@torproject.org>2010-09-12 21:41:45 -0400
commit126832a3f7249d6508d3c1d73158b1593f219fa7 (patch)
tree5557b46fd4c96faea4517b0b2e336b097d142615
parentcc0efa808409ddce6dda1d7670da83bf7c0a5b05 (diff)
parent5634e0330283e76aa4e7411ee6d8bef6f71d01a6 (diff)
downloadtor-126832a3f7249d6508d3c1d73158b1593f219fa7.tar.gz
tor-126832a3f7249d6508d3c1d73158b1593f219fa7.zip
Merge branch 'bug1138'
-rw-r--r--changes/bug11385
-rw-r--r--src/or/directory.c61
2 files changed, 56 insertions, 10 deletions
diff --git a/changes/bug1138 b/changes/bug1138
new file mode 100644
index 0000000000..ffb83bd4be
--- /dev/null
+++ b/changes/bug1138
@@ -0,0 +1,5 @@
+ o Major bugfixes:
+ - Fall back to direct descriptor request to bridges when
+ requests to authorities fail due to a network error.
+ Bugfix in 0.2.1.19, closes bug 1138.
+
diff --git a/src/or/directory.c b/src/or/directory.c
index e9fcb5ee17..97ee0c9fbc 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -67,8 +67,10 @@ static void http_set_address_origin(const char *headers, connection_t *conn);
static void connection_dir_download_networkstatus_failed(
dir_connection_t *conn, int status_code);
static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
+static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn);
static void connection_dir_download_cert_failed(
dir_connection_t *conn, int status_code);
+static void connection_dir_retry_bridges(smartlist_t *descs);
static void dir_networkstatus_download_failed(smartlist_t *failed,
int status_code);
static void dir_routerdesc_download_failed(smartlist_t *failed,
@@ -592,6 +594,8 @@ connection_dir_request_failed(dir_connection_t *conn)
conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
conn->_base.address);
+ if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
+ connection_dir_bridge_routerdesc_failed(conn);
connection_dir_download_routerdesc_failed(conn);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
networkstatus_consensus_download_failed(0);
@@ -645,6 +649,24 @@ connection_dir_download_networkstatus_failed(dir_connection_t *conn,
}
}
+/** Helper: Attempt to fetch directly the descriptors of each bridge
+ * listed in <b>failed</b>.
+ */
+static void
+connection_dir_retry_bridges(smartlist_t *descs)
+{
+ char digest[DIGEST_LEN];
+ SMARTLIST_FOREACH(descs, const char *, cp,
+ {
+ if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
+ log_warn(LD_BUG, "Malformed fingerprint in list: %s",
+ escaped(cp));
+ continue;
+ }
+ retry_bridge_descriptor_fetch_directly(digest);
+ });
+}
+
/** Called when an attempt to download one or more router descriptors
* or extra-info documents on connection <b>conn</b> failed.
*/
@@ -662,6 +684,33 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn)
(void) conn;
}
+/** Called when an attempt to download a bridge's routerdesc from
+ * one of the authorities failed due to a network error. If
+ * possible attempt to download descriptors from the bridge directly.
+ */
+static void
+connection_dir_bridge_routerdesc_failed(dir_connection_t *conn)
+{
+ smartlist_t *which = NULL;
+
+ /* Requests for bridge descriptors are in the form 'fp/', so ignore
+ anything else. */
+ if (!conn->requested_resource || strcmpstart(conn->requested_resource,"fp/"))
+ return;
+
+ which = smartlist_create();
+ dir_split_resource_into_fingerprints(conn->requested_resource
+ + strlen("fp/"),
+ which, NULL, 0);
+
+ tor_assert(conn->_base.purpose != DIR_PURPOSE_FETCH_EXTRAINFO);
+ if (smartlist_len(which)) {
+ connection_dir_retry_bridges(which);
+ SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
+ }
+ smartlist_free(which);
+}
+
/** Called when an attempt to fetch a certificate fails. */
static void
connection_dir_download_cert_failed(dir_connection_t *conn, int status)
@@ -3499,16 +3548,8 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
int server = directory_fetches_from_authorities(get_options());
if (!was_descriptor_digests) {
if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
- tor_assert(!was_extrainfo); /* not supported yet */
- SMARTLIST_FOREACH(failed, const char *, cp,
- {
- if (base16_decode(digest, DIGEST_LEN, cp, strlen(cp))<0) {
- log_warn(LD_BUG, "Malformed fingerprint in list: %s",
- escaped(cp));
- continue;
- }
- retry_bridge_descriptor_fetch_directly(digest);
- });
+ tor_assert(!was_extrainfo);
+ connection_dir_retry_bridges(failed);
}
return; /* FFFF should implement for other-than-router-purpose someday */
}