Add a backpointer from entry_guard_t to guard_selection_t

This is safe, because no entry_guard_t ever outlives its
guard_selection_t.

I want this because now that multiple guard selections can be active
during one tor session, we should make sure that any information we
register about guards is with respect to the selection that they came
from.
This commit is contained in:
Nick Mathewson 2016-11-28 10:50:36 -05:00
parent 404e9e5611
commit 6dcbc24a4e
2 changed files with 42 additions and 11 deletions

View File

@ -722,6 +722,7 @@ entry_guard_add_to_sample(guard_selection_t *gs,
guard->is_reachable = GUARD_REACHABLE_MAYBE;
smartlist_add(gs->sampled_entry_guards, guard);
guard->in_selection = gs;
entry_guard_set_filtered_flags(get_options(), gs, guard);
entry_guards_changed_for_guard_selection(gs);
return guard;
@ -1743,6 +1744,8 @@ entry_guard_succeeded(guard_selection_t *gs,
if (! guard)
return -1;
tor_assert(gs == guard->in_selection); // XXXX prop271 remove argument
unsigned newstate =
entry_guards_note_guard_success(gs, guard, (*guard_state_p)->state);
@ -1772,6 +1775,8 @@ entry_guard_cancel(guard_selection_t *gs,
if (! guard)
return;
tor_assert(gs == guard->in_selection); // XXXX prop271 remove argument
/* XXXX prop271 -- last_tried_to_connect_at will be erroneous here, but this
* function will only get called in "bug" cases anyway. */
guard->is_pending = 0;
@ -1798,6 +1803,8 @@ entry_guard_failed(guard_selection_t *gs,
if (! guard)
return;
tor_assert(gs == guard->in_selection); // XXXX prop271 remove argument
entry_guards_note_guard_failure(gs, guard);
(*guard_state_p)->state = GUARD_CIRC_STATE_DEAD;
@ -1876,7 +1883,7 @@ circ_state_has_higher_priority(origin_circuit_t *a,
}
/**
* Look at all of the origin_circuit_t * objects in <b>all_circuits</b>,
* Look at all of the origin_circuit_t * objects in <b>all_circuits_in</b>,
* and see if any of them that were previously not ready to use for
* guard-related reasons are now ready to use. Place those circuits
* in <b>newly_complete_out</b>, and mark them COMPLETE.
@ -1885,11 +1892,11 @@ circ_state_has_higher_priority(origin_circuit_t *a,
*/
int
entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
const smartlist_t *all_circuits,
const smartlist_t *all_circuits_in,
smartlist_t *newly_complete_out)
{
tor_assert(gs);
tor_assert(all_circuits);
tor_assert(all_circuits_in);
tor_assert(newly_complete_out);
if (! entry_guards_all_primary_guards_are_down(gs)) {
@ -1904,10 +1911,24 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
int n_complete = 0;
origin_circuit_t *best_waiting_circuit = NULL;
origin_circuit_t *best_complete_circuit = NULL;
SMARTLIST_FOREACH_BEGIN(all_circuits, origin_circuit_t *, circ) {
smartlist_t *all_circuits = smartlist_new();
SMARTLIST_FOREACH_BEGIN(all_circuits_in, origin_circuit_t *, circ) {
// We filter out circuits that aren't ours, or which we can't
// reason about.
circuit_guard_state_t *state = origin_circuit_get_guard_state(circ);
if (state == NULL)
continue;
entry_guard_t *guard = entry_guard_handle_get(state->guard);
if (!guard || guard->in_selection != gs)
continue;
smartlist_add(all_circuits, circ);
} SMARTLIST_FOREACH_END(circ);
SMARTLIST_FOREACH_BEGIN(all_circuits, origin_circuit_t *, circ) {
circuit_guard_state_t *state = origin_circuit_get_guard_state(circ);
if BUG((state == NULL))
continue;
if (state->state == GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD) {
++n_waiting;
@ -1927,7 +1948,7 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
if (! best_waiting_circuit) {
log_debug(LD_GUARD, "Considered upgrading guard-stalled circuits, "
"but didn't find any.");
return 0;
goto no_change;
}
if (best_complete_circuit) {
@ -1940,8 +1961,7 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
"%d complete and %d guard-stalled. At least one complete "
"circuit had higher priority, so not upgrading.",
n_complete, n_waiting);
return 0;
goto no_change;
}
}
@ -1959,7 +1979,7 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
approx_time() - get_nonprimary_guard_connect_timeout();
SMARTLIST_FOREACH_BEGIN(all_circuits, origin_circuit_t *, circ) {
circuit_guard_state_t *state = origin_circuit_get_guard_state(circ);
if (state == NULL)
if (BUG(state == NULL))
continue;
if (state->state != GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD)
continue;
@ -1973,7 +1993,7 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
"%d guard-stalled, but %d pending circuit(s) had higher "
"guard priority, so not upgrading.",
n_waiting, n_blockers_found);
return 0;
goto no_change;
}
/* Okay. We have a best waiting circuit, and we aren't waiting for
@ -1982,7 +2002,7 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
int n_succeeded = 0;
SMARTLIST_FOREACH_BEGIN(all_circuits, origin_circuit_t *, circ) {
circuit_guard_state_t *state = origin_circuit_get_guard_state(circ);
if (state == NULL)
if (BUG(state == NULL))
continue;
if (state->state != GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD)
continue;
@ -2001,7 +2021,12 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
n_waiting, n_complete, n_succeeded);
tor_assert_nonfatal(n_succeeded >= 1);
smartlist_free(all_circuits);
return 1;
no_change:
smartlist_free(all_circuits);
return 0;
}
/**
@ -2431,6 +2456,7 @@ entry_guards_load_guards_from_state(or_state_t *state, int set)
GS_TYPE_INFER, 1);
tor_assert(gs);
smartlist_add(gs->sampled_entry_guards, guard);
guard->in_selection = gs;
} else {
entry_guard_free(guard);
}
@ -2925,6 +2951,7 @@ add_an_entry_guard(guard_selection_t *gs,
smartlist_insert(gs->chosen_entry_guards, 0, entry);
else
smartlist_add(gs->chosen_entry_guards, entry);
entry->in_selection = gs;
control_event_guard(entry->nickname, entry->identity, "NEW");
control_event_guard_deferred();
@ -3127,6 +3154,7 @@ remove_all_entry_guards_for_guard_selection(guard_selection_t *gs)
void
remove_all_entry_guards(void)
{
// XXXX prop271 this function shouldn't exist, in the new order.
remove_all_entry_guards_for_guard_selection(get_guard_selection_info());
}
@ -4037,6 +4065,8 @@ entry_guards_parse_state_for_guard_selection(
smartlist_free(gs->chosen_entry_guards);
}
gs->chosen_entry_guards = new_entry_guards;
SMARTLIST_FOREACH(new_entry_guards, entry_guard_t *, e,
e->in_selection = gs);
/* XXX hand new_entry_guards to this func, and move it up a
* few lines, so we don't have to re-dirty it */
@ -4429,7 +4459,7 @@ guards_update_all(void)
if (curr_guard_context->type == GS_TYPE_LEGACY) {
entry_guards_compute_status(get_options(), approx_time());
} else {
if (entry_guards_update_all(get_guard_selection_info()))
if (entry_guards_update_all(curr_guard_context))
mark_circuits = 1;
}

View File

@ -125,6 +125,7 @@ struct entry_guard_t {
* Which selection does this guard belong to?
*/
char *selection_name;
guard_selection_t *in_selection;
/* ==== Non-persistent fields. */
/* == These are used by sampled guards */