diff options
Diffstat (limited to 'src/or/connection.c')
-rw-r--r-- | src/or/connection.c | 162 |
1 files changed, 103 insertions, 59 deletions
diff --git a/src/or/connection.c b/src/or/connection.c index 012a3fbd03..97989c07f5 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -544,6 +544,7 @@ _connection_free(connection_t *conn) #ifdef USE_BUFFEREVENTS if (conn->type == CONN_TYPE_OR && TO_OR_CONN(conn)->bucket_cfg) { ev_token_bucket_cfg_free(TO_OR_CONN(conn)->bucket_cfg); + TO_OR_CONN(conn)->bucket_cfg = NULL; } #endif @@ -581,41 +582,6 @@ connection_free(connection_t *conn) _connection_free(conn); } -/** Call _connection_free() on every connection in our array, and release all - * storage held by connection.c. This is used by cpuworkers and dnsworkers - * when they fork, so they don't keep resources held open (especially - * sockets). - * - * Don't do the checks in connection_free(), because they will - * fail. - */ -void -connection_free_all(void) -{ - smartlist_t *conns = get_connection_array(); - - /* We don't want to log any messages to controllers. */ - SMARTLIST_FOREACH(conns, connection_t *, conn, - if (conn->type == CONN_TYPE_CONTROL) - TO_CONTROL_CONN(conn)->event_mask = 0); - - control_update_global_event_mask(); - - /* Unlink everything from the identity map. */ - connection_or_clear_identity_map(); - - /* Clear out our list of broken connections */ - clear_broken_connection_map(0); - - SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn)); - - if (outgoing_addrs) { - SMARTLIST_FOREACH(outgoing_addrs, void*, addr, tor_free(addr)); - smartlist_free(outgoing_addrs); - outgoing_addrs = NULL; - } -} - /** * Called when we're about to finally unlink and free a connection: * perform necessary accounting and cleanup @@ -1042,9 +1008,6 @@ connection_create_listener(const struct sockaddr *listensockaddr, "%s listening on port %u.", conn_type_to_string(type), gotPort); - if (type == CONN_TYPE_CONTROL_LISTENER) - control_ports_write_to_file(); - conn->state = LISTENER_STATE_READY; if (start_reading) { connection_start_reading(conn); @@ -1271,6 +1234,7 @@ connection_init_accepted_conn(connection_t *conn, TO_ENTRY_CONN(conn)->isolation_flags = listener->isolation_flags; TO_ENTRY_CONN(conn)->session_group = listener->session_group; TO_ENTRY_CONN(conn)->nym_epoch = get_signewnym_epoch(); + TO_ENTRY_CONN(conn)->socks_request->listener_type = listener->_base.type; switch (TO_CONN(listener)->type) { case CONN_TYPE_AP_LISTENER: conn->state = AP_CONN_STATE_SOCKS_WAIT; @@ -1841,6 +1805,8 @@ retry_listener_ports(smartlist_t *old_conns, socklen_t listensocklen = 0; char *address=NULL; connection_t *conn; + int real_port = port->port == CFG_AUTO_PORT ? 0 : port->port; + tor_assert(real_port <= UINT16_MAX); if (port->is_unix_addr) { listensockaddr = (struct sockaddr *) @@ -1849,7 +1815,7 @@ retry_listener_ports(smartlist_t *old_conns, } else { listensockaddr = tor_malloc(sizeof(struct sockaddr_storage)); listensocklen = tor_addr_to_sockaddr(&port->addr, - port->port, + real_port, listensockaddr, sizeof(struct sockaddr_storage)); address = tor_dup_addr(&port->addr); @@ -2248,24 +2214,11 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority) return 0; } -#ifndef USE_BUFFEREVENTS -/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes - * onto <b>conn</b>. Decrement buckets appropriately. */ +/** DOCDOC */ static void -connection_buckets_decrement(connection_t *conn, time_t now, - size_t num_read, size_t num_written) +record_num_bytes_transferred_impl(connection_t *conn, + time_t now, size_t num_read, size_t num_written) { - if (num_written >= INT_MAX || num_read >= INT_MAX) { - log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, " - "connection type=%s, state=%s", - (unsigned long)num_read, (unsigned long)num_written, - conn_type_to_string(conn->type), - conn_state_to_string(conn->type, conn->state)); - if (num_written >= INT_MAX) num_written = 1; - if (num_read >= INT_MAX) num_read = 1; - tor_fragile_assert(); - } - /* Count bytes of answering direct and tunneled directory requests */ if (conn->type == CONN_TYPE_DIR && conn->purpose == DIR_PURPOSE_SERVER) { if (num_read > 0) @@ -2289,6 +2242,52 @@ connection_buckets_decrement(connection_t *conn, time_t now, } if (conn->type == CONN_TYPE_EXIT) rep_hist_note_exit_bytes(conn->port, num_written, num_read); +} + +#ifdef USE_BUFFEREVENTS +/** DOCDOC */ +static void +record_num_bytes_transferred(connection_t *conn, + time_t now, size_t num_read, size_t num_written) +{ + /* XXX023 check if this is necessary */ + if (num_written >= INT_MAX || num_read >= INT_MAX) { + log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, " + "connection type=%s, state=%s", + (unsigned long)num_read, (unsigned long)num_written, + conn_type_to_string(conn->type), + conn_state_to_string(conn->type, conn->state)); + if (num_written >= INT_MAX) num_written = 1; + if (num_read >= INT_MAX) num_read = 1; + tor_fragile_assert(); + } + + record_num_bytes_transferred_impl(conn,now,num_read,num_written); +} +#endif + +#ifndef USE_BUFFEREVENTS +/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes + * onto <b>conn</b>. Decrement buckets appropriately. */ +static void +connection_buckets_decrement(connection_t *conn, time_t now, + size_t num_read, size_t num_written) +{ + if (num_written >= INT_MAX || num_read >= INT_MAX) { + log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, " + "connection type=%s, state=%s", + (unsigned long)num_read, (unsigned long)num_written, + conn_type_to_string(conn->type), + conn_state_to_string(conn->type, conn->state)); + if (num_written >= INT_MAX) num_written = 1; + if (num_read >= INT_MAX) num_read = 1; + tor_fragile_assert(); + } + + record_num_bytes_transferred_impl(conn, now, num_read, num_written); + + if (!connection_is_rate_limited(conn)) + return; /* local IPs are free */ if (connection_counts_as_relayed_traffic(conn, now)) { global_relayed_read_bucket -= (int)num_read; @@ -2498,7 +2497,6 @@ connection_bucket_should_increase(int bucket, or_connection_t *conn) return 1; } #else - static void connection_buckets_decrement(connection_t *conn, time_t now, size_t num_read, size_t num_written) @@ -2509,6 +2507,7 @@ connection_buckets_decrement(connection_t *conn, time_t now, (void) num_written; /* Libevent does this for us. */ } + void connection_bucket_refill(int seconds_elapsed, time_t now) { @@ -2564,7 +2563,7 @@ connection_enable_rate_limiting(connection_t *conn) if (conn->bufev) { if (!global_rate_limit) connection_bucket_init(); - bufferevent_add_to_rate_limit_group(conn->bufev, global_rate_limit); + tor_add_bufferevent_to_rate_limit_group(conn->bufev, global_rate_limit); } } @@ -2883,7 +2882,7 @@ evbuffer_inbuf_callback(struct evbuffer *buf, if (info->n_added) { time_t now = approx_time(); conn->timestamp_lastread = now; - connection_buckets_decrement(conn, now, info->n_added, 0); + record_num_bytes_transferred(conn, now, info->n_added, 0); connection_consider_empty_read_buckets(conn); if (conn->type == CONN_TYPE_AP) { edge_connection_t *edge_conn = TO_EDGE_CONN(conn); @@ -2904,7 +2903,7 @@ evbuffer_outbuf_callback(struct evbuffer *buf, if (info->n_deleted) { time_t now = approx_time(); conn->timestamp_lastwritten = now; - connection_buckets_decrement(conn, now, 0, info->n_deleted); + record_num_bytes_transferred(conn, now, 0, info->n_deleted); connection_consider_empty_write_buckets(conn); if (conn->type == CONN_TYPE_AP) { edge_connection_t *edge_conn = TO_EDGE_CONN(conn); @@ -3006,6 +3005,11 @@ connection_configure_bufferevent_callbacks(connection_t *conn) connection_handle_write_cb, connection_handle_event_cb, conn); + /* Set a fairly high write low-watermark so that we get the write callback + called whenever data is written to bring us under 128K. Leave the + high-watermark at 0. + */ + bufferevent_setwatermark(bufev, EV_WRITE, 128*1024, 0); input = bufferevent_get_input(bufev); output = bufferevent_get_output(bufev); @@ -4184,3 +4188,43 @@ proxy_type_to_string(int proxy_type) return NULL; /*Unreached*/ } +/** Call _connection_free() on every connection in our array, and release all + * storage held by connection.c. This is used by cpuworkers and dnsworkers + * when they fork, so they don't keep resources held open (especially + * sockets). + * + * Don't do the checks in connection_free(), because they will + * fail. + */ +void +connection_free_all(void) +{ + smartlist_t *conns = get_connection_array(); + + /* We don't want to log any messages to controllers. */ + SMARTLIST_FOREACH(conns, connection_t *, conn, + if (conn->type == CONN_TYPE_CONTROL) + TO_CONTROL_CONN(conn)->event_mask = 0); + + control_update_global_event_mask(); + + /* Unlink everything from the identity map. */ + connection_or_clear_identity_map(); + + /* Clear out our list of broken connections */ + clear_broken_connection_map(0); + + SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn)); + + if (outgoing_addrs) { + SMARTLIST_FOREACH(outgoing_addrs, void*, addr, tor_free(addr)); + smartlist_free(outgoing_addrs); + outgoing_addrs = NULL; + } + +#ifdef USE_BUFFEREVENTS + if (global_rate_limit) + bufferevent_rate_limit_group_free(global_rate_limit); +#endif +} + |