summaryrefslogtreecommitdiff
path: root/src/or/directory.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/directory.c')
-rw-r--r--src/or/directory.c64
1 files changed, 52 insertions, 12 deletions
diff --git a/src/or/directory.c b/src/or/directory.c
index a3e575ac97..11dce8ca71 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* failed, int was_ei);
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,25 @@ 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* failed, int was_ei)
+{
+ char digest[DIGEST_LEN];
+ tor_assert(!was_ei); /* 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);
+ });
+}
+
/** Called when an attempt to download one or more router descriptors
* or extra-info documents on connection <b>conn</b> failed.
*/
@@ -662,6 +685,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)
+{
+ int was_ei;
+ 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 + 3,
+ which, NULL, 0);
+
+ was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
+ if (smartlist_len(which)) {
+ connection_dir_retry_bridges(which, was_ei);
+ 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)
@@ -3498,18 +3548,8 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
time_t now = time(NULL);
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);
- });
- }
+ if (router_purpose == ROUTER_PURPOSE_BRIDGE)
+ connection_dir_retry_bridges(failed, was_extrainfo);
return; /* FFFF should implement for other-than-router-purpose someday */
}
SMARTLIST_FOREACH(failed, const char *, cp,