summaryrefslogtreecommitdiff
path: root/src/or/connection.c
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2007-01-22 06:07:51 +0000
committerRoger Dingledine <arma@torproject.org>2007-01-22 06:07:51 +0000
commitab838bddb89fa3f37eeada29e8c10d16873b5e86 (patch)
tree8c908e7cb155cbc1ae02886c3ab097f398aadeab /src/or/connection.c
parent7b5f9887fa3a8bf37d1968ab547edbdd6cba1f02 (diff)
downloadtor-ab838bddb89fa3f37eeada29e8c10d16873b5e86.tar.gz
tor-ab838bddb89fa3f37eeada29e8c10d16873b5e86.zip
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
Diffstat (limited to 'src/or/connection.c')
-rw-r--r--src/or/connection.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/src/or/connection.c b/src/or/connection.c
index 5b31cec21d..6a25cac731 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -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 *