aboutsummaryrefslogtreecommitdiff
path: root/src/core/mainloop/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/mainloop/connection.c')
-rw-r--r--src/core/mainloop/connection.c407
1 files changed, 297 insertions, 110 deletions
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 36b2c6ef63..ada542629a 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -82,6 +82,7 @@
#include "core/or/policies.h"
#include "core/or/reasons.h"
#include "core/or/relay.h"
+#include "core/or/status.h"
#include "core/or/crypt_path.h"
#include "core/proto/proto_haproxy.h"
#include "core/proto/proto_http.h"
@@ -98,6 +99,8 @@
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_common.h"
#include "feature/hs/hs_ident.h"
+#include "feature/hs/hs_metrics.h"
+#include "feature/metrics/metrics.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/relay/dns.h"
@@ -105,8 +108,11 @@
#include "feature/relay/routermode.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
+#include "feature/stats/connstats.h"
#include "feature/stats/rephist.h"
+#include "feature/stats/bwhist.h"
#include "lib/crypt_ops/crypto_util.h"
+#include "lib/crypt_ops/crypto_format.h"
#include "lib/geoip/geoip.h"
#include "lib/cc/ctassert.h"
@@ -214,12 +220,17 @@ static smartlist_t *outgoing_addrs = NULL;
case CONN_TYPE_AP_TRANS_LISTENER: \
case CONN_TYPE_AP_NATD_LISTENER: \
case CONN_TYPE_AP_DNS_LISTENER: \
- case CONN_TYPE_AP_HTTP_CONNECT_LISTENER
+ case CONN_TYPE_AP_HTTP_CONNECT_LISTENER: \
+ case CONN_TYPE_METRICS_LISTENER
/**************************************************************/
-/** Convert a connection_t* to an listener_connection_t*; assert if the cast
- * is invalid. */
+/**
+ * Cast a `connection_t *` to a `listener_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not a
+ * `listener_connection_t`.
+ **/
listener_connection_t *
TO_LISTENER_CONN(connection_t *c)
{
@@ -227,6 +238,18 @@ TO_LISTENER_CONN(connection_t *c)
return DOWNCAST(listener_connection_t, c);
}
+/**
+ * Cast a `const connection_t *` to a `const listener_connection_t *`.
+ *
+ * Exit with an assertion failure if the input is not a
+ * `listener_connection_t`.
+ **/
+const listener_connection_t *
+CONST_TO_LISTENER_CONN(const connection_t *c)
+{
+ return TO_LISTENER_CONN((connection_t *)c);
+}
+
size_t
connection_get_inbuf_len(connection_t *conn)
{
@@ -263,6 +286,8 @@ conn_type_to_string(int type)
case CONN_TYPE_EXT_OR: return "Extended OR";
case CONN_TYPE_EXT_OR_LISTENER: return "Extended OR listener";
case CONN_TYPE_AP_HTTP_CONNECT_LISTENER: return "HTTP tunnel listener";
+ case CONN_TYPE_METRICS_LISTENER: return "Metrics listener";
+ case CONN_TYPE_METRICS: return "Metrics";
default:
log_warn(LD_BUG, "unknown connection type %d", type);
tor_snprintf(buf, sizeof(buf), "unknown [%d]", type);
@@ -350,13 +375,187 @@ conn_state_to_string(int type, int state)
break;
}
+ if (state == 0) {
+ return "uninitialized";
+ }
+
log_warn(LD_BUG, "unknown connection state %d (type %d)", state, type);
tor_snprintf(buf, sizeof(buf),
"unknown state [%d] on unknown [%s] connection",
state, conn_type_to_string(type));
+ tor_assert_nonfatal_unreached_once();
return buf;
}
+/**
+ * Helper: describe the peer or address of connection @a conn in a
+ * human-readable manner.
+ *
+ * Returns a pointer to a static buffer; future calls to
+ * connection_describe_peer_internal() will invalidate this buffer.
+ *
+ * If <b>include_preposition</b> is true, include a preposition before the
+ * peer address.
+ *
+ * Nobody should parse the output of this function; it can and will change in
+ * future versions of tor.
+ **/
+static const char *
+connection_describe_peer_internal(const connection_t *conn,
+ bool include_preposition)
+{
+ IF_BUG_ONCE(!conn) {
+ return "null peer";
+ }
+
+ static char peer_buf[256];
+ const tor_addr_t *addr = &conn->addr;
+ const char *address = NULL;
+ const char *prep;
+ bool scrub = false;
+ char extra_buf[128];
+ extra_buf[0] = 0;
+
+ /* First, figure out the preposition to use */
+ switch (conn->type) {
+ CASE_ANY_LISTENER_TYPE:
+ prep = "on";
+ break;
+ case CONN_TYPE_EXIT:
+ prep = "to";
+ break;
+ case CONN_TYPE_CONTROL:
+ case CONN_TYPE_AP:
+ case CONN_TYPE_EXT_OR:
+ prep = "from";
+ break;
+ default:
+ prep = "with";
+ break;
+ }
+
+ /* Now figure out the address. */
+ if (conn->socket_family == AF_UNIX) {
+ /* For unix sockets, we always use the `address` string. */
+ address = conn->address ? conn->address : "unix socket";
+ } else if (conn->type == CONN_TYPE_OR) {
+ /* For OR connections, we have a lot to do. */
+ const or_connection_t *or_conn = CONST_TO_OR_CONN(conn);
+ /* We report the IDs we're talking to... */
+ if (fast_digest_is_zero(or_conn->identity_digest)) {
+ // This could be a client, so scrub it. No identity to report.
+ scrub = true;
+ } else {
+ const ed25519_public_key_t *ed_id =
+ connection_or_get_alleged_ed25519_id(or_conn);
+ char ed_id_buf[ED25519_BASE64_LEN+1];
+ char rsa_id_buf[HEX_DIGEST_LEN+1];
+ if (ed_id) {
+ ed25519_public_to_base64(ed_id_buf, ed_id);
+ } else {
+ strlcpy(ed_id_buf, "<none>", sizeof(ed_id_buf));
+ }
+ base16_encode(rsa_id_buf, sizeof(rsa_id_buf),
+ or_conn->identity_digest, DIGEST_LEN);
+ tor_snprintf(extra_buf, sizeof(extra_buf),
+ " ID=%s RSA_ID=%s", ed_id_buf, rsa_id_buf);
+ }
+ if (! scrub && (! tor_addr_eq(addr, &or_conn->canonical_orport.addr) ||
+ conn->port != or_conn->canonical_orport.port)) {
+ /* We report canonical address, if it's different */
+ char canonical_addr_buf[TOR_ADDR_BUF_LEN];
+ if (tor_addr_to_str(canonical_addr_buf, &or_conn->canonical_orport.addr,
+ sizeof(canonical_addr_buf), 1)) {
+ tor_snprintf(extra_buf+strlen(extra_buf),
+ sizeof(extra_buf)-strlen(extra_buf),
+ " canonical_addr=%s:%"PRIu16,
+ canonical_addr_buf,
+ or_conn->canonical_orport.port);
+ }
+ }
+ } else if (conn->type == CONN_TYPE_EXIT) {
+ scrub = true; /* This is a client's request; scrub it with SafeLogging. */
+ if (tor_addr_is_null(addr)) {
+ address = conn->address;
+ strlcpy(extra_buf, " (DNS lookup pending)", sizeof(extra_buf));
+ }
+ }
+
+ char addr_buf[TOR_ADDR_BUF_LEN];
+ if (address == NULL) {
+ if (tor_addr_family(addr) == 0) {
+ address = "<unset>";
+ } else {
+ address = tor_addr_to_str(addr_buf, addr, sizeof(addr_buf), 1);
+ if (!address) {
+ address = "<can't format!>";
+ tor_assert_nonfatal_unreached_once();
+ }
+ }
+ }
+
+ char portbuf[7];
+ portbuf[0]=0;
+ if (scrub && get_options()->SafeLogging_ != SAFELOG_SCRUB_NONE) {
+ address = "[scrubbed]";
+ } else {
+ /* Only set the port if we're not scrubbing the address. */
+ if (conn->port != 0) {
+ tor_snprintf(portbuf, sizeof(portbuf), ":%d", conn->port);
+ }
+ }
+
+ const char *sp = include_preposition ? " " : "";
+ if (! include_preposition)
+ prep = "";
+
+ tor_snprintf(peer_buf, sizeof(peer_buf),
+ "%s%s%s%s%s", prep, sp, address, portbuf, extra_buf);
+ return peer_buf;
+}
+
+/**
+ * Describe the peer or address of connection @a conn in a
+ * human-readable manner.
+ *
+ * Returns a pointer to a static buffer; future calls to
+ * connection_describe_peer() or connection_describe() will invalidate this
+ * buffer.
+ *
+ * Nobody should parse the output of this function; it can and will change in
+ * future versions of tor.
+ **/
+const char *
+connection_describe_peer(const connection_t *conn)
+{
+ return connection_describe_peer_internal(conn, false);
+}
+
+/**
+ * Describe a connection for logging purposes.
+ *
+ * Returns a pointer to a static buffer; future calls to connection_describe()
+ * will invalidate this buffer.
+ *
+ * Nobody should parse the output of this function; it can and will change in
+ * future versions of tor.
+ **/
+const char *
+connection_describe(const connection_t *conn)
+{
+ IF_BUG_ONCE(!conn) {
+ return "null connection";
+ }
+ static char desc_buf[256];
+ const char *peer = connection_describe_peer_internal(conn, true);
+ tor_snprintf(desc_buf, sizeof(desc_buf),
+ "%s connection (%s) %s",
+ conn_type_to_string(conn->type),
+ conn_state_to_string(conn->type, conn->state),
+ peer);
+ return desc_buf;
+}
+
/** Allocate and return a new dir_connection_t, initialized as by
* connection_init(). */
dir_connection_t *
@@ -382,6 +581,7 @@ or_connection_new(int type, int socket_family)
tor_assert(type == CONN_TYPE_OR || type == CONN_TYPE_EXT_OR);
connection_init(now, TO_CONN(or_conn), type, socket_family);
+ tor_addr_make_unspec(&or_conn->canonical_orport.addr);
connection_or_set_canonical(or_conn, 0);
if (type == CONN_TYPE_EXT_OR) {
@@ -852,11 +1052,11 @@ connection_close_immediate(connection_t *conn)
tor_fragile_assert();
return;
}
- if (conn->outbuf_flushlen) {
- log_info(LD_NET,"fd %d, type %s, state %s, %d bytes on outbuf.",
+ if (connection_get_outbuf_len(conn)) {
+ log_info(LD_NET,"fd %d, type %s, state %s, %"TOR_PRIuSZ" bytes on outbuf.",
(int)conn->s, conn_type_to_string(conn->type),
conn_state_to_string(conn->type, conn->state),
- (int)conn->outbuf_flushlen);
+ buf_datalen(conn->outbuf));
}
connection_unregister_events(conn);
@@ -872,7 +1072,6 @@ connection_close_immediate(connection_t *conn)
conn->linked_conn_is_closed = 1;
if (conn->outbuf)
buf_clear(conn->outbuf);
- conn->outbuf_flushlen = 0;
}
/** Mark <b>conn</b> to be closed next time we loop through
@@ -1549,13 +1748,8 @@ connection_listener_new(const struct sockaddr *listensockaddr,
*/
connection_check_oos(get_n_open_sockets(), 0);
- if (conn->socket_family == AF_UNIX) {
- log_notice(LD_NET, "Opened %s on %s",
- conn_type_to_string(type), conn->address);
- } else {
- log_notice(LD_NET, "Opened %s on %s",
- conn_type_to_string(type), fmt_addrport(&addr, gotPort));
- }
+ log_notice(LD_NET, "Opened %s", connection_describe(conn));
+
return conn;
err:
@@ -1836,6 +2030,10 @@ connection_handle_listener_read(connection_t *conn, int new_type)
log_notice(LD_CONTROL, "New control connection opened from %s.",
fmt_and_decorate_addr(&addr));
}
+ if (new_type == CONN_TYPE_METRICS) {
+ log_info(LD_CONTROL, "New metrics connection opened from %s.",
+ fmt_and_decorate_addr(&addr));
+ }
} else if (conn->socket_family == AF_UNIX && conn->type != CONN_TYPE_AP) {
tor_assert(conn->type == CONN_TYPE_CONTROL_LISTENER);
@@ -1863,6 +2061,9 @@ connection_handle_listener_read(connection_t *conn, int new_type)
connection_mark_for_close(newconn);
return 0;
}
+
+ note_connection(true /* inbound */, conn->socket_family);
+
return 0;
}
@@ -2034,6 +2235,8 @@ connection_connect_sockaddr,(connection_t *conn,
}
}
+ note_connection(false /* outbound */, conn->socket_family);
+
/* it succeeded. we're connected. */
log_fn(inprogress ? LOG_DEBUG : LOG_INFO, LD_NET,
"Connection to socket %s (sock "TOR_SOCKET_T_FORMAT").",
@@ -2067,22 +2270,13 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
return;
}
- const int must_ipv4 = !fascist_firewall_use_ipv6(options);
+ const int must_ipv4 = !reachable_addr_use_ipv6(options);
const int must_ipv6 = (options->ClientUseIPv4 == 0);
const int pref_ipv6 = (conn->type == CONN_TYPE_OR
- ? fascist_firewall_prefer_ipv6_orport(options)
- : fascist_firewall_prefer_ipv6_dirport(options));
+ ? reachable_addr_prefer_ipv6_orport(options)
+ : reachable_addr_prefer_ipv6_dirport(options));
tor_addr_t real_addr;
- tor_addr_make_null(&real_addr, AF_UNSPEC);
-
- /* OR conns keep the original address in real_addr, as addr gets overwritten
- * with the descriptor address */
- if (conn->type == CONN_TYPE_OR) {
- const or_connection_t *or_conn = TO_OR_CONN((connection_t *)conn);
- tor_addr_copy(&real_addr, &or_conn->real_addr);
- } else if (conn->type == CONN_TYPE_DIR) {
- tor_addr_copy(&real_addr, &conn->addr);
- }
+ tor_addr_copy(&real_addr, &conn->addr);
/* Check if we broke a mandatory address family restriction */
if ((must_ipv4 && tor_addr_family(&real_addr) == AF_INET6)
@@ -2105,7 +2299,7 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
return;
}
- if (fascist_firewall_use_ipv6(options)) {
+ if (reachable_addr_use_ipv6(options)) {
log_info(LD_NET, "Our outgoing connection is using IPv%d.",
tor_addr_family(&real_addr) == AF_INET6 ? 6 : 4);
}
@@ -2115,13 +2309,13 @@ connection_connect_log_client_use_ip_version(const connection_t *conn)
|| (pref_ipv6 && tor_addr_family(&real_addr) == AF_INET)) {
log_info(LD_NET, "Outgoing connection to %s doesn't satisfy "
"ClientPreferIPv6%sPort %d, with ClientUseIPv4 %d, and "
- "fascist_firewall_use_ipv6 %d (ClientUseIPv6 %d and UseBridges "
+ "reachable_addr_use_ipv6 %d (ClientUseIPv6 %d and UseBridges "
"%d).",
fmt_addr(&real_addr),
conn->type == CONN_TYPE_OR ? "OR" : "Dir",
conn->type == CONN_TYPE_OR ? options->ClientPreferIPv6ORPort
: options->ClientPreferIPv6DirPort,
- options->ClientUseIPv4, fascist_firewall_use_ipv6(options),
+ options->ClientUseIPv4, reachable_addr_use_ipv6(options),
options->ClientUseIPv6, options->UseBridges);
}
}
@@ -2155,9 +2349,9 @@ conn_get_outbound_address(sa_family_t family,
ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT]
[fam_index];
} else if (!tor_addr_is_null(
- &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index])) {
- ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index];
}
} else { // All non-exit connections
@@ -2166,9 +2360,9 @@ conn_get_outbound_address(sa_family_t family,
ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_OR]
[fam_index];
} else if (!tor_addr_is_null(
- &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index])) {
- ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_EXIT_AND_OR]
+ ext_addr = &options->OutboundBindAddresses[OUTBOUND_ADDR_ANY]
[fam_index];
}
}
@@ -2608,8 +2802,8 @@ connection_read_https_proxy_response(connection_t *conn)
if (parse_http_response(headers, &status_code, &date_header,
NULL, &reason) < 0) {
log_warn(LD_NET,
- "Unparseable headers from proxy (connecting to '%s'). Closing.",
- conn->address);
+ "Unparseable headers from proxy (%s). Closing.",
+ connection_describe(conn));
tor_free(headers);
return -1;
}
@@ -2618,8 +2812,8 @@ connection_read_https_proxy_response(connection_t *conn)
if (status_code == 200) {
log_info(LD_NET,
- "HTTPS connect to '%s' successful! (200 %s) Starting TLS.",
- conn->address, escaped(reason));
+ "HTTPS connect for %s successful! (200 %s) Starting TLS.",
+ connection_describe(conn), escaped(reason));
tor_free(reason);
return 1;
}
@@ -2835,16 +3029,16 @@ connection_read_proxy_handshake(connection_t *conn)
if (ret < 0) {
if (reason) {
- log_warn(LD_NET, "Proxy Client: unable to connect to %s:%d (%s)",
- conn->address, conn->port, escaped(reason));
+ log_warn(LD_NET, "Proxy Client: unable to connect %s (%s)",
+ connection_describe(conn), escaped(reason));
tor_free(reason);
} else {
- log_warn(LD_NET, "Proxy Client: unable to connect to %s:%d",
- conn->address, conn->port);
+ log_warn(LD_NET, "Proxy Client: unable to connect %s",
+ connection_describe(conn));
}
} else if (ret == 1) {
- log_info(LD_NET, "Proxy Client: connection to %s:%d successful",
- conn->address, conn->port);
+ log_info(LD_NET, "Proxy Client: %s successful",
+ connection_describe(conn));
}
return ret;
@@ -3001,10 +3195,10 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol)
smartlist_t *replacements = smartlist_new();
const or_options_t *options = get_options();
int retval = 0;
- const uint16_t old_or_port = router_get_advertised_or_port(options);
+ const uint16_t old_or_port = routerconf_find_or_port(options, AF_INET);
const uint16_t old_or_port_ipv6 =
- router_get_advertised_or_port_by_af(options,AF_INET6);
- const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0);
+ routerconf_find_or_port(options,AF_INET6);
+ const uint16_t old_dir_port = routerconf_find_dir_port(options, 0);
SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
if (connection_is_listener(conn) && !conn->marked_for_close)
@@ -3035,8 +3229,8 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol)
connection_t *old_conn = r->old_conn;
if (skip) {
- log_debug(LD_NET, "Skipping creating new listener for %s:%d",
- old_conn->address, old_conn->port);
+ log_debug(LD_NET, "Skipping creating new listener for %s",
+ connection_describe(old_conn));
continue;
}
@@ -3059,10 +3253,11 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol)
smartlist_add(new_conns, new_conn);
- log_notice(LD_NET, "Closed no-longer-configured %s on %s:%d "
- "(replaced by %s:%d)",
- conn_type_to_string(old_conn->type), old_conn->address,
- old_conn->port, new_conn->address, new_conn->port);
+ char *old_desc = tor_strdup(connection_describe(old_conn));
+ log_notice(LD_NET, "Closed no-longer-configured %s "
+ "(replaced by %s)",
+ old_desc, connection_describe(new_conn));
+ tor_free(old_desc);
} SMARTLIST_FOREACH_END(r);
#endif /* defined(ENABLE_LISTENER_REBIND) */
@@ -3080,10 +3275,9 @@ retry_all_listeners(smartlist_t *new_conns, int close_all_noncontrol)
SMARTLIST_FOREACH(replacements, listener_replacement_t *, r, tor_free(r));
smartlist_free(replacements);
- if (old_or_port != router_get_advertised_or_port(options) ||
- old_or_port_ipv6 != router_get_advertised_or_port_by_af(options,
- AF_INET6) ||
- old_dir_port != router_get_advertised_dir_port(options, 0)) {
+ if (old_or_port != routerconf_find_or_port(options, AF_INET) ||
+ old_or_port_ipv6 != routerconf_find_or_port(options, AF_INET6) ||
+ old_dir_port != routerconf_find_dir_port(options, 0)) {
/* Our chosen ORPort or DirPort is not what it used to be: the
* descriptor we had (if any) should be regenerated. (We won't
* automatically notice this because of changes in the option,
@@ -3261,12 +3455,12 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
{
int base = RELAY_PAYLOAD_SIZE;
int priority = conn->type != CONN_TYPE_DIR;
- size_t conn_bucket = conn->outbuf_flushlen;
+ size_t conn_bucket = buf_datalen(conn->outbuf);
size_t global_bucket_val = token_bucket_rw_get_write(&global_bucket);
if (!connection_is_rate_limited(conn)) {
/* be willing to write to local conns even if our buckets are empty */
- return conn->outbuf_flushlen;
+ return conn_bucket;
}
if (connection_speaks_cells(conn)) {
@@ -3356,9 +3550,9 @@ record_num_bytes_transferred_impl(connection_t *conn,
/* Count bytes of answering direct and tunneled directory requests */
if (conn->type == CONN_TYPE_DIR && conn->purpose == DIR_PURPOSE_SERVER) {
if (num_read > 0)
- rep_hist_note_dir_bytes_read(num_read, now);
+ bwhist_note_dir_bytes_read(num_read, now);
if (num_written > 0)
- rep_hist_note_dir_bytes_written(num_written, now);
+ bwhist_note_dir_bytes_written(num_written, now);
}
/* Linked connections and internal IPs aren't counted for statistics or
@@ -3373,15 +3567,16 @@ record_num_bytes_transferred_impl(connection_t *conn,
if (!connection_is_rate_limited(conn))
return;
+ const bool is_ipv6 = (conn->socket_family == AF_INET6);
if (conn->type == CONN_TYPE_OR)
- rep_hist_note_or_conn_bytes(conn->global_identifier, num_read,
- num_written, now);
+ conn_stats_note_or_conn_bytes(conn->global_identifier, num_read,
+ num_written, now, is_ipv6);
if (num_read > 0) {
- rep_hist_note_bytes_read(num_read, now);
+ bwhist_note_bytes_read(num_read, now, is_ipv6);
}
if (num_written > 0) {
- rep_hist_note_bytes_written(num_written, now);
+ bwhist_note_bytes_written(num_written, now, is_ipv6);
}
if (conn->type == CONN_TYPE_EXIT)
rep_hist_note_exit_bytes(conn->port, num_written, num_read);
@@ -3707,6 +3902,8 @@ connection_handle_read_impl(connection_t *conn)
return connection_handle_listener_read(conn, CONN_TYPE_DIR);
case CONN_TYPE_CONTROL_LISTENER:
return connection_handle_listener_read(conn, CONN_TYPE_CONTROL);
+ case CONN_TYPE_METRICS_LISTENER:
+ return connection_handle_listener_read(conn, CONN_TYPE_METRICS);
case CONN_TYPE_AP_DNS_LISTENER:
/* This should never happen; eventdns.c handles the reads here. */
tor_fragile_assert();
@@ -3870,17 +4067,14 @@ connection_buf_read_from_socket(connection_t *conn, ssize_t *max_to_read,
switch (result) {
case TOR_TLS_CLOSE:
case TOR_TLS_ERROR_IO:
- log_debug(LD_NET,"TLS connection closed %son read. Closing. "
- "(Nickname %s, address %s)",
- result == TOR_TLS_CLOSE ? "cleanly " : "",
- or_conn->nickname ? or_conn->nickname : "not set",
- conn->address);
+ log_debug(LD_NET,"TLS %s closed %son read. Closing.",
+ connection_describe(conn),
+ result == TOR_TLS_CLOSE ? "cleanly " : "");
return result;
CASE_TOR_TLS_ERROR_ANY_NONIO:
- log_debug(LD_NET,"tls error [%s]. breaking (nickname %s, address %s).",
+ log_debug(LD_NET,"tls error [%s] from %s. Breaking.",
tor_tls_err_to_string(result),
- or_conn->nickname ? or_conn->nickname : "not set",
- conn->address);
+ connection_describe(conn));
return result;
case TOR_TLS_WANTWRITE:
connection_start_writing(conn);
@@ -3921,12 +4115,7 @@ connection_buf_read_from_socket(connection_t *conn, ssize_t *max_to_read,
result, (long)n_read, (long)n_written);
} else if (conn->linked) {
if (conn->linked_conn) {
- result = buf_move_to_buf(conn->inbuf, conn->linked_conn->outbuf,
- &conn->linked_conn->outbuf_flushlen);
- if (BUG(result<0)) {
- log_warn(LD_BUG, "reading from linked connection buffer failed.");
- return -1;
- }
+ result = (int) buf_move_all(conn->inbuf, conn->linked_conn->outbuf);
} else {
result = 0;
}
@@ -3961,6 +4150,14 @@ connection_buf_read_from_socket(connection_t *conn, ssize_t *max_to_read,
/* change *max_to_read */
*max_to_read = at_most - n_read;
+ /* Onion service application connection. Note read bytes for metrics. */
+ if (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->hs_ident) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ hs_metrics_app_read_bytes(&edge_conn->hs_ident->identity_pk,
+ edge_conn->hs_ident->orig_virtual_port,
+ n_read);
+ }
+
/* Update edge_conn->n_read */
if (conn->type == CONN_TYPE_AP) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
@@ -4030,12 +4227,11 @@ connection_fetch_from_buf_http(connection_t *conn,
body_out, body_used, max_bodylen, force_complete);
}
-/** Return conn-\>outbuf_flushlen: how many bytes conn wants to flush
- * from its outbuf. */
+/** Return true if this connection has data to flush. */
int
connection_wants_to_flush(connection_t *conn)
{
- return conn->outbuf_flushlen > 0;
+ return connection_get_outbuf_len(conn) > 0;
}
/** Are there too many bytes on edge connection <b>conn</b>'s outbuf to
@@ -4045,7 +4241,7 @@ connection_wants_to_flush(connection_t *conn)
int
connection_outbuf_too_full(connection_t *conn)
{
- return (conn->outbuf_flushlen > 10*CELL_PAYLOAD_SIZE);
+ return connection_get_outbuf_len(conn) > 10*CELL_PAYLOAD_SIZE;
}
/**
@@ -4171,7 +4367,7 @@ connection_handle_write_impl(connection_t *conn, int force)
return -1;
}
- max_to_write = force ? (ssize_t)conn->outbuf_flushlen
+ max_to_write = force ? (ssize_t)buf_datalen(conn->outbuf)
: connection_bucket_write_limit(conn, now);
if (connection_speaks_cells(conn) &&
@@ -4203,7 +4399,7 @@ connection_handle_write_impl(connection_t *conn, int force)
/* else open, or closing */
initial_size = buf_datalen(conn->outbuf);
result = buf_flush_to_tls(conn->outbuf, or_conn->tls,
- max_to_write, &conn->outbuf_flushlen);
+ max_to_write);
if (result >= 0)
update_send_buffer_size(conn->s);
@@ -4269,7 +4465,7 @@ connection_handle_write_impl(connection_t *conn, int force)
} else {
CONN_LOG_PROTECT(conn,
result = buf_flush_to_socket(conn->outbuf, conn->s,
- max_to_write, &conn->outbuf_flushlen));
+ max_to_write));
if (result < 0) {
if (CONN_IS_EDGE(conn))
connection_edge_end_errno(TO_EDGE_CONN(conn));
@@ -4425,10 +4621,10 @@ connection_write_to_buf_failed(connection_t *conn)
/** Helper for connection_write_to_buf_impl and connection_write_buf_to_buf:
*
* Called when an attempt to add bytes on <b>conn</b>'s outbuf has succeeded:
- * record the number of bytes added.
+ * start writing if appropriate.
*/
static void
-connection_write_to_buf_commit(connection_t *conn, size_t len)
+connection_write_to_buf_commit(connection_t *conn)
{
/* If we receive optimistic data in the EXIT_CONN_STATE_RESOLVING
* state, we don't want to try to write it right away, since
@@ -4437,7 +4633,6 @@ connection_write_to_buf_commit(connection_t *conn, size_t len)
if (conn->write_event) {
connection_start_writing(conn);
}
- conn->outbuf_flushlen += len;
}
/** Append <b>len</b> bytes of <b>string</b> onto <b>conn</b>'s
@@ -4460,25 +4655,20 @@ connection_write_to_buf_impl_,(const char *string, size_t len,
if (!connection_may_write_to_buf(conn))
return;
- size_t written;
-
if (zlib) {
- size_t old_datalen = buf_datalen(conn->outbuf);
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
int done = zlib < 0;
CONN_LOG_PROTECT(conn, r = buf_add_compress(conn->outbuf,
dir_conn->compress_state,
string, len, done));
- written = buf_datalen(conn->outbuf) - old_datalen;
} else {
CONN_LOG_PROTECT(conn, r = buf_add(conn->outbuf, string, len));
- written = len;
}
if (r < 0) {
connection_write_to_buf_failed(conn);
return;
}
- connection_write_to_buf_commit(conn, written);
+ connection_write_to_buf_commit(conn);
}
/**
@@ -4523,7 +4713,7 @@ connection_buf_add_buf(connection_t *conn, buf_t *buf)
return;
buf_move_all(conn->outbuf, buf);
- connection_write_to_buf_commit(conn, len);
+ connection_write_to_buf_commit(conn);
}
#define CONN_GET_ALL_TEMPLATE(var, test) \
@@ -4733,7 +4923,7 @@ any_other_active_or_conns(const or_connection_t *this_conn)
connection_t *conn = connection_get_another_active_or_conn(this_conn);
if (conn != NULL) {
log_debug(LD_DIR, "%s: Found an OR connection: %s",
- __func__, conn->address);
+ __func__, connection_describe(conn));
return 1;
}
@@ -4883,7 +5073,7 @@ client_check_address_changed(tor_socket_t sock)
smartlist_clear(outgoing_addrs);
smartlist_add(outgoing_addrs, tor_memdup(&out_addr, sizeof(tor_addr_t)));
/* We'll need to resolve ourselves again. */
- reset_last_resolved_addr();
+ resolved_addr_reset_last(AF_INET);
/* Okay, now change our keys. */
ip_address_changed(1);
}
@@ -4937,6 +5127,8 @@ connection_process_inbuf(connection_t *conn, int package_partial)
return connection_dir_process_inbuf(TO_DIR_CONN(conn));
case CONN_TYPE_CONTROL:
return connection_control_process_inbuf(TO_CONTROL_CONN(conn));
+ case CONN_TYPE_METRICS:
+ return metrics_connection_process_inbuf(conn);
default:
log_err(LD_BUG,"got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -4995,6 +5187,8 @@ connection_finished_flushing(connection_t *conn)
return connection_dir_finished_flushing(TO_DIR_CONN(conn));
case CONN_TYPE_CONTROL:
return connection_control_finished_flushing(TO_CONTROL_CONN(conn));
+ case CONN_TYPE_METRICS:
+ return metrics_connection_finished_flushing(conn);
default:
log_err(LD_BUG,"got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -5050,6 +5244,8 @@ connection_reached_eof(connection_t *conn)
return connection_dir_reached_eof(TO_DIR_CONN(conn));
case CONN_TYPE_CONTROL:
return connection_control_reached_eof(TO_CONTROL_CONN(conn));
+ case CONN_TYPE_METRICS:
+ return metrics_connection_reached_eof(conn);
default:
log_err(LD_BUG,"got unexpected conn type %d.", conn->type);
tor_fragile_assert();
@@ -5411,18 +5607,6 @@ assert_connection_ok(connection_t *conn, time_t now)
if (conn->linked)
tor_assert(!SOCKET_OK(conn->s));
- if (conn->outbuf_flushlen > 0) {
- /* With optimistic data, we may have queued data in
- * EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing.
- * */
- tor_assert((conn->type == CONN_TYPE_EXIT &&
- conn->state == EXIT_CONN_STATE_RESOLVING) ||
- connection_is_writing(conn) ||
- conn->write_blocked_on_bw ||
- (CONN_IS_EDGE(conn) &&
- TO_EDGE_CONN(conn)->edge_blocked_on_circ));
- }
-
if (conn->hold_open_until_flushed)
tor_assert(conn->marked_for_close);
@@ -5512,6 +5696,9 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(conn->state >= CONTROL_CONN_STATE_MIN_);
tor_assert(conn->state <= CONTROL_CONN_STATE_MAX_);
break;
+ case CONN_TYPE_METRICS:
+ /* No state. */
+ break;
default:
tor_assert(0);
}