Quellcode durchsuchen

Merge remote branch 'arma/optimistic_server'

Nick Mathewson vor 13 Jahren
Ursprung
Commit
415caba967
3 geänderte Dateien mit 47 neuen und 7 gelöschten Zeilen
  1. 6 0
      changes/prop174_server
  2. 16 3
      src/or/connection.c
  3. 25 4
      src/or/relay.c

+ 6 - 0
changes/prop174_server

@@ -0,0 +1,6 @@
+  o Features:
+    - Servers now accept and queue data on not-yet-connected
+      streams.  Previously, such data wasn't allowed.  This forced
+      clients to wait for a CONNECTED cell before sending their
+      data, thus adding a round trip to stream setup.  (Patch from
+      Ian Goldberg; implements the server side of Proposal 174.)

+ 16 - 3
src/or/connection.c

@@ -3259,7 +3259,13 @@ _connection_write_to_buf_impl(const char *string, size_t len,
     return;
   }
 
-  connection_start_writing(conn);
+  /* If we receive optimistic data in the EXIT_CONN_STATE_RESOLVING
+   * state, we don't want to try to write it right away, since
+   * conn->write_event won't be set yet.  Otherwise, write data from
+   * this conn as the socket is available. */
+  if (conn->write_event) {
+    connection_start_writing(conn);
+  }
   if (zlib) {
     conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen;
   } else {
@@ -3837,8 +3843,15 @@ assert_connection_ok(connection_t *conn, time_t now)
     tor_assert(conn->s < 0);
 
   if (conn->outbuf_flushlen > 0) {
-    tor_assert(connection_is_writing(conn) || conn->write_blocked_on_bw ||
-            (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->edge_blocked_on_circ));
+    /* With optimistic data, we may have queued data in
+     * EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing.
+     * */
+    tor_assert((conn->type == CONN_TYPE_EXIT &&
+                conn->state == EXIT_CONN_STATE_RESOLVING) ||
+               connection_is_writing(conn) ||
+               conn->write_blocked_on_bw ||
+               (CONN_IS_EDGE(conn) &&
+                TO_EDGE_CONN(conn)->edge_blocked_on_circ));
   }
 
   if (conn->hold_open_until_flushed)

+ 25 - 4
src/or/relay.c

@@ -1031,6 +1031,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
   relay_header_t rh;
   unsigned domain = layer_hint?LD_APP:LD_EXIT;
   int reason;
+  int optimistic_data = 0; /* Set to 1 if we receive data on a stream
+                            * that's in the EXIT_CONN_STATE_RESOLVING
+                            * or EXIT_CONN_STATE_CONNECTING states. */
 
   tor_assert(cell);
   tor_assert(circ);
@@ -1050,9 +1053,20 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
   /* either conn is NULL, in which case we've got a control cell, or else
    * conn points to the recognized stream. */
 
-  if (conn && !connection_state_is_open(TO_CONN(conn)))
-    return connection_edge_process_relay_cell_not_open(
-             &rh, cell, circ, conn, layer_hint);
+  if (conn && !connection_state_is_open(TO_CONN(conn))) {
+    if (conn->_base.type == CONN_TYPE_EXIT &&
+        (conn->_base.state == EXIT_CONN_STATE_CONNECTING ||
+         conn->_base.state == EXIT_CONN_STATE_RESOLVING) &&
+        rh.command == RELAY_COMMAND_DATA) {
+      /* Allow DATA cells to be delivered to an exit node in state
+       * EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING.
+       * This speeds up HTTP, for example. */
+      optimistic_data = 1;
+    } else {
+      return connection_edge_process_relay_cell_not_open(
+               &rh, cell, circ, conn, layer_hint);
+    }
+  }
 
   switch (rh.command) {
     case RELAY_COMMAND_DROP:
@@ -1119,7 +1133,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
       stats_n_data_bytes_received += rh.length;
       connection_write_to_buf((char*)(cell->payload + RELAY_HEADER_SIZE),
                               rh.length, TO_CONN(conn));
-      connection_edge_consider_sending_sendme(conn);
+
+      if (!optimistic_data) {
+        /* Only send a SENDME if we're not getting optimistic data; otherwise
+         * a SENDME could arrive before the CONNECTED.
+         */
+        connection_edge_consider_sending_sendme(conn);
+      }
+
       return 0;
     case RELAY_COMMAND_END:
       reason = rh.length > 0 ?