Browse Source

r17436@tombo: nickm | 2008-07-30 09:03:19 -0400
Move n_addr, n_port, and n_conn_id_digest fields of circuit_t into a separately allocated extend_info_t. Saves 22 bytes per connected circuit_t on 32-bit platforms, and makes me more comfortable with using tor_addr_t in place of uint32_t n_addr.


svn:r16257

Nick Mathewson 17 years ago
parent
commit
186097906d
5 changed files with 61 additions and 56 deletions
  1. 3 0
      ChangeLog
  2. 31 35
      src/or/circuitbuild.c
  3. 14 10
      src/or/circuitlist.c
  4. 9 5
      src/or/circuituse.c
  5. 4 6
      src/or/or.h

+ 3 - 0
ChangeLog

@@ -33,6 +33,9 @@ Changes in version 0.2.1.3-alpha - 2008-07-xx
     - Change the implementation of ExcludeNodes and ExcludeExitNodes
     - Change the implementation of ExcludeNodes and ExcludeExitNodes
       to be more efficient.  Formerly it was quadratic in the number
       to be more efficient.  Formerly it was quadratic in the number
       of servers; now it should be linear.  Fixes bug 509.
       of servers; now it should be linear.  Fixes bug 509.
+    - Save 16-22 bytes per open circuit by moving the n_hop, n_port,
+      and n_conn_id_digest fields into a separate structure that's
+      only needed when the circuit has not yet attached to an n_conn.
 
 
   o Minor bugfixes:
   o Minor bugfixes:
     - Change the contrib/tor.logrotate script so it makes the new
     - Change the contrib/tor.logrotate script so it makes the new

+ 31 - 35
src/or/circuitbuild.c

@@ -356,9 +356,7 @@ circuit_handle_first_hop(origin_circuit_t *circ)
   tor_inet_ntoa(&in, tmpbuf, sizeof(tmpbuf));
   tor_inet_ntoa(&in, tmpbuf, sizeof(tmpbuf));
   log_debug(LD_CIRC,"Looking for firsthop '%s:%u'",tmpbuf,
   log_debug(LD_CIRC,"Looking for firsthop '%s:%u'",tmpbuf,
             firsthop->extend_info->port);
             firsthop->extend_info->port);
-  /* imprint the circuit with its future n_conn->id */
+
-  memcpy(circ->_base.n_conn_id_digest, firsthop->extend_info->identity_digest,
-         DIGEST_LEN);
   n_conn = connection_or_get_by_identity_digest(
   n_conn = connection_or_get_by_identity_digest(
          firsthop->extend_info->identity_digest);
          firsthop->extend_info->identity_digest);
   /* If we don't have an open conn, or the conn we have is obsolete
   /* If we don't have an open conn, or the conn we have is obsolete
@@ -367,8 +365,7 @@ circuit_handle_first_hop(origin_circuit_t *circ)
   if (!n_conn || n_conn->_base.state != OR_CONN_STATE_OPEN ||
   if (!n_conn || n_conn->_base.state != OR_CONN_STATE_OPEN ||
       (n_conn->_base.or_is_obsolete)) {
       (n_conn->_base.or_is_obsolete)) {
     /* not currently connected */
     /* not currently connected */
-    circ->_base.n_addr = firsthop->extend_info->addr;
+    circ->_base.n_hop = extend_info_dup(firsthop->extend_info);
-    circ->_base.n_port = firsthop->extend_info->port;
 
 
     if (!n_conn || n_conn->_base.or_is_obsolete) { /* launch the connection */
     if (!n_conn || n_conn->_base.or_is_obsolete) { /* launch the connection */
       if (circ->build_state->onehop_tunnel)
       if (circ->build_state->onehop_tunnel)
@@ -389,8 +386,7 @@ circuit_handle_first_hop(origin_circuit_t *circ)
      */
      */
     return 0;
     return 0;
   } else { /* it's already open. use it. */
   } else { /* it's already open. use it. */
-    circ->_base.n_addr = n_conn->_base.addr;
+    tor_assert(!circ->_base.n_hop);
-    circ->_base.n_port = n_conn->_base.port;
     circ->_base.n_conn = n_conn;
     circ->_base.n_conn = n_conn;
     log_debug(LD_CIRC,"Conn open. Delivering first onion skin.");
     log_debug(LD_CIRC,"Conn open. Delivering first onion skin.");
     if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
     if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
@@ -419,25 +415,24 @@ circuit_n_conn_done(or_connection_t *or_conn, int status)
   pending_circs = smartlist_create();
   pending_circs = smartlist_create();
   circuit_get_all_pending_on_or_conn(pending_circs, or_conn);
   circuit_get_all_pending_on_or_conn(pending_circs, or_conn);
 
 
-  SMARTLIST_FOREACH(pending_circs, circuit_t *, circ,
+  SMARTLIST_FOREACH_BEGIN (pending_circs, circuit_t *, circ)
     {
     {
       /* These checks are redundant wrt get_all_pending_on_or_conn, but I'm
       /* These checks are redundant wrt get_all_pending_on_or_conn, but I'm
        * leaving them in in case it's possible for the status of a circuit to
        * leaving them in in case it's possible for the status of a circuit to
        * change as we're going down the list. */
        * change as we're going down the list. */
-      if (circ->marked_for_close || circ->n_conn ||
+      if (circ->marked_for_close || circ->n_conn || !circ->n_hop ||
           circ->state != CIRCUIT_STATE_OR_WAIT)
           circ->state != CIRCUIT_STATE_OR_WAIT)
         continue;
         continue;
-      if (tor_digest_is_zero(circ->n_conn_id_digest)) {
+
+      if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
         /* Look at addr/port. This is an unkeyed connection. */
         /* Look at addr/port. This is an unkeyed connection. */
-        if (circ->n_addr != or_conn->_base.addr ||
+        if (circ->n_hop->addr != or_conn->_base.addr ||
-            circ->n_port != or_conn->_base.port)
+            circ->n_hop->port != or_conn->_base.port)
           continue;
           continue;
-        /* now teach circ the right identity_digest */
-        memcpy(circ->n_conn_id_digest, or_conn->identity_digest, DIGEST_LEN);
       } else {
       } else {
         /* We expected a key. See if it's the right one. */
         /* We expected a key. See if it's the right one. */
         if (memcmp(or_conn->identity_digest,
         if (memcmp(or_conn->identity_digest,
-                   circ->n_conn_id_digest, DIGEST_LEN))
+                   circ->n_hop->identity_digest, DIGEST_LEN))
           continue;
           continue;
       }
       }
       if (!status) { /* or_conn failed; close circ */
       if (!status) { /* or_conn failed; close circ */
@@ -450,6 +445,9 @@ circuit_n_conn_done(or_connection_t *or_conn, int status)
        * orconn_circuid_circuit_map, so we don't need to call
        * orconn_circuid_circuit_map, so we don't need to call
        * set_circid_orconn here. */
        * set_circid_orconn here. */
       circ->n_conn = or_conn;
       circ->n_conn = or_conn;
+      extend_info_free(circ->n_hop);
+      circ->n_hop = NULL;
+
       if (CIRCUIT_IS_ORIGIN(circ)) {
       if (CIRCUIT_IS_ORIGIN(circ)) {
         if ((err_reason =
         if ((err_reason =
              circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ))) < 0) {
              circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ))) < 0) {
@@ -471,7 +469,8 @@ circuit_n_conn_done(or_connection_t *or_conn, int status)
         tor_free(circ->n_conn_onionskin);
         tor_free(circ->n_conn_onionskin);
         circuit_set_state(circ, CIRCUIT_STATE_OPEN);
         circuit_set_state(circ, CIRCUIT_STATE_OPEN);
       }
       }
-    });
+    }
+  SMARTLIST_FOREACH_END(circ);
 
 
   smartlist_free(pending_circs);
   smartlist_free(pending_circs);
 }
 }
@@ -723,6 +722,8 @@ circuit_extend(cell_t *cell, circuit_t *circ)
   relay_header_t rh;
   relay_header_t rh;
   char *onionskin;
   char *onionskin;
   char *id_digest=NULL;
   char *id_digest=NULL;
+  uint32_t n_addr;
+  uint16_t n_port;
 
 
   if (circ->n_conn) {
   if (circ->n_conn) {
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
@@ -745,11 +746,11 @@ circuit_extend(cell_t *cell, circuit_t *circ)
     return -1;
     return -1;
   }
   }
 
 
-  circ->n_addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
+  n_addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
-  circ->n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4));
+  n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4));
-
   onionskin = cell->payload+RELAY_HEADER_SIZE+4+2;
   onionskin = cell->payload+RELAY_HEADER_SIZE+4+2;
   id_digest = cell->payload+RELAY_HEADER_SIZE+4+2+ONIONSKIN_CHALLENGE_LEN;
   id_digest = cell->payload+RELAY_HEADER_SIZE+4+2+ONIONSKIN_CHALLENGE_LEN;
+
   n_conn = connection_or_get_by_identity_digest(id_digest);
   n_conn = connection_or_get_by_identity_digest(id_digest);
 
 
   /* If we don't have an open conn, or the conn we have is obsolete
   /* If we don't have an open conn, or the conn we have is obsolete
@@ -759,24 +760,23 @@ circuit_extend(cell_t *cell, circuit_t *circ)
       n_conn->_base.or_is_obsolete) {
       n_conn->_base.or_is_obsolete) {
     struct in_addr in;
     struct in_addr in;
     char tmpbuf[INET_NTOA_BUF_LEN];
     char tmpbuf[INET_NTOA_BUF_LEN];
-    in.s_addr = htonl(circ->n_addr);
+    in.s_addr = htonl(n_addr);
     tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
     tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
     log_debug(LD_CIRC|LD_OR,"Next router (%s:%d) not connected. Connecting.",
     log_debug(LD_CIRC|LD_OR,"Next router (%s:%d) not connected. Connecting.",
-              tmpbuf, circ->n_port);
+              tmpbuf, (int)n_port);
+
+    circ->n_hop = extend_info_alloc(NULL /*nickname*/,
+                                    id_digest,
+                                    NULL /*onion_key*/,
+                                    n_addr, n_port);
 
 
     circ->n_conn_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
     circ->n_conn_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
     memcpy(circ->n_conn_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN);
     memcpy(circ->n_conn_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN);
     circuit_set_state(circ, CIRCUIT_STATE_OR_WAIT);
     circuit_set_state(circ, CIRCUIT_STATE_OR_WAIT);
 
 
-    /* imprint the circuit with its future n_conn->id */
+    if (! (n_conn && !n_conn->_base.or_is_obsolete)) {
-    memcpy(circ->n_conn_id_digest, id_digest, DIGEST_LEN);
+      /* we should try to open a connection */
-
+      n_conn = connection_or_connect(n_addr, n_port, id_digest);
-    if (n_conn && !n_conn->_base.or_is_obsolete) {
-      circ->n_addr = n_conn->_base.addr;
-      circ->n_port = n_conn->_base.port;
-    } else {
-     /* we should try to open a connection */
-      n_conn = connection_or_connect(circ->n_addr, circ->n_port, id_digest);
       if (!n_conn) {
       if (!n_conn) {
         log_info(LD_CIRC,"Launching n_conn failed. Closing circuit.");
         log_info(LD_CIRC,"Launching n_conn failed. Closing circuit.");
         circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
         circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
@@ -791,12 +791,8 @@ circuit_extend(cell_t *cell, circuit_t *circ)
     return 0;
     return 0;
   }
   }
 
 
-  /* these may be different if the router connected to us from elsewhere */
+  tor_assert(circ->n_hop);
-  circ->n_addr = n_conn->_base.addr;
-  circ->n_port = n_conn->_base.port;
-
   circ->n_conn = n_conn;
   circ->n_conn = n_conn;
-  memcpy(circ->n_conn_id_digest, n_conn->identity_digest, DIGEST_LEN);
   log_debug(LD_CIRC,"n_conn is %s:%u",
   log_debug(LD_CIRC,"n_conn is %s:%u",
             n_conn->_base.address,n_conn->_base.port);
             n_conn->_base.address,n_conn->_base.port);
 
 

+ 14 - 10
src/or/circuitlist.c

@@ -235,16 +235,18 @@ circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn)
   {
   {
     if (circ->marked_for_close)
     if (circ->marked_for_close)
       continue;
       continue;
+    if (!circ->n_hop)
+      continue;
     tor_assert(circ->state == CIRCUIT_STATE_OR_WAIT);
     tor_assert(circ->state == CIRCUIT_STATE_OR_WAIT);
-    if (tor_digest_is_zero(circ->n_conn_id_digest)) {
+    if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
       /* Look at addr/port. This is an unkeyed connection. */
       /* Look at addr/port. This is an unkeyed connection. */
-      if (circ->n_addr != or_conn->_base.addr ||
+      if (circ->n_hop->addr != or_conn->_base.addr ||
-          circ->n_port != or_conn->_base.port)
+          circ->n_hop->port != or_conn->_base.port)
         continue;
         continue;
     } else {
     } else {
       /* We expected a key. See if it's the right one. */
       /* We expected a key. See if it's the right one. */
       if (memcmp(or_conn->identity_digest,
       if (memcmp(or_conn->identity_digest,
-                 circ->n_conn_id_digest, DIGEST_LEN))
+                 circ->n_hop->identity_digest, DIGEST_LEN))
         continue;
         continue;
     }
     }
     smartlist_add(out, circ);
     smartlist_add(out, circ);
@@ -430,6 +432,8 @@ circuit_free(circuit_t *circ)
     cell_queue_clear(&ocirc->p_conn_cells);
     cell_queue_clear(&ocirc->p_conn_cells);
   }
   }
 
 
+  if (circ->n_hop)
+    extend_info_free(circ->n_hop);
   tor_free(circ->n_conn_onionskin);
   tor_free(circ->n_conn_onionskin);
 
 
   /* Remove from map. */
   /* Remove from map. */
@@ -568,11 +572,11 @@ circuit_dump_by_conn(connection_t *conn, int severity)
         }
         }
       }
       }
     }
     }
-    if (!circ->n_conn && circ->n_addr && circ->n_port &&
+    if (!circ->n_conn && circ->n_hop &&
-        circ->n_addr == conn->addr &&
+        circ->n_hop->addr == conn->addr &&
-        circ->n_port == conn->port &&
+        circ->n_hop->port == conn->port &&
         conn->type == CONN_TYPE_OR &&
         conn->type == CONN_TYPE_OR &&
-        !memcmp(TO_OR_CONN(conn)->identity_digest, circ->n_conn_id_digest,
+        !memcmp(TO_OR_CONN(conn)->identity_digest, circ->n_hop->identity_digest,
                 DIGEST_LEN)) {
                 DIGEST_LEN)) {
       circuit_dump_details(severity, circ, conn->conn_array_index,
       circuit_dump_details(severity, circ, conn->conn_array_index,
                            (circ->state == CIRCUIT_STATE_OPEN &&
                            (circ->state == CIRCUIT_STATE_OPEN &&
@@ -1152,8 +1156,8 @@ assert_circuit_ok(const circuit_t *c)
   }
   }
 
 
   if (c->n_conn) {
   if (c->n_conn) {
-    tor_assert(!memcmp(c->n_conn->identity_digest, c->n_conn_id_digest,
+    tor_assert(!c->n_hop);
-                       DIGEST_LEN));
+
     if (c->n_circ_id)
     if (c->n_circ_id)
       tor_assert(c == circuit_get_by_circid_orconn(c->n_circ_id, c->n_conn));
       tor_assert(c == circuit_get_by_circid_orconn(c->n_circ_id, c->n_conn));
   }
   }

+ 9 - 5
src/or/circuituse.c

@@ -289,7 +289,7 @@ circuit_expire_building(time_t now)
 
 
     if (victim->n_conn)
     if (victim->n_conn)
       log_info(LD_CIRC,"Abandoning circ %s:%d:%d (state %d:%s, purpose %d)",
       log_info(LD_CIRC,"Abandoning circ %s:%d:%d (state %d:%s, purpose %d)",
-               victim->n_conn->_base.address, victim->n_port,
+               victim->n_conn->_base.address, victim->n_conn->_base.port,
                victim->n_circ_id,
                victim->n_circ_id,
                victim->state, circuit_state_to_string(victim->state),
                victim->state, circuit_state_to_string(victim->state),
                victim->purpose);
                victim->purpose);
@@ -739,12 +739,15 @@ circuit_build_failed(origin_circuit_t *circ)
     /* We failed at the first hop. If there's an OR connection
     /* We failed at the first hop. If there's an OR connection
        to blame, blame it. */
        to blame, blame it. */
     or_connection_t *n_conn = NULL;
     or_connection_t *n_conn = NULL;
+    const char *n_conn_id = NULL;
     if (circ->_base.n_conn) {
     if (circ->_base.n_conn) {
       n_conn = circ->_base.n_conn;
       n_conn = circ->_base.n_conn;
-    } else if (circ->_base.state == CIRCUIT_STATE_OR_WAIT) {
+      if (n_conn) n_conn_id = n_conn->identity_digest;
+    } else if (circ->_base.state == CIRCUIT_STATE_OR_WAIT &&
+               circ->_base.n_hop) {
       /* we have to hunt for it */
       /* we have to hunt for it */
-      n_conn = connection_or_get_by_identity_digest(
+      n_conn_id = circ->_base.n_hop->identity_digest;
-                                               circ->_base.n_conn_id_digest);
+      n_conn = connection_or_get_by_identity_digest(n_conn_id);
     }
     }
     if (n_conn) {
     if (n_conn) {
       log_info(LD_OR,
       log_info(LD_OR,
@@ -760,7 +763,8 @@ circuit_build_failed(origin_circuit_t *circ)
     }
     }
     /* if there are any one-hop streams waiting on this circuit, fail
     /* if there are any one-hop streams waiting on this circuit, fail
      * them now so they can retry elsewhere. */
      * them now so they can retry elsewhere. */
-    connection_ap_fail_onehop(circ->_base.n_conn_id_digest, circ->build_state);
+    if (n_conn_id)
+      connection_ap_fail_onehop(n_conn_id, circ->build_state);
   }
   }
 
 
   switch (circ->_base.purpose) {
   switch (circ->_base.purpose) {

+ 4 - 6
src/or/or.h

@@ -1780,14 +1780,12 @@ typedef struct circuit_t {
   cell_queue_t n_conn_cells;
   cell_queue_t n_conn_cells;
   /** The OR connection that is next in this circuit. */
   /** The OR connection that is next in this circuit. */
   or_connection_t *n_conn;
   or_connection_t *n_conn;
-  /** The identity hash of n_conn. */
-  char n_conn_id_digest[DIGEST_LEN];
   /** The circuit_id used in the next (forward) hop of this circuit. */
   /** The circuit_id used in the next (forward) hop of this circuit. */
   circid_t n_circ_id;
   circid_t n_circ_id;
-  /** The port for the OR that is next in this circuit. */
+
-  uint16_t n_port;
+  /** The hop to which we want to extend this ciruit.  Should be NULL if
-  /** The IPv4 address of the OR that is next in this circuit. */
+   * the */
-  uint32_t n_addr;
+  extend_info_t *n_hop;
 
 
   /** True iff we are waiting for n_conn_cells to become less full before
   /** True iff we are waiting for n_conn_cells to become less full before
    * allowing p_streams to add any more cells. (Origin circuit only.) */
    * allowing p_streams to add any more cells. (Origin circuit only.) */