diff options
Diffstat (limited to 'src/or/connection_or.c')
-rw-r--r-- | src/or/connection_or.c | 99 |
1 files changed, 46 insertions, 53 deletions
diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 8c8094b440..09c9b7c27f 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2013, The Tor Project, Inc. */ + * Copyright (c) 2007-2015, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -38,6 +38,8 @@ #include "router.h" #include "routerlist.h" #include "ext_orport.h" +#include "scheduler.h" + #ifdef USE_BUFFEREVENTS #include <event2/bufferevent_ssl.h> #endif @@ -576,48 +578,51 @@ connection_or_process_inbuf(or_connection_t *conn) return ret; } -/** When adding cells to an OR connection's outbuf, keep adding until the - * outbuf is at least this long, or we run out of cells. */ -#define OR_CONN_HIGHWATER (32*1024) - -/** Add cells to an OR connection's outbuf whenever the outbuf's data length - * drops below this size. */ -#define OR_CONN_LOWWATER (16*1024) - /** Called whenever we have flushed some data on an or_conn: add more data * from active circuits. */ int connection_or_flushed_some(or_connection_t *conn) { - size_t datalen, temp; - ssize_t n, flushed; - size_t cell_network_size = get_cell_network_size(conn->wide_circ_ids); + size_t datalen; + + /* The channel will want to update its estimated queue size */ + channel_update_xmit_queue_size(TLS_CHAN_TO_BASE(conn->chan)); /* If we're under the low water mark, add cells until we're just over the * high water mark. */ datalen = connection_get_outbuf_len(TO_CONN(conn)); if (datalen < OR_CONN_LOWWATER) { - while ((conn->chan) && channel_tls_more_to_flush(conn->chan)) { - /* Compute how many more cells we want at most */ - n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, cell_network_size); - /* Bail out if we don't want any more */ - if (n <= 0) break; - /* We're still here; try to flush some more cells */ - flushed = channel_tls_flush_some_cells(conn->chan, n); - /* Bail out if it says it didn't flush anything */ - if (flushed <= 0) break; - /* How much in the outbuf now? */ - temp = connection_get_outbuf_len(TO_CONN(conn)); - /* Bail out if we didn't actually increase the outbuf size */ - if (temp <= datalen) break; - /* Update datalen for the next iteration */ - datalen = temp; - } + /* Let the scheduler know */ + scheduler_channel_wants_writes(TLS_CHAN_TO_BASE(conn->chan)); } return 0; } +/** This is for channeltls.c to ask how many cells we could accept if + * they were available. */ +ssize_t +connection_or_num_cells_writeable(or_connection_t *conn) +{ + size_t datalen, cell_network_size; + ssize_t n = 0; + + tor_assert(conn); + + /* + * If we're under the high water mark, we're potentially + * writeable; note this is different from the calculation above + * used to trigger when to start writing after we've stopped. + */ + datalen = connection_get_outbuf_len(TO_CONN(conn)); + if (datalen < OR_CONN_HIGHWATER) { + cell_network_size = get_cell_network_size(conn->wide_circ_ids); + n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, cell_network_size); + } + + return n; +} + /** Connection <b>conn</b> has finished writing and has no bytes left on * its outbuf. * @@ -910,18 +915,11 @@ connection_or_init_conn_from_address(or_connection_t *conn, tor_free(conn->base_.address); conn->base_.address = tor_dup_addr(&node_ap.addr); } else { - const char *n; - /* If we're an authoritative directory server, we may know a - * nickname for this router. */ - n = dirserv_get_nickname_by_digest(id_digest); - if (n) { - conn->nickname = tor_strdup(n); - } else { - conn->nickname = tor_malloc(HEX_DIGEST_LEN+2); - conn->nickname[0] = '$'; - base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1, - conn->identity_digest, DIGEST_LEN); - } + conn->nickname = tor_malloc(HEX_DIGEST_LEN+2); + conn->nickname[0] = '$'; + base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1, + conn->identity_digest, DIGEST_LEN); + tor_free(conn->base_.address); conn->base_.address = tor_dup_addr(addr); } @@ -1153,9 +1151,7 @@ connection_or_notify_error(or_connection_t *conn, if (conn->chan) { chan = TLS_CHAN_TO_BASE(conn->chan); /* Don't transition if we're already in closing, closed or error */ - if (!(chan->state == CHANNEL_STATE_CLOSING || - chan->state == CHANNEL_STATE_CLOSED || - chan->state == CHANNEL_STATE_ERROR)) { + if (!CHANNEL_CONDEMNED(chan)) { channel_close_for_error(chan); } } @@ -1178,10 +1174,10 @@ connection_or_notify_error(or_connection_t *conn, * * Return the launched conn, or NULL if it failed. */ -or_connection_t * -connection_or_connect(const tor_addr_t *_addr, uint16_t port, - const char *id_digest, - channel_tls_t *chan) + +MOCK_IMPL(or_connection_t *, +connection_or_connect, (const tor_addr_t *_addr, uint16_t port, + const char *id_digest, channel_tls_t *chan)) { or_connection_t *conn; const or_options_t *options = get_options(); @@ -1314,9 +1310,7 @@ connection_or_close_normally(or_connection_t *orconn, int flush) if (orconn->chan) { chan = TLS_CHAN_TO_BASE(orconn->chan); /* Don't transition if we're already in closing, closed or error */ - if (!(chan->state == CHANNEL_STATE_CLOSING || - chan->state == CHANNEL_STATE_CLOSED || - chan->state == CHANNEL_STATE_ERROR)) { + if (!CHANNEL_CONDEMNED(chan)) { channel_close_from_lower_layer(chan); } } @@ -1337,9 +1331,7 @@ connection_or_close_for_error(or_connection_t *orconn, int flush) if (orconn->chan) { chan = TLS_CHAN_TO_BASE(orconn->chan); /* Don't transition if we're already in closing, closed or error */ - if (!(chan->state == CHANNEL_STATE_CLOSING || - chan->state == CHANNEL_STATE_CLOSED || - chan->state == CHANNEL_STATE_ERROR)) { + if (!CHANNEL_CONDEMNED(chan)) { channel_close_for_error(chan); } } @@ -1829,6 +1821,7 @@ connection_tls_finish_handshake(or_connection_t *conn) conn->base_.port, digest_rcvd, 0); } tor_tls_block_renegotiation(conn->tls); + rep_hist_note_negotiated_link_proto(1, started_here); return connection_or_set_state_open(conn); } else { connection_or_change_state(conn, OR_CONN_STATE_OR_HANDSHAKING_V2); |