summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2004-04-13 02:31:52 +0000
committerNick Mathewson <nickm@torproject.org>2004-04-13 02:31:52 +0000
commite53ba59250834f9d5ae8f17adc585446a8b2e2d6 (patch)
tree6742b47a0d4bf659534e563a70c54cb6f923b8ba
parent8483bace6591836d289e55d42f6c2fd94e806aa5 (diff)
downloadtor-e53ba59250834f9d5ae8f17adc585446a8b2e2d6.tar.gz
tor-e53ba59250834f9d5ae8f17adc585446a8b2e2d6.zip
Handle introduce naks. Arma: Is this right?
svn:r1602
-rw-r--r--src/or/rendclient.c61
1 files changed, 59 insertions, 2 deletions
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 5fba33006f..fb4543aedd 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -143,6 +143,10 @@ int
rend_client_introduction_acked(circuit_t *circ,
const char *request, int request_len)
{
+ int i;
+ rend_cache_entry_t *ent;
+ char *nickname;
+
if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
log_fn(LOG_WARN, "Recieved REND_INTRODUCE_ACK on unexpected circuit %d",
circ->n_circ_id);
@@ -150,6 +154,8 @@ rend_client_introduction_acked(circuit_t *circ,
return -1;
}
+ assert(circ->build_state->chosen_exit);
+
if (request_len == 0) {
/* It's an ACK; the introduction point relayed our introduction request. */
/* So close the circuit; we won't need it any more. */
@@ -163,9 +169,60 @@ rend_client_introduction_acked(circuit_t *circ,
* non-functional at the first intro point somehow?
*
* Or re-fetch the service descriptor? Hm....
- *
- * XXXX writeme
*/
+ i = rend_cache_lookup_entry(circ->rend_query, &ent);
+ if (i<0) {
+ log_fn(LOG_WARN, "Malformed service ID '%s'", circ->rend_query);
+ return -1;
+ }
+ if (i>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. */
+ if (ent->parsed->n_intro_points) {
+ nickname = rend_client_get_random_intro(circ->rend_query);
+ assert(nickname);
+ if (!router_get_by_nickname(nickname)) {
+ log_fn(LOG_WARN, "Advertised intro point '%s' is not known. Closing.",
+ nickname);
+ circuit_mark_for_close(circ);
+ return -1;
+ }
+ log_fn(LOG_INFO, "Chose new intro point %s for %s (circ %d)",
+ nickname, circ->rend_query, circ->n_circ_id);
+ circ->state = CIRCUIT_STATE_BUILDING;
+ tor_free(circ->build_state->chosen_exit);
+ circ->build_state->chosen_exit = tor_strdup(nickname);
+ ++circ->build_state->desired_path_len;
+ if (circuit_send_next_onion_skin(circ)<0) {
+ log_fn(LOG_WARN, "Couldn't extend circuit to new intro point.");
+ circuit_mark_for_close(circ);
+ 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. */
+ /* XXXX What do we do to this circ in the meantime? */
+ /* 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;
}