[tor-commits] [tor/master] Only use optimistic data with exits that support it

nickm at torproject.org nickm at torproject.org
Wed Jul 20 13:51:19 UTC 2011


commit 1e441df2d0d06aa66eaf2c0e00a42d7fe9c39c87
Author: Nick Mathewson <nickm at torproject.org>
Date:   Mon Jul 18 13:56:22 2011 -0400

    Only use optimistic data with exits that support it
    
    This adds a little code complexity: we need to remember for each
    node whether it supports the right feature, and then check for each
    connection whether it's exiting at such a node.  We store this in a
    flag in the edge_connection_t, and set that flag at link time.
---
 src/or/circuituse.c      |   21 +++++++++++++++++
 src/or/connection_edge.c |   56 ++++++++++++++++++++++++++++++++-------------
 src/or/or.h              |    8 ++++++
 src/or/routerparse.c     |    3 ++
 4 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 460c41f..3c8cacb 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -677,6 +677,7 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
   tor_assert(conn);
 
   conn->cpath_layer = NULL; /* make sure we don't keep a stale pointer */
+  conn->exit_allows_optimistic_data = 0;
   conn->on_circuit = NULL;
 
   if (CIRCUIT_IS_ORIGIN(circ)) {
@@ -1449,6 +1450,8 @@ static void
 link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
                     crypt_path_t *cpath)
 {
+  const node_t *exitnode;
+
   /* add it into the linked list of streams on this circuit */
   log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.",
             circ->_base.n_circ_id);
@@ -1468,6 +1471,24 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
     tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
     apconn->cpath_layer = circ->cpath->prev;
   }
+
+  /* See if we can use optimistic data on this circuit */
+  if (apconn->cpath_layer->extend_info &&
+      (exitnode = node_get_by_id(
+                     apconn->cpath_layer->extend_info->identity_digest)) &&
+      exitnode->rs) {
+    /* Okay; we know what exit node this is. */
+    if (circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL &&
+        exitnode->rs->version_supports_optimistic_data)
+      apconn->exit_allows_optimistic_data = 1;
+    else
+      apconn->exit_allows_optimistic_data = 0;
+    log_info(LD_APP, "Looks like completed circuit to %s %s allow "
+             "optimistic data for connection to %s",
+             safe_str_client(node_describe(exitnode)),
+             apconn->exit_allows_optimistic_data ? "does" : "doesn't",
+             safe_str_client(apconn->socks_request->address));
+  }
 }
 
 /** Return true iff <b>address</b> is matched by one of the entries in
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 6f91d1a..20f8bc9 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -57,6 +57,7 @@ static int connection_exit_connect_dir(edge_connection_t *exitconn);
 static int address_is_in_virtual_range(const char *addr);
 static int consider_plaintext_ports(edge_connection_t *conn, uint16_t port);
 static void clear_trackexithost_mappings(const char *exitname);
+static int connection_ap_supports_optimistic_data(const edge_connection_t *);
 
 /** An AP stream has failed/finished. If it hasn't already sent back
  * a socks reply, send one now (based on endreason). Also set
@@ -154,6 +155,22 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
         return -1;
       }
       return 0;
+    case AP_CONN_STATE_CONNECT_WAIT:
+      if (connection_ap_supports_optimistic_data(conn)) {
+        log_info(LD_EDGE,
+                 "data from edge while in '%s' state. Sending it anyway. "
+                 "package_partial=%d, buflen=%ld",
+                 conn_state_to_string(conn->_base.type, conn->_base.state),
+                 package_partial, connection_get_inbuf_len(TO_CONN(conn)));
+        if (connection_edge_package_raw_inbuf(conn, package_partial, NULL)<0) {
+          /* (We already sent an end cell if possible) */
+          connection_mark_for_close(TO_CONN(conn));
+          return -1;
+        }
+        return 0;
+      }
+      /* Fall through if the connection is on a circuit without optimistic
+       * data support. */
     case EXIT_CONN_STATE_CONNECTING:
     case AP_CONN_STATE_RENDDESC_WAIT:
     case AP_CONN_STATE_CIRCUIT_WAIT:
@@ -163,18 +180,6 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
                "data from edge while in '%s' state. Leaving it on buffer.",
                conn_state_to_string(conn->_base.type, conn->_base.state));
       return 0;
-    case AP_CONN_STATE_CONNECT_WAIT:
-      log_info(LD_EDGE,
-               "data from edge while in '%s' state. Sending it anyway. "
-               "package_partial=%d, buflen=%ld",
-               conn_state_to_string(conn->_base.type, conn->_base.state),
-               package_partial, connection_get_inbuf_len(TO_CONN(conn)));
-      if (connection_edge_package_raw_inbuf(conn, package_partial, NULL) < 0) {
-        /* (We already sent an end cell if possible) */
-        connection_mark_for_close(TO_CONN(conn));
-        return -1;
-      }
-      return 0;
   }
   log_warn(LD_BUG,"Got unexpected state %d. Closing.",conn->_base.state);
   tor_fragile_assert();
@@ -2345,6 +2350,22 @@ get_unique_stream_id_by_circ(origin_circuit_t *circ)
   return test_stream_id;
 }
 
+/** Return true iff <b>conn</b> is linked to a circuit and configured to use
+ * an exit that supports optimistic data. */
+static int
+connection_ap_supports_optimistic_data(const edge_connection_t *conn)
+{
+  tor_assert(conn->_base.type == CONN_TYPE_AP);
+  /* We can only send optimistic data if we're connected to an open
+     general circuit. */
+  if (conn->on_circuit == NULL ||
+      conn->on_circuit->state != CIRCUIT_STATE_OPEN ||
+      conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL)
+    return 0;
+
+  return conn->exit_allows_optimistic_data;
+}
+
 /** Write a relay begin cell, using destaddr and destport from ap_conn's
  * socks_request field, and send it down circ.
  *
@@ -2408,10 +2429,13 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
   control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT, 0);
 
   /* If there's queued-up data, send it now */
-  log_info(LD_APP, "Possibly sending queued-up data: %ld",
-           connection_get_inbuf_len(TO_CONN(ap_conn)));
-  if (connection_edge_package_raw_inbuf(ap_conn, 1, NULL) < 0) {
-    connection_mark_for_close(TO_CONN(ap_conn));
+  if (connection_get_inbuf_len(TO_CONN(ap_conn)) &&
+      connection_ap_supports_optimistic_data(ap_conn)) {
+    log_info(LD_APP, "Sending up to %ld bytes of queued-up data",
+             connection_get_inbuf_len(TO_CONN(ap_conn)));
+    if (connection_edge_package_raw_inbuf(ap_conn, 1, NULL) < 0) {
+      connection_mark_for_close(TO_CONN(ap_conn));
+    }
   }
 
   return 0;
diff --git a/src/or/or.h b/src/or/or.h
index 7a2bde5..f805215 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1232,6 +1232,11 @@ typedef struct edge_connection_t {
    * NATd connection */
   unsigned int is_transparent_ap:1;
 
+  /** Set if this connection's target exit node allows optimistic data.
+   * (That is, data sent on this stream before the exit has sent a
+   * CONNECTED cell.)*/
+  unsigned int exit_allows_optimistic_data : 1;
+
   /** If this is a DNSPort connection, this field holds the pending DNS
    * request that we're going to try to answer.  */
   struct evdns_server_request *dns_server_request;
@@ -1667,6 +1672,9 @@ typedef struct routerstatus_t {
   /** True iff this router is a version that, if it caches directory info,
    * we can get microdescriptors from. */
   unsigned int version_supports_microdesc_cache:1;
+  /** True iff this router is a version that allows DATA cells to arrive on
+   * a stream before it has sent a CONNECTED cell. */
+  unsigned int version_supports_optimistic_data:1;
 
   unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
   unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index d1b2cd0..5f160d0 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -2092,6 +2092,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
       rs->version_supports_extrainfo_upload = 1;
       rs->version_supports_conditional_consensus = 1;
       rs->version_supports_microdesc_cache = 1;
+      rs->version_supports_optimistic_data = 1;
     } else {
       rs->version_supports_begindir =
         tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
@@ -2109,6 +2110,8 @@ routerstatus_parse_entry_from_string(memarea_t *area,
        */
       rs->version_supports_microdesc_cache =
         tor_version_as_new_as(tok->args[0], "0.2.3.0-alpha");
+      rs->version_supports_optimistic_data =
+        tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
     }
     if (vote_rs) {
       vote_rs->version = tor_strdup(tok->args[0]);





More information about the tor-commits mailing list