generalize choose_random_entry()'s dirinfo parameter

Now we can specify to skip bridges that wouldn't be able to answer the
type of dir fetch we're launching.

It's still the responsibility of the rest of the code to prevent us from
launching a given dir fetch if we have no bridges that could handle it.
This commit is contained in:
Roger Dingledine 2012-01-25 20:49:32 -05:00 committed by Andrea Shepard
parent a8297cdbd3
commit bce5019eff
4 changed files with 28 additions and 23 deletions

View File

@ -3373,7 +3373,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
(purpose != CIRCUIT_PURPOSE_TESTING || options->BridgeRelay)) { (purpose != CIRCUIT_PURPOSE_TESTING || options->BridgeRelay)) {
/* This request is for an entry server to use for a regular circuit, /* This request is for an entry server to use for a regular circuit,
* and we use entry guard nodes. Just return one of the guard nodes. */ * and we use entry guard nodes. Just return one of the guard nodes. */
return choose_random_entry(state, 0); return choose_random_entry(state, NO_DIRINFO);
} }
excluded = smartlist_new(); excluded = smartlist_new();

View File

@ -472,14 +472,13 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
if (options->UseBridges && type != BRIDGE_DIRINFO) { if (options->UseBridges && type != BRIDGE_DIRINFO) {
/* We want to ask a running bridge for which we have a descriptor. /* We want to ask a running bridge for which we have a descriptor.
* *
* When we ask choose_random_entry() for a bridge, we specify that * When we ask choose_random_entry() for a bridge, we specify what
* we're going to be using it for a dir fetch: if any of our bridges * sort of dir fetch we'll be doing, so it won't return a bridge
* can handle microdescriptor questions, we'll get one of the ones * that can't answer our question.
* that can.
*/ */
/* XXX024 Not all bridges handle conditional consensus downloading, /* XXX024 Not all bridges handle conditional consensus downloading,
* so, for now, never assume the server supports that. -PP */ * so, for now, never assume the server supports that. -PP */
const node_t *node = choose_random_entry(NULL, 1); const node_t *node = choose_random_entry(NULL, type);
if (node && node->ri) { if (node && node->ri) {
/* every bridge has a routerinfo. */ /* every bridge has a routerinfo. */
tor_addr_t addr; tor_addr_t addr;

View File

@ -64,8 +64,7 @@ static int entry_guards_dirty = 0;
static void bridge_free(bridge_info_t *bridge); static void bridge_free(bridge_info_t *bridge);
static const node_t *choose_random_entry_impl(cpath_build_state_t *state, static const node_t *choose_random_entry_impl(cpath_build_state_t *state,
int for_directory, int for_directory,
dirinfo_type_t dirtype, dirinfo_type_t dirtype);
int prefer_microdescs);
/** Return the list of entry guards, creating it if necessary. */ /** Return the list of entry guards, creating it if necessary. */
const smartlist_t * const smartlist_t *
@ -844,20 +843,28 @@ node_understands_microdescriptors(const node_t *node)
return 0; return 0;
} }
/** Return true iff <b>node</b> is able to answer directory questions
* of type <b>dirinfo</b>. */
static int
node_can_handle_dirinfo(const node_t *node, dirinfo_type_t dirinfo)
{
if ((dirinfo & MICRODESC_DIRINFO) &&
!node_understands_microdescriptors(node))
return 0;
return 1;
}
/** Pick a live (up and listed) entry guard from entry_guards. If /** Pick a live (up and listed) entry guard from entry_guards. If
* <b>state</b> is non-NULL, this is for a specific circuit -- * <b>state</b> is non-NULL, this is for a specific circuit --
* make sure not to pick this circuit's exit or any node in the * make sure not to pick this circuit's exit or any node in the
* exit's family. If <b>state</b> is NULL, we're looking for a random * exit's family. If <b>state</b> is NULL, we're looking for a random
* guard (likely a bridge). * guard (likely a bridge). If <b>dirinfo</b> is not NO_DIRINFO, then
* * only select from nodes that know how to answer directory questions
* If the prefer_microdescs flag is set, we are looking for a bridge to * of that type. */
* use for directory fetching and pick a bridge that supports microdescriptors
* if we know any that do so.
*/
const node_t * const node_t *
choose_random_entry(cpath_build_state_t *state, int prefer_microdescs) choose_random_entry(cpath_build_state_t *state, dirinfo_type_t dirinfo)
{ {
return choose_random_entry_impl(state, 0, 0, prefer_microdescs); return choose_random_entry_impl(state, 0, dirinfo);
} }
/** Pick a live (up and listed) directory guard from entry_guards for /** Pick a live (up and listed) directory guard from entry_guards for
@ -865,13 +872,13 @@ choose_random_entry(cpath_build_state_t *state, int prefer_microdescs)
const node_t * const node_t *
choose_random_dirguard(dirinfo_type_t type) choose_random_dirguard(dirinfo_type_t type)
{ {
return choose_random_entry_impl(NULL, 1, type, 0); return choose_random_entry_impl(NULL, 1, type);
} }
/** Helper for choose_random{entry,dirguard}. */ /** Helper for choose_random{entry,dirguard}. */
static const node_t * static const node_t *
choose_random_entry_impl(cpath_build_state_t *state, int for_directory, choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
dirinfo_type_t dirinfo_type, int prefer_microdescs) dirinfo_type_t dirinfo_type)
{ {
const or_options_t *options = get_options(); const or_options_t *options = get_options();
smartlist_t *live_entry_guards = smartlist_new(); smartlist_t *live_entry_guards = smartlist_new();
@ -923,9 +930,8 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory,
continue; /* don't pick the same node for entry and exit */ continue; /* don't pick the same node for entry and exit */
if (consider_exit_family && smartlist_contains(exit_family, node)) if (consider_exit_family && smartlist_contains(exit_family, node))
continue; /* avoid relays that are family members of our exit */ continue; /* avoid relays that are family members of our exit */
if (prefer_microdescs && if (dirinfo_type != NO_DIRINFO &&
we_use_microdescriptors_for_circuits(options) && !node_can_handle_dirinfo(node, dirinfo_type))
!node_understands_microdescriptors(node))
continue; /* this node won't be able to answer our dir questions */ continue; /* this node won't be able to answer our dir questions */
#if 0 /* since EntryNodes is always strict now, this clause is moot */ #if 0 /* since EntryNodes is always strict now, this clause is moot */
if (options->EntryNodes && if (options->EntryNodes &&
@ -2006,7 +2012,7 @@ int
any_bridge_descriptors_known(void) any_bridge_descriptors_known(void)
{ {
tor_assert(get_options()->UseBridges); tor_assert(get_options()->UseBridges);
return choose_random_entry(NULL, 0)!=NULL ? 1 : 0; return choose_random_entry(NULL, NO_DIRINFO)!=NULL ? 1 : 0;
} }
/** Return 1 if there are any directory conns fetching bridge descriptors /** Return 1 if there are any directory conns fetching bridge descriptors

View File

@ -79,7 +79,7 @@ int entry_guard_register_connect_status(const char *digest, int succeeded,
void entry_nodes_should_be_added(void); void entry_nodes_should_be_added(void);
int entry_list_is_constrained(const or_options_t *options); int entry_list_is_constrained(const or_options_t *options);
const node_t *choose_random_entry(cpath_build_state_t *state, const node_t *choose_random_entry(cpath_build_state_t *state,
int prefer_microdescs); dirinfo_type_t dirinfo);
const node_t *choose_random_dirguard(dirinfo_type_t t); const node_t *choose_random_dirguard(dirinfo_type_t t);
int entry_guards_parse_state(or_state_t *state, int set, char **msg); int entry_guards_parse_state(or_state_t *state, int set, char **msg);
void entry_guards_update_state(or_state_t *state); void entry_guards_update_state(or_state_t *state);