summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2007-11-04 00:15:42 +0000
committerRoger Dingledine <arma@torproject.org>2007-11-04 00:15:42 +0000
commite9af56cf2f3adc88e11280d2e6fafc3ce6d0f371 (patch)
treeb548fa06bc3da6533f9c855fb6a12103f6f7c298
parent8cc70addd7a33b266eba946203f373c5a8cfadc6 (diff)
downloadtor-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--ChangeLog7
-rw-r--r--src/or/circuitbuild.c78
-rw-r--r--src/or/directory.c21
-rw-r--r--src/or/or.h1
4 files changed, 77 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index f753484777..8050421556 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);