Add a new GUARD_WAIT state for circuits

This state corresponds to the WAITING_FOR_BETTER_GUARD state; it's
for circuits that are 100% constructed, but which we won't use until
we are sure that we wouldn't use circuits with a better guard.
This commit is contained in:
Nick Mathewson 2016-11-21 16:59:00 -05:00
parent 36e9fbd752
commit 238828c92b
3 changed files with 25 additions and 6 deletions

View File

@ -439,7 +439,13 @@ circuit_set_state(circuit_t *circ, uint8_t state)
/* add to waiting-circuit list. */
smartlist_add(circuits_pending_chans, circ);
}
if (state == CIRCUIT_STATE_OPEN)
if (circ->state == CIRCUIT_STATE_GUARD_WAIT) {
smartlist_remove(circuits_pending_other_guards, circ);
}
if (state == CIRCUIT_STATE_GUARD_WAIT) {
smartlist_add(circuits_pending_other_guards, circ);
}
if (state == CIRCUIT_STATE_GUARD_WAIT || state == CIRCUIT_STATE_OPEN)
tor_assert(!circ->n_chan_create_cell);
circ->state = state;
}
@ -542,6 +548,8 @@ circuit_state_to_string(int state)
case CIRCUIT_STATE_BUILDING: return "doing handshakes";
case CIRCUIT_STATE_ONIONSKIN_PENDING: return "processing the onion";
case CIRCUIT_STATE_CHAN_WAIT: return "connecting to server";
case CIRCUIT_STATE_GUARD_WAIT: return "waiting to see how other "
"guards perform";
case CIRCUIT_STATE_OPEN: return "open";
default:
log_warn(LD_BUG, "Unknown circuit state %d", state);
@ -1868,7 +1876,8 @@ circuit_about_to_free(circuit_t *circ)
* module then. If it isn't OPEN, we send it there now to remember which
* links worked and which didn't.
*/
if (circ->state != CIRCUIT_STATE_OPEN) {
if (circ->state != CIRCUIT_STATE_OPEN &&
circ->state != CIRCUIT_STATE_GUARD_WAIT) {
if (CIRCUIT_IS_ORIGIN(circ)) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
circuit_build_failed(ocirc); /* take actions if necessary */
@ -1881,7 +1890,9 @@ circuit_about_to_free(circuit_t *circ)
}
if (CIRCUIT_IS_ORIGIN(circ)) {
control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
(circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED,
(circ->state == CIRCUIT_STATE_OPEN ||
circ->state == CIRCUIT_STATE_GUARD_WAIT) ?
CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED,
orig_reason);
}
@ -2403,7 +2414,8 @@ assert_circuit_ok(const circuit_t *c)
tor_assert(c->deliver_window >= 0);
tor_assert(c->package_window >= 0);
if (c->state == CIRCUIT_STATE_OPEN) {
if (c->state == CIRCUIT_STATE_OPEN ||
c->state == CIRCUIT_STATE_GUARD_WAIT) {
tor_assert(!c->n_chan_create_cell);
if (or_circ) {
tor_assert(or_circ->n_crypto);

View File

@ -2596,6 +2596,8 @@ getinfo_helper_events(control_connection_t *control_conn,
if (circ->base_.state == CIRCUIT_STATE_OPEN)
state = "BUILT";
else if (circ->base_.state == CIRCUIT_STATE_GUARD_WAIT)
state = "GUARD_WAIT"; // XXXX prop271 must specify this.
else if (circ->cpath)
state = "EXTENDED";
else
@ -3379,7 +3381,8 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
goto done;
}
} else {
if (circ->base_.state == CIRCUIT_STATE_OPEN) {
if (circ->base_.state == CIRCUIT_STATE_OPEN ||
circ->base_.state == CIRCUIT_STATE_GUARD_WAIT) {
int err_reason = 0;
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {

View File

@ -438,8 +438,12 @@ typedef enum {
/** Circuit state: I'd like to deliver a create, but my n_chan is still
* connecting. */
#define CIRCUIT_STATE_CHAN_WAIT 2
/** Circuit state: the circuit is open but we don't want to actually use it
* until we find out if a better guard will be available.
*/
#define CIRCUIT_STATE_GUARD_WAIT 3
/** Circuit state: onionskin(s) processed, ready to send/receive cells. */
#define CIRCUIT_STATE_OPEN 3
#define CIRCUIT_STATE_OPEN 4
#define CIRCUIT_PURPOSE_MIN_ 1