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
This commit is contained in:
Roger Dingledine 2007-11-04 00:15:42 +00:00
parent 8cc70addd7
commit e9af56cf2f
4 changed files with 77 additions and 30 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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);