mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-20 10:12:15 +01:00
Do round-robin writes of at most 16 kB per write. This might
be more fair on loaded Tor servers, and it might resolve our Windows crash bug. It might also slow things down. svn:r5332
This commit is contained in:
parent
862e8a1bd1
commit
bf2be9abd7
@ -576,21 +576,19 @@ flush_buf_impl(int s, buf_t *buf, size_t sz, size_t *buf_flushlen)
|
||||
return 0;
|
||||
} else {
|
||||
*buf_flushlen -= write_result;
|
||||
|
||||
buf_remove_from_front(buf, write_result);
|
||||
|
||||
return write_result;
|
||||
}
|
||||
}
|
||||
|
||||
/** Write data from <b>buf</b> to the socket <b>s</b>. Write at most
|
||||
* *<b>buf_flushlen</b> bytes, decrement *<b>buf_flushlen</b> by
|
||||
* <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
|
||||
* the number of bytes actually written, and remove the written bytes
|
||||
* from the buffer. Return the number of bytes written on success,
|
||||
* -1 on failure. Return 0 if write() would block.
|
||||
*/
|
||||
int
|
||||
flush_buf(int s, buf_t *buf, size_t *buf_flushlen)
|
||||
flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen)
|
||||
{
|
||||
int r;
|
||||
size_t flushed = 0;
|
||||
@ -600,11 +598,12 @@ flush_buf(int s, buf_t *buf, size_t *buf_flushlen)
|
||||
tor_assert(buf_flushlen);
|
||||
tor_assert(s>=0);
|
||||
tor_assert(*buf_flushlen <= buf->datalen);
|
||||
tor_assert(sz <= *buf_flushlen);
|
||||
|
||||
if (*buf_flushlen == 0) /* nothing to flush */
|
||||
if (sz == 0) /* nothing to flush */
|
||||
return 0;
|
||||
|
||||
flushlen0 = *buf_flushlen;
|
||||
flushlen0 = sz;
|
||||
_split_range(buf, buf->cur, &flushlen0, &flushlen1);
|
||||
|
||||
r = flush_buf_impl(s, buf, flushlen0, buf_flushlen);
|
||||
@ -653,7 +652,7 @@ flush_buf_tls_impl(tor_tls_t *tls, buf_t *buf, size_t sz, size_t *buf_flushlen)
|
||||
/** As flush_buf(), but writes data to a TLS connection.
|
||||
*/
|
||||
int
|
||||
flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t *buf_flushlen)
|
||||
flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t sz, size_t *buf_flushlen)
|
||||
{
|
||||
int r;
|
||||
size_t flushed=0;
|
||||
@ -661,12 +660,14 @@ flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t *buf_flushlen)
|
||||
assert_buf_ok(buf);
|
||||
tor_assert(tls);
|
||||
tor_assert(buf_flushlen);
|
||||
tor_assert(*buf_flushlen <= buf->datalen);
|
||||
tor_assert(sz <= *buf_flushlen);
|
||||
|
||||
/* we want to let tls write even if flushlen is zero, because it might
|
||||
* have a partial record pending */
|
||||
check_no_tls_errors();
|
||||
|
||||
flushlen0 = *buf_flushlen;
|
||||
flushlen0 = sz;
|
||||
_split_range(buf, buf->cur, &flushlen0, &flushlen1);
|
||||
|
||||
r = flush_buf_tls_impl(tls, buf, flushlen0, buf_flushlen);
|
||||
|
@ -23,7 +23,6 @@ static int connection_finished_connecting(connection_t *conn);
|
||||
static int connection_reached_eof(connection_t *conn);
|
||||
static int connection_read_to_buf(connection_t *conn, int *max_to_read);
|
||||
static int connection_process_inbuf(connection_t *conn, int package_partial);
|
||||
static int connection_bucket_read_limit(connection_t *conn);
|
||||
static void client_check_address_changed(int sock);
|
||||
|
||||
static uint32_t last_interface_ip = 0;
|
||||
@ -983,6 +982,29 @@ connection_bucket_read_limit(connection_t *conn)
|
||||
return at_most;
|
||||
}
|
||||
|
||||
/** How many bytes at most can we write onto this connection? */
|
||||
int
|
||||
connection_bucket_write_limit(connection_t *conn)
|
||||
{
|
||||
int at_most;
|
||||
|
||||
/* do a rudimentary round-robin so one circuit can't hog a connection */
|
||||
if (connection_speaks_cells(conn)) {
|
||||
at_most = 32*(CELL_NETWORK_SIZE);
|
||||
} else {
|
||||
at_most = 32*(RELAY_PAYLOAD_SIZE);
|
||||
}
|
||||
|
||||
if (at_most > conn->outbuf_flushlen)
|
||||
at_most = conn->outbuf_flushlen;
|
||||
|
||||
#if 0 /* don't enable til we actually do write limiting */
|
||||
if (at_most > global_write_bucket)
|
||||
at_most = global_write_bucket;
|
||||
#endif
|
||||
return at_most;
|
||||
}
|
||||
|
||||
/** We just read num_read onto conn. Decrement buckets appropriately. */
|
||||
static void
|
||||
connection_read_bucket_decrement(connection_t *conn, int num_read)
|
||||
@ -1317,6 +1339,7 @@ connection_handle_write(connection_t *conn)
|
||||
int e;
|
||||
socklen_t len=sizeof(e);
|
||||
int result;
|
||||
int max_to_write;
|
||||
time_t now = time(NULL);
|
||||
|
||||
tor_assert(!connection_is_listener(conn));
|
||||
@ -1359,6 +1382,8 @@ connection_handle_write(connection_t *conn)
|
||||
return -1;
|
||||
}
|
||||
|
||||
max_to_write = connection_bucket_write_limit(conn);
|
||||
|
||||
if (connection_speaks_cells(conn) && conn->state > OR_CONN_STATE_PROXY_READING) {
|
||||
if (conn->state == OR_CONN_STATE_HANDSHAKING) {
|
||||
connection_stop_writing(conn);
|
||||
@ -1371,7 +1396,8 @@ connection_handle_write(connection_t *conn)
|
||||
}
|
||||
|
||||
/* else open, or closing */
|
||||
result = flush_buf_tls(conn->tls, conn->outbuf, &conn->outbuf_flushlen);
|
||||
result = flush_buf_tls(conn->tls, conn->outbuf,
|
||||
max_to_write, &conn->outbuf_flushlen);
|
||||
switch (result) {
|
||||
case TOR_TLS_ERROR:
|
||||
case TOR_TLS_CLOSE:
|
||||
@ -1403,7 +1429,8 @@ connection_handle_write(connection_t *conn)
|
||||
}
|
||||
} else {
|
||||
CONN_LOG_PROTECT(conn,
|
||||
result = flush_buf(conn->s, conn->outbuf, &conn->outbuf_flushlen));
|
||||
result = flush_buf(conn->s, conn->outbuf,
|
||||
max_to_write, &conn->outbuf_flushlen));
|
||||
if (result < 0) {
|
||||
if (CONN_IS_EDGE(conn))
|
||||
connection_edge_end_errno(conn, conn->cpath_layer);
|
||||
@ -1429,7 +1456,8 @@ connection_handle_write(connection_t *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DOCDOC */
|
||||
/* A controller event has just happened with such urgency that we
|
||||
* need to write it onto controller <b>conn</b> immediately. */
|
||||
void
|
||||
_connection_controller_force_write(connection_t *conn)
|
||||
{
|
||||
@ -1445,7 +1473,8 @@ _connection_controller_force_write(connection_t *conn)
|
||||
return;
|
||||
|
||||
CONN_LOG_PROTECT(conn,
|
||||
result = flush_buf(conn->s, conn->outbuf, &conn->outbuf_flushlen));
|
||||
result = flush_buf(conn->s, conn->outbuf,
|
||||
conn->outbuf_flushlen, &conn->outbuf_flushlen));
|
||||
if (result < 0) {
|
||||
connection_close_immediate(conn); /* Don't flush; connection is dead. */
|
||||
connection_mark_for_close(conn);
|
||||
|
@ -439,8 +439,9 @@ conn_close_if_marked(int i)
|
||||
|
||||
debug(LD_NET,"Cleaning up connection (fd %d).",conn->s);
|
||||
if (conn->s >= 0 && connection_wants_to_flush(conn)) {
|
||||
/* -1 means it's an incomplete edge connection, or that the socket
|
||||
/* s == -1 means it's an incomplete edge connection, or that the socket
|
||||
* has already been closed as unflushable. */
|
||||
int sz = connection_bucket_write_limit(conn);
|
||||
if (!conn->hold_open_until_flushed)
|
||||
info(LD_NET,
|
||||
"Conn (addr %s, fd %d, type %s, state %d) marked, but wants to flush %d bytes. "
|
||||
@ -449,14 +450,15 @@ conn_close_if_marked(int i)
|
||||
(int)conn->outbuf_flushlen, conn->marked_for_close_file, conn->marked_for_close);
|
||||
if (connection_speaks_cells(conn)) {
|
||||
if (conn->state == OR_CONN_STATE_OPEN) {
|
||||
retval = flush_buf_tls(conn->tls, conn->outbuf, &conn->outbuf_flushlen);
|
||||
retval = flush_buf_tls(conn->tls, conn->outbuf, sz, &conn->outbuf_flushlen);
|
||||
} else
|
||||
retval = -1; /* never flush non-open broken tls connections */
|
||||
} else {
|
||||
retval = flush_buf(conn->s, conn->outbuf, &conn->outbuf_flushlen);
|
||||
retval = flush_buf(conn->s, conn->outbuf, sz, &conn->outbuf_flushlen);
|
||||
}
|
||||
if (retval >= 0 &&
|
||||
conn->hold_open_until_flushed && connection_wants_to_flush(conn)) {
|
||||
if (retval >= 0 && /* Technically, we could survive things like
|
||||
TLS_WANT_WRITE here. But don't bother for now. */
|
||||
conn->hold_open_until_flushed && connection_wants_to_flush(conn)) {
|
||||
LOG_FN_CONN(conn,
|
||||
(LOG_INFO,LD_NET,"Holding conn (fd %d) open for more flushing.",conn->s));
|
||||
/* XXX should we reset timestamp_lastwritten here? */
|
||||
|
@ -1363,8 +1363,8 @@ const char *_buf_peek_raw_buffer(const buf_t *buf);
|
||||
int read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof);
|
||||
int read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf);
|
||||
|
||||
int flush_buf(int s, buf_t *buf, size_t *buf_flushlen);
|
||||
int flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t *buf_flushlen);
|
||||
int flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen);
|
||||
int flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t sz, size_t *buf_flushlen);
|
||||
|
||||
int write_to_buf(const char *string, size_t string_len, buf_t *buf);
|
||||
int fetch_from_buf(char *string, size_t string_len, buf_t *buf);
|
||||
@ -1541,6 +1541,7 @@ int connection_connect(connection_t *conn, char *address, uint32_t addr, uint16_
|
||||
int retry_all_listeners(int force, smartlist_t *replaced_conns,
|
||||
smartlist_t *new_conns);
|
||||
|
||||
int connection_bucket_write_limit(connection_t *conn);
|
||||
void connection_bucket_init(void);
|
||||
void connection_bucket_refill(struct timeval *now);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user