mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 12:23:32 +01:00
Only use optimistic data with exits that support it
This adds a little code complexity: we need to remember for each node whether it supports the right feature, and then check for each connection whether it's exiting at such a node. We store this in a flag in the edge_connection_t, and set that flag at link time.
This commit is contained in:
parent
ba5d758104
commit
1e441df2d0
@ -677,6 +677,7 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
|
||||
tor_assert(conn);
|
||||
|
||||
conn->cpath_layer = NULL; /* make sure we don't keep a stale pointer */
|
||||
conn->exit_allows_optimistic_data = 0;
|
||||
conn->on_circuit = NULL;
|
||||
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
@ -1449,6 +1450,8 @@ static void
|
||||
link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
|
||||
crypt_path_t *cpath)
|
||||
{
|
||||
const node_t *exitnode;
|
||||
|
||||
/* add it into the linked list of streams on this circuit */
|
||||
log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.",
|
||||
circ->_base.n_circ_id);
|
||||
@ -1468,6 +1471,24 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
|
||||
tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
|
||||
apconn->cpath_layer = circ->cpath->prev;
|
||||
}
|
||||
|
||||
/* See if we can use optimistic data on this circuit */
|
||||
if (apconn->cpath_layer->extend_info &&
|
||||
(exitnode = node_get_by_id(
|
||||
apconn->cpath_layer->extend_info->identity_digest)) &&
|
||||
exitnode->rs) {
|
||||
/* Okay; we know what exit node this is. */
|
||||
if (circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL &&
|
||||
exitnode->rs->version_supports_optimistic_data)
|
||||
apconn->exit_allows_optimistic_data = 1;
|
||||
else
|
||||
apconn->exit_allows_optimistic_data = 0;
|
||||
log_info(LD_APP, "Looks like completed circuit to %s %s allow "
|
||||
"optimistic data for connection to %s",
|
||||
safe_str_client(node_describe(exitnode)),
|
||||
apconn->exit_allows_optimistic_data ? "does" : "doesn't",
|
||||
safe_str_client(apconn->socks_request->address));
|
||||
}
|
||||
}
|
||||
|
||||
/** Return true iff <b>address</b> is matched by one of the entries in
|
||||
|
@ -57,6 +57,7 @@ static int connection_exit_connect_dir(edge_connection_t *exitconn);
|
||||
static int address_is_in_virtual_range(const char *addr);
|
||||
static int consider_plaintext_ports(edge_connection_t *conn, uint16_t port);
|
||||
static void clear_trackexithost_mappings(const char *exitname);
|
||||
static int connection_ap_supports_optimistic_data(const edge_connection_t *);
|
||||
|
||||
/** An AP stream has failed/finished. If it hasn't already sent back
|
||||
* a socks reply, send one now (based on endreason). Also set
|
||||
@ -154,16 +155,8 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
case EXIT_CONN_STATE_CONNECTING:
|
||||
case AP_CONN_STATE_RENDDESC_WAIT:
|
||||
case AP_CONN_STATE_CIRCUIT_WAIT:
|
||||
case AP_CONN_STATE_RESOLVE_WAIT:
|
||||
case AP_CONN_STATE_CONTROLLER_WAIT:
|
||||
log_info(LD_EDGE,
|
||||
"data from edge while in '%s' state. Leaving it on buffer.",
|
||||
conn_state_to_string(conn->_base.type, conn->_base.state));
|
||||
return 0;
|
||||
case AP_CONN_STATE_CONNECT_WAIT:
|
||||
if (connection_ap_supports_optimistic_data(conn)) {
|
||||
log_info(LD_EDGE,
|
||||
"data from edge while in '%s' state. Sending it anyway. "
|
||||
"package_partial=%d, buflen=%ld",
|
||||
@ -176,6 +169,18 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Fall through if the connection is on a circuit without optimistic
|
||||
* data support. */
|
||||
case EXIT_CONN_STATE_CONNECTING:
|
||||
case AP_CONN_STATE_RENDDESC_WAIT:
|
||||
case AP_CONN_STATE_CIRCUIT_WAIT:
|
||||
case AP_CONN_STATE_RESOLVE_WAIT:
|
||||
case AP_CONN_STATE_CONTROLLER_WAIT:
|
||||
log_info(LD_EDGE,
|
||||
"data from edge while in '%s' state. Leaving it on buffer.",
|
||||
conn_state_to_string(conn->_base.type, conn->_base.state));
|
||||
return 0;
|
||||
}
|
||||
log_warn(LD_BUG,"Got unexpected state %d. Closing.",conn->_base.state);
|
||||
tor_fragile_assert();
|
||||
connection_edge_end(conn, END_STREAM_REASON_INTERNAL);
|
||||
@ -2345,6 +2350,22 @@ get_unique_stream_id_by_circ(origin_circuit_t *circ)
|
||||
return test_stream_id;
|
||||
}
|
||||
|
||||
/** Return true iff <b>conn</b> is linked to a circuit and configured to use
|
||||
* an exit that supports optimistic data. */
|
||||
static int
|
||||
connection_ap_supports_optimistic_data(const edge_connection_t *conn)
|
||||
{
|
||||
tor_assert(conn->_base.type == CONN_TYPE_AP);
|
||||
/* We can only send optimistic data if we're connected to an open
|
||||
general circuit. */
|
||||
if (conn->on_circuit == NULL ||
|
||||
conn->on_circuit->state != CIRCUIT_STATE_OPEN ||
|
||||
conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL)
|
||||
return 0;
|
||||
|
||||
return conn->exit_allows_optimistic_data;
|
||||
}
|
||||
|
||||
/** Write a relay begin cell, using destaddr and destport from ap_conn's
|
||||
* socks_request field, and send it down circ.
|
||||
*
|
||||
@ -2408,11 +2429,14 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
|
||||
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT, 0);
|
||||
|
||||
/* If there's queued-up data, send it now */
|
||||
log_info(LD_APP, "Possibly sending queued-up data: %ld",
|
||||
if (connection_get_inbuf_len(TO_CONN(ap_conn)) &&
|
||||
connection_ap_supports_optimistic_data(ap_conn)) {
|
||||
log_info(LD_APP, "Sending up to %ld bytes of queued-up data",
|
||||
connection_get_inbuf_len(TO_CONN(ap_conn)));
|
||||
if (connection_edge_package_raw_inbuf(ap_conn, 1, NULL) < 0) {
|
||||
connection_mark_for_close(TO_CONN(ap_conn));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1232,6 +1232,11 @@ typedef struct edge_connection_t {
|
||||
* NATd connection */
|
||||
unsigned int is_transparent_ap:1;
|
||||
|
||||
/** Set if this connection's target exit node allows optimistic data.
|
||||
* (That is, data sent on this stream before the exit has sent a
|
||||
* CONNECTED cell.)*/
|
||||
unsigned int exit_allows_optimistic_data : 1;
|
||||
|
||||
/** If this is a DNSPort connection, this field holds the pending DNS
|
||||
* request that we're going to try to answer. */
|
||||
struct evdns_server_request *dns_server_request;
|
||||
@ -1667,6 +1672,9 @@ typedef struct routerstatus_t {
|
||||
/** True iff this router is a version that, if it caches directory info,
|
||||
* we can get microdescriptors from. */
|
||||
unsigned int version_supports_microdesc_cache:1;
|
||||
/** True iff this router is a version that allows DATA cells to arrive on
|
||||
* a stream before it has sent a CONNECTED cell. */
|
||||
unsigned int version_supports_optimistic_data:1;
|
||||
|
||||
unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
|
||||
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
|
||||
|
@ -2092,6 +2092,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
|
||||
rs->version_supports_extrainfo_upload = 1;
|
||||
rs->version_supports_conditional_consensus = 1;
|
||||
rs->version_supports_microdesc_cache = 1;
|
||||
rs->version_supports_optimistic_data = 1;
|
||||
} else {
|
||||
rs->version_supports_begindir =
|
||||
tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
|
||||
@ -2109,6 +2110,8 @@ routerstatus_parse_entry_from_string(memarea_t *area,
|
||||
*/
|
||||
rs->version_supports_microdesc_cache =
|
||||
tor_version_as_new_as(tok->args[0], "0.2.3.0-alpha");
|
||||
rs->version_supports_optimistic_data =
|
||||
tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
|
||||
}
|
||||
if (vote_rs) {
|
||||
vote_rs->version = tor_strdup(tok->args[0]);
|
||||
|
Loading…
Reference in New Issue
Block a user