[or-cvs] let introcircs receive acks. rend streams now deal correctl...

Roger Dingledine arma at seul.org
Tue Apr 13 22:56:26 UTC 2004


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/home2/arma/work/onion/cvs/src/or

Modified Files:
	circuit.c connection_edge.c or.h rendclient.c 
Log Message:
let introcircs receive acks. rend streams now deal correctly again.
(i think)


Index: circuit.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuit.c,v
retrieving revision 1.206
retrieving revision 1.207
diff -u -d -r1.206 -r1.207
--- circuit.c	13 Apr 2004 17:16:47 -0000	1.206
+++ circuit.c	13 Apr 2004 22:56:24 -0000	1.207
@@ -275,9 +275,10 @@
   if(purpose == CIRCUIT_PURPOSE_C_REND_JOINED && !must_be_open) {
     if(circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
        circ->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
+       circ->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED &&
        circ->purpose != CIRCUIT_PURPOSE_C_REND_JOINED)
       return 0;
-  } else if (purpose == CIRCUIT_PURPOSE_C_INTRODUCING) {
+  } else if (purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT && !must_be_open) {
     if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCING &&
         circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
       return 0;
@@ -311,8 +312,10 @@
         return 0;
       }
     } else { /* not general */
-      if(rend_cmp_service_ids(conn->rend_query, circ->rend_query)) {
-        /* this circ is not for this conn */
+      if(rend_cmp_service_ids(conn->rend_query, circ->rend_query) &&
+         (circ->rend_query[0] || purpose != CIRCUIT_PURPOSE_C_REND_JOINED)) {
+        /* this circ is not for this conn, and it's not suitable
+         * for cannibalizing either */
         return 0;
       }
     }
@@ -340,9 +343,9 @@
           return 1;
       }
       break;
-    case CIRCUIT_PURPOSE_C_INTRODUCING:
-      /* more recently created is best */
-      if(a->timestamp_created > b->timestamp_created)
+    case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
+      /* the closer it is to ack_wait the better it is */
+      if(a->purpose > b->purpose)
         return 1;
       break;
     case CIRCUIT_PURPOSE_C_REND_JOINED:
@@ -356,25 +359,28 @@
 
 /* Find the best circ that conn can use, preferably one which is
  * dirty. Circ must not be too old.
- * If !conn, return newest.
+ * conn must be defined.
  *
  * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN.
  *
  * circ_purpose specifies what sort of circuit we must have.
- * It can be C_GENERAL, C_INTRODUCING, or C_REND_JOINED.
+ * It can be C_GENERAL, C_INTRODUCE_ACK_WAIT, or C_REND_JOINED.
  *
  * If it's REND_JOINED and must_be_open==0, then return the closest
  * rendezvous-purposed circuit that you can find.
  *
- * If circ_purpose is not GENERAL, then conn must be defined.
+ * If it's INTRODUCE_ACK_WAIT and must_be_open==0, then return the
+ * closest introduce-purposed circuit that you can find.
  */
 circuit_t *circuit_get_best(connection_t *conn,
                             int must_be_open, uint8_t purpose) {
   circuit_t *circ, *best=NULL;
   time_t now = time(NULL);
 
+  assert(conn);
+
   assert(purpose == CIRCUIT_PURPOSE_C_GENERAL ||
-         purpose == CIRCUIT_PURPOSE_C_INTRODUCING ||
+         purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT ||
          purpose == CIRCUIT_PURPOSE_C_REND_JOINED);
 
   for (circ=global_circuitlist;circ;circ = circ->next) {
@@ -391,6 +397,18 @@
   return best;
 }
 
+circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose) {
+  circuit_t *circ;
+
+  for (circ = global_circuitlist; circ; circ = circ->next) {
+    if (!circ->marked_for_close &&
+        circ->purpose == purpose &&
+        !rend_cmp_service_ids(rend_query, circ->rend_query))
+      return circ;
+  }
+  return NULL;
+}
+
 /* Return the first circuit in global_circuitlist after 'start' whose
  * rend_pk_digest field is 'digest' and whose purpose is purpose. Returns
  * NULL if no circuit is found.  If 'start' is null, begin at the start of

Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_edge.c,v
retrieving revision 1.159
retrieving revision 1.160
diff -u -d -r1.159 -r1.160
--- connection_edge.c	13 Apr 2004 18:44:42 -0000	1.159
+++ connection_edge.c	13 Apr 2004 22:56:24 -0000	1.160
@@ -806,7 +806,7 @@
     char *exitname=NULL;
     uint8_t new_circ_purpose;
 
-    if(desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCING) {
+    if(desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
       /* need to pick an intro point */
       exitname = rend_client_get_random_intro(conn->rend_query);
       if(!exitname) {
@@ -823,6 +823,8 @@
 
     if(desired_circuit_purpose == CIRCUIT_PURPOSE_C_REND_JOINED)
       new_circ_purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
+    else if(desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
+      new_circ_purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
     else
       new_circ_purpose = desired_circuit_purpose;
 
@@ -893,16 +895,13 @@
   } else { /* we're a rendezvous conn */
     circuit_t *rendcirc=NULL, *introcirc=NULL;
 
-    /* before anything else, see if we've already been attached
-     * to a rendezvous circuit */
-    if(conn->cpath_layer) {
-      return 1;
-    }
+    assert(!conn->cpath_layer);
 
-    /* else, start by finding a rendezvous circuit for us */
+    /* start by finding a rendezvous circuit for us */
 
     retval = circuit_get_open_circ_or_launch(conn, CIRCUIT_PURPOSE_C_REND_JOINED, &rendcirc);
     if(retval < 0) return -1; /* failed */
+    assert(rendcirc);
 
     if(retval > 0) {
       /* one is already established, attach */
@@ -913,36 +912,41 @@
       return 1;
     }
 
-    if(rendcirc &&
-       rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY &&
-       rendcirc->build_state->pending_final_cpath) {
-      log_fn(LOG_INFO,"pending-join circ already here. reusing.");
-      link_apconn_to_circ(conn, rendcirc);
-      /* don't send the begin, because we're still waiting for contact from bob */
-      return 1;
+    if(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) {
+      log_fn(LOG_INFO,"pending-join circ already here, with intro ack. Stalling.");
+      return 0;
     }
 
     /* it's on its way. find an intro circ. */
-    retval = circuit_get_open_circ_or_launch(conn, CIRCUIT_PURPOSE_C_INTRODUCING, &introcirc);
+    retval = circuit_get_open_circ_or_launch(conn, CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT, &introcirc);
     if(retval < 0) return -1; /* failed */
+    assert(introcirc);
 
     if(retval > 0) {
-      log_fn(LOG_INFO,"Intro circ is ready for us");
-      if(rendcirc &&
-         rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
-        /* then we know !pending_final_cpath, from above */
-        log_fn(LOG_INFO,"intro and rend circs are both ready. introducing.");
-        /* this call marks introcirc for close */
+      /* one has already sent the intro. keep waiting. */
+      log_fn(LOG_INFO,"Intro circ present and awaiting ack. Stalling.");
+      return 0;
+    }
+
+    /* now both rendcirc and introcirc are defined, and neither is finished */
+
+    if(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
+      log_fn(LOG_INFO,"ready rend circ already here (no intro-ack yet).");
+      /* look around for any new intro circs that should introduce */
+
+      assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
+      if(introcirc->state == CIRCUIT_STATE_OPEN) {
+        log_fn(LOG_INFO,"found open intro circ; sending introduction.");
+        /* XXX here we should cannibalize the rend circ if it's a zero service id */
         if(rend_client_send_introduction(introcirc, rendcirc) < 0) {
           return -1;
         }
-        /* now attach conn to rendcirc */
-        link_apconn_to_circ(conn, rendcirc);
         if(!rendcirc->timestamp_dirty)
           rendcirc->timestamp_dirty = time(NULL);
-        return 1;
+        return 0;
       }
     }
+
     log_fn(LOG_INFO,"Intro and rend circs are not both ready. Stalling conn.");
     return 0;
   }

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.317
retrieving revision 1.318
diff -u -d -r1.317 -r1.318
--- or.h	13 Apr 2004 17:16:47 -0000	1.317
+++ or.h	13 Apr 2004 22:56:24 -0000	1.318
@@ -209,10 +209,12 @@
  *   circuits that are c_establish_rend are either on their way
  *     to becoming open, or they are open and have sent the
  *     establish_rendezvous cell but haven't received an ack.
- *   circuits that are c_rend_ready are open and have received an
- *     ack, but haven't heard from bob yet. if they have a
+ *   circuits that are c_rend_ready are open and have received a
+ *     rend ack, but haven't heard from bob yet. if they have a
  *     buildstate->pending_final_cpath then they're expecting a
  *     cell from bob, else they're not.
+ *   circuits that are c_rend_ready_intro_acked are open, and
+ *     some intro circ has sent its intro and received an ack.
  *   circuits that are c_rend_joined are open, have heard from
  *     bob, and are talking to him.
  */
@@ -222,14 +224,15 @@
 
 #define CIRCUIT_PURPOSE_C_ESTABLISH_REND 8 /* at Alice, waiting for ack */
 #define CIRCUIT_PURPOSE_C_REND_READY 9 /* at Alice, waiting for Bob */
-#define CIRCUIT_PURPOSE_C_REND_JOINED 10 /* at Alice, rendezvous established */
+#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED 10 /* at Alice, waiting for Bob */
+#define CIRCUIT_PURPOSE_C_REND_JOINED 11 /* at Alice, rendezvous established */
 
-#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 11 /* at Bob, waiting for introductions */
-#define CIRCUIT_PURPOSE_S_INTRO 12 /* at Bob, successfully established intro */
-#define CIRCUIT_PURPOSE_S_CONNECT_REND 13 /* at Bob, connecting to rend point */
+#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 12 /* at Bob, waiting for introductions */
+#define CIRCUIT_PURPOSE_S_INTRO 13 /* at Bob, successfully established intro */
+#define CIRCUIT_PURPOSE_S_CONNECT_REND 14 /* at Bob, connecting to rend point */
 
-#define CIRCUIT_PURPOSE_S_REND_JOINED 14 /* at Bob, rendezvous established.*/
-#define _CIRCUIT_PURPOSE_MAX 14
+#define CIRCUIT_PURPOSE_S_REND_JOINED 15 /* at Bob, rendezvous established.*/
+#define _CIRCUIT_PURPOSE_MAX 15
 
 #define CIRCUIT_PURPOSE_IS_ORIGIN(p) ((p)>_CIRCUIT_PURPOSE_OR_MAX)
 #define CIRCUIT_IS_ORIGIN(c) (CIRCUIT_PURPOSE_IS_ORIGIN((c)->purpose))
@@ -685,6 +688,7 @@
 circuit_t *circuit_get_by_conn(connection_t *conn);
 circuit_t *circuit_get_best(connection_t *conn,
                             int must_be_open, uint8_t purpose);
+circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose);
 circuit_t *circuit_get_next_by_pk_and_purpose(circuit_t *circuit,
                                               const char *servid, uint8_t purpose);
 circuit_t *circuit_get_rendezvous(const char *cookie);
@@ -1038,7 +1042,7 @@
 int rend_client_receive_rendezvous(circuit_t *circ, const char *request, int request_len);
 void rend_client_desc_fetched(char *query, int success);
 
-int rend_cmp_service_ids(char *one, char *two);
+int rend_cmp_service_ids(const char *one, const char *two);
 char *rend_client_get_random_intro(char *query);
 int rend_parse_rendezvous_address(char *address);
 

Index: rendclient.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rendclient.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- rendclient.c	13 Apr 2004 05:20:52 -0000	1.35
+++ rendclient.c	13 Apr 2004 22:56:24 -0000	1.36
@@ -8,16 +8,11 @@
 void
 rend_client_introcirc_is_open(circuit_t *circ)
 {
-  circuit_t *rendcirc = NULL;
   assert(circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
   assert(CIRCUIT_IS_ORIGIN(circ) && circ->cpath);
 
   log_fn(LOG_INFO,"introcirc is open");
   connection_ap_attach_pending();
-  while ((rendcirc = circuit_get_next_by_pk_and_purpose(
-            rendcirc, circ->rend_pk_digest, CIRCUIT_PURPOSE_C_REND_READY))) {
-    rend_client_send_introduction(circ, rendcirc);
-  }
 }
 
 /* send the establish-rendezvous cell. if it fails, mark
@@ -154,6 +149,7 @@
   int i, r;
   rend_cache_entry_t *ent;
   char *nickname;
+  circuit_t *rendcirc;
 
   if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
     log_fn(LOG_WARN, "Received REND_INTRODUCE_ACK on unexpected circuit %d",
@@ -166,7 +162,15 @@
 
   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. */
+    /* Locate the rend circ which is waiting to hear about this ack,
+     * and tell it.
+     */
+    rendcirc = circuit_get_by_rend_query_and_purpose(
+               circ->rend_query, CIRCUIT_PURPOSE_C_REND_READY);
+    if(rendcirc) { /* remember the ack */
+      rendcirc->purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
+    }
+    /* close the circuit: we won't need it anymore. */
     circuit_mark_for_close(circ);
   } else {
     /* It's a NAK; the introduction point didn't relay our request. */
@@ -305,13 +309,6 @@
 
   onion_append_to_cpath(&circ->cpath, hop);
   circ->build_state->pending_final_cpath = NULL; /* prevent double-free */
-
-  for(apconn = circ->p_streams; apconn; apconn = apconn->next_stream) {
-    apconn->cpath_layer = circ->cpath->prev;
-    /* now the last hop is different. be sure to send all the way. */
-    if(connection_ap_handshake_send_begin(apconn, circ) < 0)
-      return -1;
-  }
   return 0;
  err:
   circuit_mark_for_close(circ);
@@ -356,7 +353,7 @@
   }
 }
 
-int rend_cmp_service_ids(char *one, char *two) {
+int rend_cmp_service_ids(const char *one, const char *two) {
   return strcasecmp(one,two);
 }
 



More information about the tor-commits mailing list