if an intro circ waiting for an ack dies before getting one, then

count it as a nack


svn:r1665
This commit is contained in:
Roger Dingledine 2004-04-18 07:37:16 +00:00
parent 8d86f8abf5
commit 3fa2925a6a
4 changed files with 89 additions and 67 deletions

View File

@ -997,6 +997,13 @@ int _circuit_mark_for_close(circuit_t *circ) {
circuit_build_failed(circ); /* take actions if necessary */ circuit_build_failed(circ); /* take actions if necessary */
circuit_rep_hist_note_result(circ); circuit_rep_hist_note_result(circ);
} }
if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
assert(circ->state == CIRCUIT_STATE_OPEN);
/* treat this like getting a nack from it */
log_fn(LOG_INFO,"Failed intro circ %s to %s (awaiting ack). Removing from descriptor.",
circ->rend_query, circ->build_state->chosen_exit);
rend_client_remove_intro_point(circ->build_state->chosen_exit, circ->rend_query);
}
if(circ->n_conn) if(circ->n_conn)
connection_send_destroy(circ->n_circ_id, circ->n_conn); connection_send_destroy(circ->n_circ_id, circ->n_conn);

View File

@ -757,14 +757,7 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
return connection_ap_handshake_attach_circuit(conn); return connection_ap_handshake_attach_circuit(conn);
} else { } else {
conn->state = AP_CONN_STATE_RENDDESC_WAIT; conn->state = AP_CONN_STATE_RENDDESC_WAIT;
if(connection_get_by_type_rendquery(CONN_TYPE_DIR, conn->rend_query)) { rend_client_refetch_renddesc(conn->rend_query);
log_fn(LOG_INFO,"Would fetch a new renddesc here (for %s), but one is already in progress.", conn->rend_query);
} else {
/* not one already; initiate a dir rend desc lookup */
directory_initiate_command(router_pick_directory_server(),
DIR_PURPOSE_FETCH_RENDDESC,
conn->rend_query, strlen(conn->rend_query));
}
return 0; return 0;
} }
} }

View File

@ -1043,6 +1043,8 @@ void rep_hist_dump_stats(time_t now, int severity);
void rend_client_introcirc_is_open(circuit_t *circ); void rend_client_introcirc_is_open(circuit_t *circ);
void rend_client_rendcirc_is_open(circuit_t *circ); void rend_client_rendcirc_is_open(circuit_t *circ);
int rend_client_introduction_acked(circuit_t *circ, const char *request, int request_len); int rend_client_introduction_acked(circuit_t *circ, const char *request, int request_len);
void rend_client_refetch_renddesc(char *query);
int rend_client_remove_intro_point(char *failed_intro, char *query);
int rend_client_rendezvous_acked(circuit_t *circ, const char *request, int request_len); int rend_client_rendezvous_acked(circuit_t *circ, const char *request, int request_len);
int rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request_len); int rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request_len);
void rend_client_desc_fetched(char *query, int success); void rend_client_desc_fetched(char *query, int success);

View File

@ -147,8 +147,6 @@ int
rend_client_introduction_acked(circuit_t *circ, rend_client_introduction_acked(circuit_t *circ,
const char *request, int request_len) const char *request, int request_len)
{ {
int i, r;
rend_cache_entry_t *ent;
char *nickname; char *nickname;
circuit_t *rendcirc; circuit_t *rendcirc;
@ -177,71 +175,93 @@ rend_client_introduction_acked(circuit_t *circ,
} else { } else {
/* It's a NAK; the introduction point didn't relay our request. */ /* It's a NAK; the introduction point didn't relay our request. */
circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING; circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
/* XXXX /* Remove this intro point from the set of viable introduction
* Now become non-open, extend to another one of Bob's * points. If any remain, extend to a new one and try again.
* introduction points, and try again. Maybe mark the service as * If none remain, refetch the service descriptor.
* non-functional at the first intro point somehow?
*
* Or re-fetch the service descriptor? Hm....
*/ */
r = rend_cache_lookup_entry(circ->rend_query, &ent); if(rend_client_remove_intro_point(circ->build_state->chosen_exit,
if (r<0) { circ->rend_query) > 0) {
log_fn(LOG_WARN, "Malformed service ID '%s'", circ->rend_query); /* There are introduction points left. re-extend the circuit to
return -1;
}
if (r>0) {
/* Okay, we found the right service desc. First, remove this intro point
* from the parsed descriptor (if it's still there!)
*/
for (i=0; i < ent->parsed->n_intro_points; ++i) {
if (!strcasecmp(ent->parsed->intro_points[i],
circ->build_state->chosen_exit)) {
tor_free(ent->parsed->intro_points[i]);
ent->parsed->intro_points[i] =
ent->parsed->intro_points[--ent->parsed->n_intro_points];
break;
}
}
/* If there are any introduction points left, re-extend the circuit to
* another intro point and try again. */ * another intro point and try again. */
if (ent->parsed->n_intro_points) { nickname = rend_client_get_random_intro(circ->rend_query);
nickname = rend_client_get_random_intro(circ->rend_query); assert(nickname);
assert(nickname); log_fn(LOG_INFO,"Got nack for %s from %s, extending to %s.", circ->rend_query, circ->build_state->chosen_exit, nickname);
if (!router_get_by_nickname(nickname)) { if (!router_get_by_nickname(nickname)) {
log_fn(LOG_WARN, "Advertised intro point '%s' for %s is not known. Closing.", log_fn(LOG_WARN, "Advertised intro point '%s' for %s is not known. Closing.",
nickname, circ->rend_query); nickname, circ->rend_query);
circuit_mark_for_close(circ); circuit_mark_for_close(circ);
return -1; return -1;
} }
log_fn(LOG_INFO, "Chose new intro point %s for %s (circ %d, %d choices left)", log_fn(LOG_INFO, "Chose new intro point %s for %s (circ %d)",
nickname, circ->rend_query, circ->n_circ_id, ent->parsed->n_intro_points); nickname, circ->rend_query, circ->n_circ_id);
circ->state = CIRCUIT_STATE_BUILDING; circ->state = CIRCUIT_STATE_BUILDING;
tor_free(circ->build_state->chosen_exit); tor_free(circ->build_state->chosen_exit);
circ->build_state->chosen_exit = tor_strdup(nickname); circ->build_state->chosen_exit = tor_strdup(nickname);
++circ->build_state->desired_path_len; ++circ->build_state->desired_path_len;
if (circuit_send_next_onion_skin(circ)<0) { if (circuit_send_next_onion_skin(circ)<0) {
log_fn(LOG_WARN, "Couldn't extend circuit to new intro point."); log_fn(LOG_WARN, "Couldn't extend circuit to new intro point.");
circuit_mark_for_close(circ); circuit_mark_for_close(circ);
return -1; return -1;
}
return 0;
} }
}
/* Either we have no service desc, or all the intro points in that
* descriptor failed. So re-fetch the descriptor and try again. */
circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
/* XXX anything else we need to do to circ? */
/* Refetch descriptor */
if(!connection_get_by_type_rendquery(CONN_TYPE_DIR, circ->rend_query)) {
/* not one already; initiate a dir rend desc lookup */
directory_initiate_command(router_pick_directory_server(),
DIR_PURPOSE_FETCH_RENDDESC,
circ->rend_query, strlen(circ->rend_query));
} }
} }
return 0; return 0;
} }
void
rend_client_refetch_renddesc(char *query)
{
if(connection_get_by_type_rendquery(CONN_TYPE_DIR, query)) {
log_fn(LOG_INFO,"Would fetch a new renddesc here (for %s), but one is already in progress.", query);
} else {
/* not one already; initiate a dir rend desc lookup */
directory_initiate_command(router_pick_directory_server(),
DIR_PURPOSE_FETCH_RENDDESC,
query, strlen(query));
}
}
/* remove failed_intro from ent. if ent now has no intro points, or
* service is unrecognized, then launch a new renddesc fetch.
*
* Return -1 if error, 0 if no intro points remain or service
* unrecognized, 1 if recognized and some intro points remain.
*/
int
rend_client_remove_intro_point(char *failed_intro, char *query)
{
int i, r;
rend_cache_entry_t *ent;
r = rend_cache_lookup_entry(query, &ent);
if (r<0) {
log_fn(LOG_WARN, "Malformed service ID '%s'", query);
return -1;
}
if (r==0) {
log_fn(LOG_INFO, "Unknown service %s. Re-fetching descriptor.", query);
rend_client_refetch_renddesc(query);
return 0;
}
for (i=0; i < ent->parsed->n_intro_points; ++i) {
if (!strcasecmp(ent->parsed->intro_points[i], failed_intro)) {
tor_free(ent->parsed->intro_points[i]);
ent->parsed->intro_points[i] =
ent->parsed->intro_points[--ent->parsed->n_intro_points];
break;
}
}
if(!ent->parsed->n_intro_points) {
log_fn(LOG_INFO,"No more intro points remain for %s. Re-fetching descriptor.", query);
rend_client_refetch_renddesc(query);
return 0;
}
log_fn(LOG_INFO,"%d options left for %s.", ent->parsed->n_intro_points, query);
return 1;
}
/* Called when we receive a RENDEZVOUS_ESTABLISHED cell; changes the state of /* Called when we receive a RENDEZVOUS_ESTABLISHED cell; changes the state of
* the circuit to C_REND_READY. * the circuit to C_REND_READY.
*/ */