Split select_entry_guard_for_circuit()

This commit is contained in:
rl1987 2018-06-22 16:43:50 +03:00
parent e6c51a056c
commit 042d22c8d1

View File

@ -2027,31 +2027,23 @@ entry_guards_note_internet_connectivity(guard_selection_t *gs)
}
/**
* Get a guard for use with a circuit. Prefer to pick a running primary
* guard; then a non-pending running filtered confirmed guard; then a
* non-pending runnable filtered guard. Update the
* Pick a primary guard for use with a circuit, if available. Update the
* <b>last_tried_to_connect</b> time and the <b>is_pending</b> fields of the
* guard as appropriate. Set <b>state_out</b> to the new guard-state
* of the circuit.
*/
STATIC entry_guard_t *
select_entry_guard_for_circuit(guard_selection_t *gs,
guard_usage_t usage,
const entry_guard_restriction_t *rst,
unsigned *state_out)
static entry_guard_t *
select_primary_guard_for_circuit(guard_selection_t *gs,
guard_usage_t usage,
const entry_guard_restriction_t *rst,
unsigned *state_out)
{
const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC);
tor_assert(gs);
tor_assert(state_out);
if (!gs->primary_guards_up_to_date)
entry_guards_update_primary(gs);
entry_guard_t *chosen_guard = NULL;
int num_entry_guards = get_n_primary_guards_to_use(usage);
smartlist_t *usable_primary_guards = smartlist_new();
/* "If any entry in PRIMARY_GUARDS has {is_reachable} status of
<maybe> or <yes>, return the first such guard." */
SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) {
entry_guard_consider_retry(guard);
if (! entry_guard_obeys_restriction(guard, rst))
@ -2069,18 +2061,30 @@ select_entry_guard_for_circuit(guard_selection_t *gs,
} SMARTLIST_FOREACH_END(guard);
if (smartlist_len(usable_primary_guards)) {
entry_guard_t *guard = smartlist_choose(usable_primary_guards);
chosen_guard = smartlist_choose(usable_primary_guards);
smartlist_free(usable_primary_guards);
log_info(LD_GUARD, "Selected primary guard %s for circuit.",
entry_guard_describe(guard));
return guard;
entry_guard_describe(chosen_guard));
}
smartlist_free(usable_primary_guards);
/* "Otherwise, if the ordered intersection of {CONFIRMED_GUARDS}
and {USABLE_FILTERED_GUARDS} is nonempty, return the first
entry in that intersection that has {is_pending} set to
false." */
smartlist_free(usable_primary_guards);
return chosen_guard;
}
/**
* For use with a circuit, pick a non-pending running filtered confirmed guard,
* if one is available. Update the <b>last_tried_to_connect</b> time and the
* <b>is_pending</b> fields of the guard as appropriate. Set <b>state_out</b>
* to the new guard-state of the circuit.
*/
static entry_guard_t *
select_confirmed_guard_for_circuit(guard_selection_t *gs,
guard_usage_t usage,
const entry_guard_restriction_t *rst,
unsigned *state_out)
{
const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC);
SMARTLIST_FOREACH_BEGIN(gs->confirmed_entry_guards, entry_guard_t *, guard) {
if (guard->is_primary)
continue; /* we already considered this one. */
@ -2101,34 +2105,93 @@ select_entry_guard_for_circuit(guard_selection_t *gs,
}
} SMARTLIST_FOREACH_END(guard);
return NULL;
}
/**
* For use with a circuit, pick a confirmed usable filtered guard
* at random. Update the <b>last_tried_to_connect</b> time and the
* <b>is_pending</b> fields of the guard as appropriate. Set <b>state_out</b>
* to the new guard-state of the circuit.
*/
static entry_guard_t *
select_filtered_guard_for_circuit(guard_selection_t *gs,
guard_usage_t usage,
const entry_guard_restriction_t *rst,
unsigned *state_out)
{
const int need_descriptor = (usage == GUARD_USAGE_TRAFFIC);
entry_guard_t *chosen_guard = NULL;
unsigned flags = 0;
if (need_descriptor)
flags |= SAMPLE_EXCLUDE_NO_DESCRIPTOR;
chosen_guard = sample_reachable_filtered_entry_guards(gs,
rst,
SAMPLE_EXCLUDE_CONFIRMED |
SAMPLE_EXCLUDE_PRIMARY |
SAMPLE_EXCLUDE_PENDING |
flags);
if (!chosen_guard) {
return NULL;
}
chosen_guard->is_pending = 1;
chosen_guard->last_tried_to_connect = approx_time();
*state_out = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD;
log_info(LD_GUARD, "No primary or confirmed guards available. Selected "
"random guard %s for circuit. Will try other guards before "
"using this circuit.",
entry_guard_describe(chosen_guard));
return chosen_guard;
}
/**
* Get a guard for use with a circuit. Prefer to pick a running primary
* guard; then a non-pending running filtered confirmed guard; then a
* non-pending runnable filtered guard. Update the
* <b>last_tried_to_connect</b> time and the <b>is_pending</b> fields of the
* guard as appropriate. Set <b>state_out</b> to the new guard-state
* of the circuit.
*/
STATIC entry_guard_t *
select_entry_guard_for_circuit(guard_selection_t *gs,
guard_usage_t usage,
const entry_guard_restriction_t *rst,
unsigned *state_out)
{
entry_guard_t *chosen_guard = NULL;
tor_assert(gs);
tor_assert(state_out);
if (!gs->primary_guards_up_to_date)
entry_guards_update_primary(gs);
/* "If any entry in PRIMARY_GUARDS has {is_reachable} status of
<maybe> or <yes>, return the first such guard." */
chosen_guard = select_primary_guard_for_circuit(gs, usage, rst, state_out);
if (chosen_guard)
return chosen_guard;
/* "Otherwise, if the ordered intersection of {CONFIRMED_GUARDS}
and {USABLE_FILTERED_GUARDS} is nonempty, return the first
entry in that intersection that has {is_pending} set to
false." */
chosen_guard = select_confirmed_guard_for_circuit(gs, usage, rst, state_out);
if (chosen_guard)
return chosen_guard;
/* "Otherwise, if there is no such entry, select a member at
random from {USABLE_FILTERED_GUARDS}." */
{
entry_guard_t *guard;
unsigned flags = 0;
if (need_descriptor)
flags |= SAMPLE_EXCLUDE_NO_DESCRIPTOR;
guard = sample_reachable_filtered_entry_guards(gs,
rst,
SAMPLE_EXCLUDE_CONFIRMED |
SAMPLE_EXCLUDE_PRIMARY |
SAMPLE_EXCLUDE_PENDING |
flags);
if (guard == NULL) {
log_info(LD_GUARD, "Absolutely no sampled guards were available. "
"Marking all guards for retry and starting from top again.");
mark_all_guards_maybe_reachable(gs);
return NULL;
}
guard->is_pending = 1;
guard->last_tried_to_connect = approx_time();
*state_out = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD;
log_info(LD_GUARD, "No primary or confirmed guards available. Selected "
"random guard %s for circuit. Will try other guards before "
"using this circuit.",
entry_guard_describe(guard));
return guard;
chosen_guard = select_filtered_guard_for_circuit(gs, usage, rst, state_out);
if (chosen_guard == NULL) {
log_info(LD_GUARD, "Absolutely no sampled guards were available. "
"Marking all guards for retry and starting from top again.");
mark_all_guards_maybe_reachable(gs);
return NULL;
}
return chosen_guard;
}
/**