]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Retry non-final-hop rendezvous failures
authorNick Mathewson <nickm@torproject.org>
Wed, 14 Apr 2004 21:40:50 +0000 (21:40 +0000)
committerNick Mathewson <nickm@torproject.org>
Wed, 14 Apr 2004 21:40:50 +0000 (21:40 +0000)
svn:r1625

doc/TODO
src/or/circuit.c
src/or/or.h
src/or/rendservice.c

index 49d313cdfea0d51103d56d4dbb85c5ed55bdb913..7119feea759b641ba5c91547083d25e47b1c50e6 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -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?
 
index d0fc81fec7a80378656626dfaadba90c54ed2c17..6099a8360f4418b3058631268b328fbb1ca2195e 100644 (file)
@@ -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
index d91cd1207ddd9a2c0879fdb5aa34a6c86c1e1fe7..8bb41f6d9ffb626f1d75219545132dcb64d3f478 100644 (file)
@@ -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);
 
index e7f787e4cd80d081f6c25970dc83dc3724fdf592..0c92d1d9181c7273ce82d22c618c832f0026fd38 100644 (file)
@@ -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