[or-cvs] some of the infrastructure to let ORs connect on demand

Roger Dingledine arma at seul.org
Fri Jul 2 09:29:03 UTC 2004


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

Modified Files:
	circuitbuild.c circuitlist.c circuituse.c connection_or.c or.h 
	router.c 
Log Message:
some of the infrastructure to let ORs connect on demand


Index: circuitbuild.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuitbuild.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- circuitbuild.c	1 Jul 2004 23:13:04 -0000	1.4
+++ circuitbuild.c	2 Jul 2004 09:29:00 -0000	1.5
@@ -225,7 +225,8 @@
     circ->n_port = firsthop->or_port;
 
     if(!n_conn) { /* launch the connection */
-      n_conn = connection_or_connect(firsthop);
+      n_conn = connection_or_connect(firsthop->addr, firsthop->or_port,
+                                     firsthop->identity_digest);
       if(!n_conn) { /* connect failed, forget the whole thing */
         log_fn(LOG_INFO,"connect to firsthop failed. Closing.");
         circuit_mark_for_close(circ);
@@ -255,21 +256,33 @@
 /** Find circuits that are waiting on <b>or_conn</b> to become open,
  * if any, and get them to send their create cells forward.
  */
-void circuit_n_conn_open(connection_t *or_conn) {
+void circuit_n_conn_done(connection_t *or_conn, int success) {
   circuit_t *circ;
 
   for(circ=global_circuitlist;circ;circ = circ->next) {
     if (circ->marked_for_close)
       continue;
-    if(CIRCUIT_IS_ORIGIN(circ) && circ->n_addr == or_conn->addr && circ->n_port == or_conn->port) {
+    if(!circ->n_conn &&
+       circ->n_addr == or_conn->addr &&
+       circ->n_port == or_conn->port &&
+       !memcmp(or_conn->identity_digest, circ->n_conn_id_digest, DIGEST_LEN)) {
       tor_assert(circ->state == CIRCUIT_STATE_OR_WAIT);
-      log_fn(LOG_DEBUG,"Found circ %d, sending onion skin.", circ->n_circ_id);
-      circ->n_conn = or_conn;
-      if(circuit_send_next_onion_skin(circ) < 0) {
-        log_fn(LOG_INFO,"send_next_onion_skin failed; circuit marked for closing.");
+      if(!success) { /* or_conn failed; close circ */
+        log_fn(LOG_INFO,"or_conn failed. Closing circ.");
         circuit_mark_for_close(circ);
         continue;
-        /* XXX could this be bad, eg if next_onion_skin failed because conn died? */
+      }
+      log_fn(LOG_DEBUG,"Found circ %d, sending create cell.", circ->n_circ_id);
+      circ->n_conn = or_conn;
+      if(CIRCUIT_IS_ORIGIN(circ)) {
+        if(circuit_send_next_onion_skin(circ) < 0) {
+          log_fn(LOG_INFO,"send_next_onion_skin failed; circuit marked for closing.");
+          circuit_mark_for_close(circ);
+          continue;
+          /* XXX could this be bad, eg if next_onion_skin failed because conn died? */
+        }
+      } else {
+        /* XXX008 pull the create cell out of circ->onionskin, and send it */
       }
     }
   }
@@ -418,24 +431,38 @@
     n_conn = connection_twin_get_by_addr_port(circ->n_addr,circ->n_port);
     onionskin = cell->payload+RELAY_HEADER_SIZE+4+2;
   } else {
-    /* XXXX Roger: in this case, we should create the connnection if
-     * n_conn is null. */
     n_conn = connection_get_by_identity_digest(
                          cell->payload+RELAY_HEADER_SIZE+4+2,
                          CONN_TYPE_OR);
     onionskin = cell->payload+RELAY_HEADER_SIZE+4+2+DIGEST_LEN;
   }
 
-  if(!n_conn || n_conn->type != CONN_TYPE_OR) {
-    /* I've disabled making connections through OPs, but it's definitely
-     * possible here. I'm not sure if it would be a bug or a feature.
-     *
-     * Note also that this will close circuits where the onion has the same
+  if(!n_conn) { /* we should try to open a connection */
+     /* Note that this will close circuits where the onion has the same
      * router twice in a row in the path. I think that's ok.
      */
+    routerinfo_t *router;
     struct in_addr in;
     in.s_addr = htonl(circ->n_addr);
-    log_fn(LOG_INFO,"Next router (%s:%d) not connected. Closing.", inet_ntoa(in), circ->n_port);
+    log_fn(LOG_INFO,"Next router (%s:%d) not connected. Connecting.",
+           inet_ntoa(in), circ->n_port);
+
+    if (old_format) {
+      router = router_get_by_addr_port(circ->n_addr, circ->n_port);
+      if(!router) {
+        log_fn(LOG_INFO,"Next hop is an unknown router. Closing.");
+        circuit_mark_for_close(circ);
+        return 0;
+      }
+    } else { /* new format */
+      router = router_get_by_digest(cell->payload+RELAY_HEADER_SIZE+4+2);
+    }
+
+    /* XXX copy onionskin into circ->onionskin, get into the right
+     * state, launch an or conn to the right place.
+     *...
+     */
+
 #if 0 /* if we do truncateds, no need to kill circ */
     connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED,
                                  NULL, 0, NULL);

Index: circuitlist.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuitlist.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- circuitlist.c	2 Jun 2004 18:11:28 -0000	1.6
+++ circuitlist.c	2 Jul 2004 09:29:00 -0000	1.7
@@ -454,6 +454,8 @@
 
   if (c->n_conn)
     tor_assert(c->n_conn->type == CONN_TYPE_OR);
+    /* XXX008 have to memcpy id_digest when we attach n_conn */
+    tor_assert(!memcmp(c->n_conn->identity_digest, c->n_conn_id_digest, DIGEST_LEN));
   if (c->p_conn)
     tor_assert(c->p_conn->type == CONN_TYPE_OR);
   for (conn = c->p_streams; conn; conn = conn->next_stream)

Index: circuituse.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuituse.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- circuituse.c	17 Jun 2004 18:13:09 -0000	1.3
+++ circuituse.c	2 Jul 2004 09:29:00 -0000	1.4
@@ -393,7 +393,11 @@
 
   switch(conn->type) {
     case CONN_TYPE_OR:
-      /* We must close all the circuits on it. */
+      if(conn->state != OR_CONN_STATE_OPEN) {
+        /* Inform any pending (not attached) circs that they should give up. */
+        circuit_n_conn_done(conn, 0);
+      }
+      /* Now close all the attached circuits on it. */
       while((circ = circuit_get_by_conn(conn))) {
         if(circ->n_conn == conn) /* it's closing in front of us */
           circ->n_conn = NULL;

Index: connection_or.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_or.c,v
retrieving revision 1.111
retrieving revision 1.112
diff -u -d -r1.111 -r1.112
--- connection_or.c	1 Jul 2004 23:13:04 -0000	1.111
+++ connection_or.c	2 Jul 2004 09:29:00 -0000	1.112
@@ -119,6 +119,7 @@
                                      const char *id_digest)
 {
   routerinfo_t *r;
+  struct in_addr in;
   r = router_get_by_digest(id_digest);
   if (r) {
     connection_or_init_conn_from_router(conn,r);
@@ -132,14 +133,17 @@
   conn->nickname = tor_malloc(HEX_DIGEST_LEN+1);
   base16_encode(conn->nickname, HEX_DIGEST_LEN+1,
                 conn->identity_digest, DIGEST_LEN);
-  /* Do something about address? Or is it already set? XXXX NMNM */
+  tor_free(conn->address);
+  in.s_addr = htonl(addr);
+  conn->address = tor_strdup(inet_ntoa(in));
 }
 
-/** Launch a new OR connection to <b>router</b>.
+/** Launch a new OR connection to <b>addr</b>:<b>port</b> and expect to
+ * handshake with an OR with identity digest <b>id_digest</b>.
  *
- * If <b>router</b> is me, do nothing. If we're already connected to <b>router</b>,
- * return that connection. If the connect is in progress, set conn's
- * state to 'connecting' and return. If connect to <b>router</b> succeeds, call
+ * If <b>id_digest</b> is me, do nothing. If we're already connected to it,
+ * return that connection. If the connect() is in progress, set conn's
+ * state to 'connecting' and return. If connect() succeeds, call
  * connection_tls_start_handshake() on it.
  *
  * This function is called from router_retry_connections(), for
@@ -148,30 +152,30 @@
  *
  * Return the launched conn, or NULL if it failed.
  */
-connection_t *connection_or_connect(routerinfo_t *router) {
+connection_t *connection_or_connect(uint32_t addr, uint16_t port,
+                                    const char *id_digest) {
   connection_t *conn;
 
-  tor_assert(router);
+  tor_assert(id_digest);
 
-  if(router_is_me(router)) {
-    log_fn(LOG_WARN,"You asked me to connect to myself! Failing.");
+  if(0) { /* XXX008 if I'm an OR and id_digest is my digest */
+    log_fn(LOG_WARN,"Request to connect to myself! Failing.");
     return NULL;
   }
 
-  /* this function should never be called if we're already connected to router, but */
-  /* check first to be sure */
-  conn = connection_get_by_identity_digest(router->identity_digest,
-                                           CONN_TYPE_OR);
+  /* this function should never be called if we're already connected to
+   * id_digest, but check first to be sure */
+  conn = connection_get_by_identity_digest(id_digest, CONN_TYPE_OR);
   if(conn)
     return conn;
 
   conn = connection_new(CONN_TYPE_OR);
 
   /* set up conn so it's got all the data we need to remember */
-  connection_or_init_conn_from_router(conn, router);
+  connection_or_init_conn_from_address(conn, addr, port, id_digest);
   conn->state = OR_CONN_STATE_CONNECTING;
 
-  switch(connection_connect(conn, router->address, router->addr, router->or_port)) {
+  switch(connection_connect(conn, conn->address, addr, port)) {
     case -1:
       connection_free(conn);
       return NULL;
@@ -252,7 +256,7 @@
  *
  * If either of us is an OP, set bandwidth to the default OP bandwidth.
  *
- * If all is successful and he's an OR, then call circuit_n_conn_open()
+ * If all is successful and he's an OR, then call circuit_n_conn_done()
  * to handle events that have been pending on the tls handshake
  * completion, and set the directory to be dirty (only matters if I'm
  * a dirserver).
@@ -284,6 +288,10 @@
   log_fn(LOG_DEBUG, "Other side (%s:%d) claims to be '%s'", conn->address,
          conn->port, nickname);
   router = router_get_by_nickname(nickname);
+  /* XXX008 here we need to tolerate unknown routers, so ORs can
+   * connect to us even when we don't know they're verified. This
+   * should probably be a call to router_get_by_digest() now, since
+   * we can't trust the nickname some guy shows up with. */
   if (!router) {
     log_fn(LOG_INFO, "Unrecognized router with nickname '%s' at %s:%d",
            nickname, conn->address, conn->port);
@@ -316,7 +324,7 @@
     conn->receiver_bucket = conn->bandwidth = DEFAULT_BANDWIDTH_OP;
   }
   directory_set_dirty();
-  circuit_n_conn_open(conn); /* send the pending creates, if any. */
+  circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
   /* Note the success */
   rep_hist_note_connect_succeeded(nickname, time(NULL));
   return 0;

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.373
retrieving revision 1.374
diff -u -d -r1.373 -r1.374
--- or.h	1 Jul 2004 11:32:25 -0000	1.373
+++ or.h	2 Jul 2004 09:29:00 -0000	1.374
@@ -270,7 +270,7 @@
 #define CIRCUIT_STATE_BUILDING 0
 /** Circuit state: Waiting to process the onionskin. */
 #define CIRCUIT_STATE_ONIONSKIN_PENDING 1
-/** Circuit state: I'm the OP, my firsthop is still connecting. */
+/** Circuit state: I'd like to deliver a create, but my n_conn is still connecting. */
 #define CIRCUIT_STATE_OR_WAIT 2
 /** Circuit state: onionskin(s) processed, ready to send/receive cells. */
 #define CIRCUIT_STATE_OPEN 3
@@ -700,6 +700,8 @@
   connection_t *p_conn;
   /** The OR connection that is next in this circuit. */
   connection_t *n_conn;
+  /** The identity hash of n_conn. */
+  char n_conn_id_digest[DIGEST_LEN];
   /** Linked list of AP streams associated with this circuit. */
   connection_t *p_streams;
   /** Linked list of Exit streams associated with this circuit. */
@@ -754,8 +756,9 @@
    */
   crypt_path_t *cpath;
 
-  char onionskin[ONIONSKIN_CHALLENGE_LEN]; /**< For storage while onionskin
-                                            * pending. */
+  /** For storage while passing to cpuworker, or while n_conn is pending. */
+  char onionskin[ONIONSKIN_CHALLENGE_LEN];
+
   char handshake_digest[DIGEST_LEN]; /**< Stores KH for intermediate hops. */
 
   time_t timestamp_created; /**< When was this circuit created? */
@@ -917,7 +920,7 @@
 void circuit_dump_by_conn(connection_t *conn, int severity);
 circuit_t *circuit_establish_circuit(uint8_t purpose,
                                      const char *exit_nickname);
-void circuit_n_conn_open(connection_t *or_conn);
+void circuit_n_conn_done(connection_t *or_conn, int success);
 int circuit_send_next_onion_skin(circuit_t *circ);
 int circuit_extend(cell_t *cell, circuit_t *circ);
 int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data, int reverse);
@@ -1108,7 +1111,8 @@
 int connection_or_finished_flushing(connection_t *conn);
 int connection_or_finished_connecting(connection_t *conn);
 
-connection_t *connection_or_connect(routerinfo_t *router);
+connection_t *connection_or_connect(uint32_t addr, uint16_t port,
+                                    const char *id_digest);
 
 int connection_tls_start_handshake(connection_t *conn, int receiving);
 int connection_tls_continue_handshake(connection_t *conn);

Index: router.c
===================================================================
RCS file: /home/or/cvsroot/src/or/router.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -d -r1.56 -r1.57
--- router.c	1 Jul 2004 23:13:04 -0000	1.56
+++ router.c	2 Jul 2004 09:29:01 -0000	1.57
@@ -321,7 +321,7 @@
                                           CONN_TYPE_OR)) {
       /* not in the list */
       log_fn(LOG_DEBUG,"connecting to OR %s:%u.",router->address,router->or_port);
-      connection_or_connect(router);
+      connection_or_connect(router->addr, router->or_port, router->identity_digest);
     }
   }
 }



More information about the tor-commits mailing list