mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
timeout and retry schedules for fetching bridge descriptors
svn:r10867
This commit is contained in:
parent
5c4d86f512
commit
50487c249d
4
doc/TODO
4
doc/TODO
@ -238,7 +238,7 @@ N - Design/implement the "local-status" or something like it, from the
|
||||
manually listed in the torrc.
|
||||
D and some mechanism for specifying that we want to stop using
|
||||
a given bridge in this cache.
|
||||
- timeout and retry schedules for fetching bridge descriptors
|
||||
o timeout and retry schedules for fetching bridge descriptors
|
||||
- give extend_info_t a router_purpose again
|
||||
o react faster to download networkstatuses after the first bridge
|
||||
descriptor arrives
|
||||
@ -247,7 +247,7 @@ N - Design/implement the "local-status" or something like it, from the
|
||||
- Bridges operators (rudimentary version)
|
||||
- Ability to act as dir cache without a dir port.
|
||||
o Bridges publish to bridge authorities
|
||||
- Fix BEGIN_DIR so that you connect to bridge of which you only
|
||||
o Fix BEGIN_DIR so that you connect to bridge of which you only
|
||||
know IP (and optionally fingerprint), and then use BEGIN_DIR to learn
|
||||
more about it.
|
||||
- look at server_mode() and decide if it always applies to bridges too.
|
||||
|
@ -2668,6 +2668,7 @@ typedef struct {
|
||||
uint32_t addr;
|
||||
uint16_t port;
|
||||
char identity[DIGEST_LEN];
|
||||
download_status_t fetch_status;
|
||||
} bridge_info_t;
|
||||
|
||||
/** A list of known bridges. */
|
||||
@ -2697,21 +2698,28 @@ identity_digest_is_a_bridge(const char *digest)
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Return 1 if <b>ri</b> is one of our known bridges (either by
|
||||
* comparing keys if possible, else by comparing addr/port). */
|
||||
int
|
||||
routerinfo_is_a_bridge(routerinfo_t *ri)
|
||||
/** 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. */
|
||||
static bridge_info_t *
|
||||
routerinfo_get_configured_bridge(routerinfo_t *ri)
|
||||
{
|
||||
SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge,
|
||||
{
|
||||
if (tor_digest_is_zero(bridge->identity) &&
|
||||
bridge->addr == ri->addr && bridge->port == ri->or_port)
|
||||
return 1;
|
||||
return bridge;
|
||||
if (!memcmp(bridge->identity, ri->cache_info.identity_digest,
|
||||
DIGEST_LEN))
|
||||
return 1;
|
||||
return bridge;
|
||||
});
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
routerinfo_is_a_configured_bridge(routerinfo_t *ri)
|
||||
{
|
||||
return routerinfo_get_configured_bridge(ri) ? 1 : 0;
|
||||
}
|
||||
|
||||
/** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b>
|
||||
@ -2729,11 +2737,34 @@ bridge_add_from_config(uint32_t addr, uint16_t port, char *digest)
|
||||
smartlist_add(bridge_list, b);
|
||||
}
|
||||
|
||||
/** Schedule the next fetch for <b>bridge</b>, based on
|
||||
* some retry schedule. */
|
||||
static void
|
||||
bridge_fetch_status_increment(bridge_info_t *bridge, time_t now)
|
||||
{
|
||||
switch (bridge->fetch_status.n_download_failures) {
|
||||
case 0: bridge->fetch_status.next_attempt_at = now+60*15; break;
|
||||
case 1: bridge->fetch_status.next_attempt_at = now+60*15; break;
|
||||
default: bridge->fetch_status.next_attempt_at = now+60*60; break;
|
||||
}
|
||||
if (bridge->fetch_status.n_download_failures < 10)
|
||||
bridge->fetch_status.n_download_failures++;
|
||||
}
|
||||
|
||||
/** We just got a new descriptor for <b>bridge</b>. Reschedule the
|
||||
* next fetch for a long time from <b>now</b>. */
|
||||
static void
|
||||
bridge_fetch_status_arrived(bridge_info_t *bridge, time_t now)
|
||||
{
|
||||
bridge->fetch_status.next_attempt_at = now+60*60;
|
||||
bridge->fetch_status.n_download_failures = 0;
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
void
|
||||
fetch_bridge_descriptors(void)
|
||||
fetch_bridge_descriptors(time_t now)
|
||||
{
|
||||
char address_buf[INET_NTOA_BUF_LEN+1];
|
||||
struct in_addr in;
|
||||
@ -2746,8 +2777,12 @@ fetch_bridge_descriptors(void)
|
||||
|
||||
SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge,
|
||||
{
|
||||
if (router_get_by_digest(bridge->identity))
|
||||
continue; /* we've already got one. great. */
|
||||
if (bridge->fetch_status.next_attempt_at >= now)
|
||||
continue; /* don't bother, no need to retry yet */
|
||||
|
||||
/* schedule another fetch as if this one failed, in case it does */
|
||||
bridge_fetch_status_increment(bridge, now);
|
||||
|
||||
in.s_addr = htonl(bridge->addr);
|
||||
tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
|
||||
|
||||
@ -2792,16 +2827,22 @@ learned_bridge_descriptor(routerinfo_t *ri)
|
||||
tor_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE);
|
||||
if (get_options()->UseBridges) {
|
||||
int first = !any_bridge_descriptors_known();
|
||||
bridge_info_t *bridge = routerinfo_get_configured_bridge(ri);
|
||||
time_t now = time(NULL);
|
||||
ri->is_running = 1;
|
||||
|
||||
/* it's here; schedule its re-fetch for a long time from now. */
|
||||
bridge_fetch_status_arrived(bridge, now);
|
||||
|
||||
add_an_entry_guard(ri, 1);
|
||||
log_notice(LD_DIR, "new bridge descriptor '%s'", ri->nickname);
|
||||
if (first)
|
||||
routerlist_retry_directory_downloads(time(NULL));
|
||||
routerlist_retry_directory_downloads(now);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return 1 if any of our entry guards have descriptors that
|
||||
* are marked with purpose 'bridge'. Else return 0.
|
||||
* are marked with purpose 'bridge' and are running. Else return 0.
|
||||
*
|
||||
* We use this function to decide if we're ready to start building
|
||||
* circuits through our bridges, or if we need to wait until the
|
||||
@ -2810,19 +2851,30 @@ int
|
||||
any_bridge_descriptors_known(void)
|
||||
{
|
||||
return choose_random_entry(NULL)!=NULL ? 1 : 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Return 1 if we have at least one descriptor for a bridge and
|
||||
* all descriptors we know are down. Else return 0. */
|
||||
int
|
||||
all_bridges_down(void)
|
||||
{
|
||||
routerinfo_t *ri;
|
||||
int any_known = 0;
|
||||
if (!entry_guards)
|
||||
entry_guards = smartlist_create();
|
||||
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e,
|
||||
{
|
||||
ri = router_get_by_digest(e->identity);
|
||||
if (ri && ri->purpose == ROUTER_PURPOSE_BRIDGE)
|
||||
return 1;
|
||||
if (ri && ri->purpose == ROUTER_PURPOSE_BRIDGE) {
|
||||
any_known = 1;
|
||||
if (ri->is_running)
|
||||
return 0; /* some bridge is both known and running */
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
#endif
|
||||
return any_known;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Release all storage held by the list of entry guards and related
|
||||
* memory structs. */
|
||||
|
@ -881,16 +881,16 @@ run_scheduled_events(time_t now)
|
||||
|
||||
if (time_to_try_getting_descriptors < now) {
|
||||
/* XXXX Maybe we should do this every 10sec when not enough info,
|
||||
* and every 60sec when we have enough info -NM */
|
||||
* and every 60sec when we have enough info -NM Great idea -RD */
|
||||
update_router_descriptor_downloads(now);
|
||||
update_extrainfo_downloads(now);
|
||||
if (options->UseBridges)
|
||||
fetch_bridge_descriptors(now);
|
||||
time_to_try_getting_descriptors = now + DESCRIPTOR_RETRY_INTERVAL;
|
||||
}
|
||||
|
||||
if (time_to_reset_descriptor_failures < now) {
|
||||
router_reset_descriptor_download_failures();
|
||||
if (options->UseBridges)
|
||||
fetch_bridge_descriptors(); /* XXX get this its own retry schedule -RD */
|
||||
time_to_reset_descriptor_failures =
|
||||
now + DESCRIPTOR_FAILURE_RESET_INTERVAL;
|
||||
}
|
||||
|
@ -2231,15 +2231,16 @@ int entry_guards_parse_state(or_state_t *state, int set, char **msg);
|
||||
void entry_guards_update_state(or_state_t *state);
|
||||
int getinfo_helper_entry_guards(control_connection_t *conn,
|
||||
const char *question, char **answer);
|
||||
void entry_guards_free_all(void);
|
||||
|
||||
void clear_bridge_list(void);
|
||||
int routerinfo_is_a_bridge(routerinfo_t *ri);
|
||||
int routerinfo_is_a_configured_bridge(routerinfo_t *ri);
|
||||
void bridge_add_from_config(uint32_t addr, uint16_t port, char *digest);
|
||||
void fetch_bridge_descriptors(void);
|
||||
void fetch_bridge_descriptors(time_t now);
|
||||
void learned_bridge_descriptor(routerinfo_t *ri);
|
||||
int any_bridge_descriptors_known(void);
|
||||
|
||||
void entry_guards_free_all(void);
|
||||
|
||||
/********************************* circuitlist.c ***********************/
|
||||
|
||||
circuit_t * _circuit_get_global_list(void);
|
||||
|
@ -2413,7 +2413,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
|
||||
* we are receiving in response to a fetch. */
|
||||
|
||||
if (!signed_desc_digest_is_recognized(&router->cache_info) &&
|
||||
!routerinfo_is_a_bridge(router)) {
|
||||
!routerinfo_is_a_configured_bridge(router)) {
|
||||
/* We asked for it, so some networkstatus must have listed it when we
|
||||
* did. Save it if we're a cache in case somebody else asks for it. */
|
||||
log_info(LD_DIR,
|
||||
|
Loading…
Reference in New Issue
Block a user