diff options
-rw-r--r-- | doc/TODO | 2 | ||||
-rw-r--r-- | src/or/circuit.c | 17 | ||||
-rw-r--r-- | src/or/or.h | 3 | ||||
-rw-r--r-- | src/or/rendservice.c | 38 |
4 files changed, 57 insertions, 3 deletions
@@ -161,7 +161,7 @@ Rendezvous service: - cannibalize general circs? D how to set up multiple locations for a hidden service? o make bob publish only established intro circs? - - when bob tries to connect to alice's chosen rend point, but + o when bob tries to connect to alice's chosen rend point, but can't, but it's not the fault of the last hop in the rend circ, then he should retry? diff --git a/src/or/circuit.c b/src/or/circuit.c index d0fc81fec..6099a8360 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -1253,7 +1253,14 @@ static void circuit_build_failed(circuit_t *circ) { /* we should examine circ and see if it failed because of * the last hop or an earlier hop. then use this info below. */ - //int failed_at_last_hop; + int failed_at_last_hop = 0; + /* If the last hop isn't open, and the second-to-last is, we failed + * at the last hop. */ + if (circ->cpath && + circ->cpath->prev->state != CPATH_STATE_OPEN && + circ->cpath->prev->prev->state == CPATH_STATE_OPEN) { + failed_at_last_hop = 1; + } switch(circ->purpose) { case CIRCUIT_PURPOSE_C_GENERAL: @@ -1291,7 +1298,13 @@ static void circuit_build_failed(circuit_t *circ) { /* at Bob, connecting to rend point */ /* Don't increment failure count, since Alice may have picked * the rendezvous point maliciously */ - log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s. Sucks to be Alice.", circ->build_state->chosen_exit); + if (failed_at_last_hop) { + log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s. Sucks to be Alice.", circ->build_state->chosen_exit); + } else { + log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s, because an earlier node failed.", + circ->build_state->chosen_exit); + rend_service_relaunch_rendezvous(circ); + } break; default: /* Other cases are impossible, since this function is only called with diff --git a/src/or/or.h b/src/or/or.h index d91cd1207..8bb41f6d9 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -500,6 +500,8 @@ typedef struct { char *chosen_exit; /* cpath to append after rendezvous. */ struct crypt_path_t *pending_final_cpath; + /* How many times has building a circuit for this task failed? */ + int failure_count; } cpath_build_state_t; /* struct for a path (circuit) through the network */ @@ -1095,6 +1097,7 @@ void rend_service_intro_is_ready(circuit_t *circuit); int rend_service_intro_established(circuit_t *circuit, const char *request, int request_len); void rend_service_rendezvous_is_ready(circuit_t *circuit); int rend_service_introduce(circuit_t *circuit, const char *request, int request_len); +void rend_service_relaunch_rendezvous(circuit_t *oldcirc); int rend_service_set_connection_addr_port(connection_t *conn, circuit_t *circ); void rend_service_dump_stats(int severity); diff --git a/src/or/rendservice.c b/src/or/rendservice.c index e7f787e4c..0c92d1d91 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -457,6 +457,44 @@ rend_service_introduce(circuit_t *circuit, const char *request, int request_len) return -1; } +#define MAX_REND_FAILURES 3 +void +rend_service_relaunch_rendezvous(circuit_t *oldcirc) +{ + circuit_t *newcirc; + cpath_build_state_t *newstate, *oldstate; + + /* XXXX assert type and build_state */ + + if (!oldcirc->build_state || + oldcirc->build_state->failure_count > MAX_REND_FAILURES) { + log_fn(LOG_INFO,"Attempt to build circuit to %s for rendezvous has failed too many times; giving up.", + oldcirc->build_state->chosen_exit); + return; + } + + log_fn(LOG_INFO,"Reattempting rendezvous circuit to %s", + oldcirc->build_state->chosen_exit); + + newcirc = circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND, + oldcirc->build_state->chosen_exit); + if (!newcirc) { + log_fn(LOG_WARN,"Couldn't relaunch rendezvous circuit to %s", + oldcirc->build_state->chosen_exit); + return; + } + oldstate = oldcirc->build_state; + newstate = newcirc->build_state; + assert(newstate && oldstate); + newstate->failure_count = oldstate->failure_count+1; + newstate->pending_final_cpath = oldstate->pending_final_cpath; + oldstate->pending_final_cpath = NULL; + + memcpy(newcirc->rend_query, oldcirc->rend_query, REND_SERVICE_ID_LEN+1); + memcpy(newcirc->rend_pk_digest, oldcirc->rend_pk_digest, DIGEST_LEN); + memcpy(newcirc->rend_splice, oldcirc->rend_splice, REND_COOKIE_LEN); +} + /* Launch a circuit to serve as an introduction point. */ static int |