Forráskód Böngészése

Merge remote-tracking branch 'public/bug7708_023_v3_squashed'

Nick Mathewson 11 éve
szülő
commit
c93f66b103
2 módosított fájl, 21 hozzáadás és 4 törlés
  1. 5 0
      changes/bug7708
  2. 16 4
      src/or/connection.c

+ 5 - 0
changes/bug7708

@@ -0,0 +1,5 @@
+  o Major bugfixes:
+    - When a TLS write is partially successful but incomplete, remember
+      that the flushed part has been flushed, and notice that bytes were
+      actually written. Reported and fixed pseudonymously. Fixes bug
+      7708; bugfix on Tor 0.1.0.5-rc.

+ 16 - 4
src/or/connection.c

@@ -3276,6 +3276,7 @@ connection_handle_write_impl(connection_t *conn, int force)
   ssize_t max_to_write;
   time_t now = approx_time();
   size_t n_read = 0, n_written = 0;
+  int dont_stop_writing = 0;
 
   tor_assert(!connection_is_listener(conn));
 
@@ -3332,6 +3333,7 @@ connection_handle_write_impl(connection_t *conn, int force)
   if (connection_speaks_cells(conn) &&
       conn->state > OR_CONN_STATE_PROXY_HANDSHAKING) {
     or_connection_t *or_conn = TO_OR_CONN(conn);
+    size_t initial_size;
     if (conn->state == OR_CONN_STATE_TLS_HANDSHAKING ||
         conn->state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) {
       connection_stop_writing(conn);
@@ -3355,6 +3357,7 @@ connection_handle_write_impl(connection_t *conn, int force)
     }
 
     /* else open, or closing */
+    initial_size = buf_datalen(conn->outbuf);
     result = flush_buf_tls(or_conn->tls, conn->outbuf,
                            max_to_write, &conn->outbuf_flushlen);
 
@@ -3385,7 +3388,8 @@ connection_handle_write_impl(connection_t *conn, int force)
       case TOR_TLS_WANTWRITE:
         log_debug(LD_NET,"wanted write.");
         /* we're already writing */
-        return 0;
+        dont_stop_writing = 1;
+        break;
       case TOR_TLS_WANTREAD:
         /* Make sure to avoid a loop if the receive buckets are empty. */
         log_debug(LD_NET,"wanted read.");
@@ -3407,6 +3411,12 @@ connection_handle_write_impl(connection_t *conn, int force)
     tor_tls_get_n_raw_bytes(or_conn->tls, &n_read, &n_written);
     log_debug(LD_GENERAL, "After TLS write of %d: %ld read, %ld written",
               result, (long)n_read, (long)n_written);
+    /* So we notice bytes were written even on error */
+    /* XXXX024 This cast is safe since we can never write INT_MAX bytes in a
+     * single set of TLS operations. But it looks kinda ugly. If we refactor
+     * the *_buf_tls functions, we should make them return ssize_t or size_t
+     * or something. */
+    result = (int)(initial_size-buf_datalen(conn->outbuf));
   } else {
     CONN_LOG_PROTECT(conn,
              result = flush_buf(conn->s, conn->outbuf,
@@ -3453,7 +3463,8 @@ connection_handle_write_impl(connection_t *conn, int force)
     }
   }
 
-  if (!connection_wants_to_flush(conn)) { /* it's done flushing */
+  if (!connection_wants_to_flush(conn) &&
+      !dont_stop_writing) { /* it's done flushing */
     if (connection_finished_flushing(conn) < 0) {
       /* already marked */
       return -1;
@@ -3981,8 +3992,9 @@ connection_flushed_some(connection_t *conn)
   return r;
 }
 
-/** We just finished flushing bytes from conn-\>outbuf, and there
- * are no more bytes remaining.
+/** We just finished flushing bytes to the appropriately low network layer,
+ * and there are no more bytes remaining in conn-\>outbuf, conn-\>bev, or
+ * conn-\>tls to be flushed.
  *
  * This function just passes conn to the connection-specific
  * connection_*_finished_flushing() function.