Commit ab838bdd authored by Roger Dingledine's avatar Roger Dingledine
Browse files

Flush local controller connection buffers periodically as we're

writing to them, so we avoid queueing 4+ megabytes of data before
trying to flush.

Also add a new XXX012.


svn:r9382
parent 7b5f9887
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@ Changes in version 0.1.2.7-alpha - 2007-??-??
      pointer loops.
    - Fix a memory leak when sending a 503 response for a networkstatus
      request.
    - Flush local controller connection buffers periodically as we're
      writing to them, so we avoid queueing 4+ megabytes of data before
      trying to flush.

  o Minor bugfixes:
    - When computing clock skew from directory HTTP headers, consider what
+48 −4
Original line number Diff line number Diff line
@@ -1780,6 +1780,13 @@ connection_handle_write(connection_t *conn, int force)
  return 0;
}

/** Openssl TLS record size is 16383; this is close. The goal here is to
 * push data out as soon as we know there's enough for a TLS record, so
 * during periods of high load we won't read entire megabytes from
 * input before pushing any data out. It also has the feature of not
 * growing huge outbufs unless something is slow. */
#define MIN_TLS_FLUSHLEN 15872

/** Append <b>len</b> bytes of <b>string</b> onto <b>conn</b>'s
 * outbuf, and ask it to start writing.
 *
@@ -1787,6 +1794,11 @@ connection_handle_write(connection_t *conn, int force)
 * its contents compressed or decompressed as they're written.  If zlib is
 * negative, this is the last data to be compressed, and the connection's zlib
 * state should be flushed.
 *
 * If it's an OR conn and an entire TLS record is ready, then try to
 * flush the record now. Similarly, if it's a local control connection
 * and a 64k chunk is ready, try to flush it all, so we don't end up with
 * many megabytes of controller info queued at once.
 */
void
_connection_write_to_buf_impl(const char *string, size_t len,
@@ -1804,7 +1816,7 @@ _connection_write_to_buf_impl(const char *string, size_t len,
  if (zlib) {
    dir_connection_t *dir_conn = TO_DIR_CONN(conn);
    int done = zlib < 0;
    if (!dir_conn) return;
    if (!dir_conn) return; /* <-- XXX012 This line is pointless, yes? */
    CONN_LOG_PROTECT(conn, r = write_to_buf_zlib(conn->outbuf,
                                                 dir_conn->zlib_state,
                                                 string, len, done));
@@ -1828,10 +1840,42 @@ _connection_write_to_buf_impl(const char *string, size_t len,
  }

  connection_start_writing(conn);
  if (zlib)
  if (zlib) {
    conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen;
  else
  } else {
    int extra = 0;
    conn->outbuf_flushlen += len;

    if (conn->type == CONN_TYPE_OR &&
        conn->outbuf_flushlen-len < MIN_TLS_FLUSHLEN &&
        conn->outbuf_flushlen >= MIN_TLS_FLUSHLEN) {
      extra = conn->outbuf_flushlen - MIN_TLS_FLUSHLEN;
      conn->outbuf_flushlen = MIN_TLS_FLUSHLEN;
    } else if (conn->type == CONN_TYPE_CONTROL &&
               is_internal_IP(conn->addr, 0) &&
               conn->outbuf_flushlen-len < 1<<16 &&
               conn->outbuf_flushlen >= 1<<16) {
      /* just try to flush all of it */
    } else
      return; /* no need to try flushing */

    if (connection_handle_write(conn, 0) < 0) {
      if (!conn->marked_for_close) {
        /* this connection is broken. remove it. */
        log_warn(LD_BUG, "Bug: unhandled error on write for "
                 "conn (type %d, fd %d); removing",
                 conn->type, conn->s);
        tor_fragile_assert();
        /* do a close-immediate here, so we don't try to flush */
        connection_close_immediate(conn);
      }
      return;
    }
    if (extra) {
      conn->outbuf_flushlen += extra;
      connection_start_writing(conn);
    }
  }
}

/** Return the conn to addr/port that has the most recent
@@ -1881,7 +1925,7 @@ connection_get_by_type_addr_port_purpose(int type,
  return NULL;
}

/** Return the connection with id <b>id</b> if it is not already marked for
/** Return the stream with id <b>id</b> if it is not already marked for
 * close.
 */
edge_connection_t *
+0 −32
Original line number Diff line number Diff line
@@ -693,9 +693,6 @@ connection_tls_finish_handshake(or_connection_t *conn)

/** Pack <b>cell</b> into wire-format, and write it onto <b>conn</b>'s
 * outbuf.
 *
 * If it's an OR conn, and an entire TLS record is
 * ready, then try to flush the record now.
 */
void
connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
@@ -709,35 +706,6 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
  cell_pack(n, cell);

  connection_write_to_buf(n, CELL_NETWORK_SIZE, TO_CONN(conn));

#define MIN_TLS_FLUSHLEN 15872
/* openssl tls record size is 16383, this is close. The goal here is to
 * push data out as soon as we know there's enough for a tls record, so
 * during periods of high load we won't read the entire megabyte from
 * input before pushing any data out. It also has the feature of not
 * growing huge outbufs unless something is slow. */
  if (conn->_base.outbuf_flushlen-CELL_NETWORK_SIZE < MIN_TLS_FLUSHLEN &&
      conn->_base.outbuf_flushlen >= MIN_TLS_FLUSHLEN) {
    int extra = conn->_base.outbuf_flushlen - MIN_TLS_FLUSHLEN;
    conn->_base.outbuf_flushlen = MIN_TLS_FLUSHLEN;
    connection_start_writing(TO_CONN(conn));
    if (connection_handle_write(TO_CONN(conn), 0) < 0) {
      if (!conn->_base.marked_for_close) {
        /* this connection is broken. remove it. */
        log_warn(LD_BUG,
                 "Bug: unhandled error on write for OR conn (fd %d); removing",
                 conn->_base.s);
        tor_fragile_assert();
        /* do a close-immediate here, so we don't try to flush */
        connection_close_immediate(TO_CONN(conn));
      }
      return;
    }
    if (extra) {
      conn->_base.outbuf_flushlen += extra;
      connection_start_writing(TO_CONN(conn));
    }
  }
}

/** Process cells from <b>conn</b>'s inbuf.