summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2013-02-01 17:11:46 -0500
committerNick Mathewson <nickm@torproject.org>2013-02-01 17:11:46 -0500
commitc93f66b1037e151268b5662f3957d13c4c94d1fb (patch)
treed952875329991810eea11733097bdd329508ce08
parent4074ff440e20c6549d8589a4f214791d610e3deb (diff)
parent690ea9e8cf3b9c047484a6aea30fa94650fb66c8 (diff)
downloadtor-c93f66b1037e151268b5662f3957d13c4c94d1fb.tar.gz
tor-c93f66b1037e151268b5662f3957d13c4c94d1fb.zip
Merge remote-tracking branch 'public/bug7708_023_v3_squashed'
-rw-r--r--changes/bug77085
-rw-r--r--src/or/connection.c20
2 files changed, 21 insertions, 4 deletions
diff --git a/changes/bug7708 b/changes/bug7708
new file mode 100644
index 0000000000..e272adf227
--- /dev/null
+++ b/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.
diff --git a/src/or/connection.c b/src/or/connection.c
index c1cfbd61f7..0d8242a54e 100644
--- a/src/or/connection.c
+++ b/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.