Merge remote-tracking branch 'public/split_entry_conn'

Conflicts:
	src/or/connection.c
	src/or/connection_edge.c
	src/or/connection_edge.h
	src/or/dnsserv.c

Some of these were a little tricky, since they touched code that
changed because of the prop171 fixes.
This commit is contained in:
Nick Mathewson 2011-09-07 14:13:57 -04:00
commit 0cb01f5c97
17 changed files with 586 additions and 474 deletions

View File

@ -2648,14 +2648,19 @@ node_handles_some_port(const node_t *node, smartlist_t *needed_ports)
static int static int
ap_stream_wants_exit_attention(connection_t *conn) ap_stream_wants_exit_attention(connection_t *conn)
{ {
entry_connection_t *entry;
if (conn->type != CONN_TYPE_AP)
return 0;
entry = TO_ENTRY_CONN(conn);
if (conn->type == CONN_TYPE_AP && if (conn->type == CONN_TYPE_AP &&
conn->state == AP_CONN_STATE_CIRCUIT_WAIT && conn->state == AP_CONN_STATE_CIRCUIT_WAIT &&
!conn->marked_for_close && !conn->marked_for_close &&
!(TO_EDGE_CONN(conn)->want_onehop) && /* ignore one-hop streams */ !(entry->want_onehop) && /* ignore one-hop streams */
!(TO_EDGE_CONN(conn)->use_begindir) && /* ignore targeted dir fetches */ !(entry->use_begindir) && /* ignore targeted dir fetches */
!(TO_EDGE_CONN(conn)->chosen_exit_name) && /* ignore defined streams */ !(entry->chosen_exit_name) && /* ignore defined streams */
!connection_edge_is_rendezvous_stream(TO_EDGE_CONN(conn)) && !connection_edge_is_rendezvous_stream(TO_EDGE_CONN(conn)) &&
!circuit_stream_is_being_handled(TO_EDGE_CONN(conn), 0, !circuit_stream_is_being_handled(TO_ENTRY_CONN(conn), 0,
MIN_CIRCUITS_HANDLING_STREAM)) MIN_CIRCUITS_HANDLING_STREAM))
return 1; return 1;
return 0; return 0;
@ -2760,7 +2765,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity)
SMARTLIST_FOREACH_BEGIN(connections, connection_t *, conn) { SMARTLIST_FOREACH_BEGIN(connections, connection_t *, conn) {
if (!ap_stream_wants_exit_attention(conn)) if (!ap_stream_wants_exit_attention(conn))
continue; /* Skip everything but APs in CIRCUIT_WAIT */ continue; /* Skip everything but APs in CIRCUIT_WAIT */
if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), node)) { if (connection_ap_can_use_exit(TO_ENTRY_CONN(conn), node)) {
++n_supported[i]; ++n_supported[i];
// log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.", // log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.",
// router->nickname, i, n_supported[i]); // router->nickname, i, n_supported[i]);

View File

@ -41,7 +41,7 @@ static void circuit_increment_failure_count(void);
*/ */
static int static int
circuit_is_acceptable(const origin_circuit_t *origin_circ, circuit_is_acceptable(const origin_circuit_t *origin_circ,
const edge_connection_t *conn, const entry_connection_t *conn,
int must_be_open, uint8_t purpose, int must_be_open, uint8_t purpose,
int need_uptime, int need_internal, int need_uptime, int need_internal,
time_t now) time_t now)
@ -135,10 +135,11 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
return 0; return 0;
} }
} else { /* not general */ } else { /* not general */
if ((conn->rend_data && !origin_circ->rend_data) || const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
(!conn->rend_data && origin_circ->rend_data) || if ((edge_conn->rend_data && !origin_circ->rend_data) ||
(conn->rend_data && origin_circ->rend_data && (!edge_conn->rend_data && origin_circ->rend_data) ||
rend_cmp_service_ids(conn->rend_data->onion_address, (edge_conn->rend_data && origin_circ->rend_data &&
rend_cmp_service_ids(edge_conn->rend_data->onion_address,
origin_circ->rend_data->onion_address))) { origin_circ->rend_data->onion_address))) {
/* this circ is not for this conn */ /* this circ is not for this conn */
return 0; return 0;
@ -159,11 +160,11 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
*/ */
static int static int
circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob, circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob,
const edge_connection_t *conn) const entry_connection_t *conn)
{ {
const circuit_t *a = TO_CIRCUIT(oa); const circuit_t *a = TO_CIRCUIT(oa);
const circuit_t *b = TO_CIRCUIT(ob); const circuit_t *b = TO_CIRCUIT(ob);
const uint8_t purpose = conn->_base.purpose; const uint8_t purpose = ENTRY_TO_CONN(conn)->purpose;
int a_bits, b_bits; int a_bits, b_bits;
switch (purpose) { switch (purpose) {
@ -241,7 +242,7 @@ circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob,
* closest introduce-purposed circuit that you can find. * closest introduce-purposed circuit that you can find.
*/ */
static origin_circuit_t * static origin_circuit_t *
circuit_get_best(const edge_connection_t *conn, circuit_get_best(const entry_connection_t *conn,
int must_be_open, uint8_t purpose, int must_be_open, uint8_t purpose,
int need_uptime, int need_internal) int need_uptime, int need_internal)
{ {
@ -544,7 +545,7 @@ circuit_remove_handled_ports(smartlist_t *needed_ports)
* Else return 0. * Else return 0.
*/ */
int int
circuit_stream_is_being_handled(edge_connection_t *conn, circuit_stream_is_being_handled(entry_connection_t *conn,
uint16_t port, int min) uint16_t port, int min)
{ {
circuit_t *circ; circuit_t *circ;
@ -738,8 +739,11 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
tor_assert(circ); tor_assert(circ);
tor_assert(conn); tor_assert(conn);
conn->cpath_layer = NULL; /* make sure we don't keep a stale pointer */ if (conn->_base.type == CONN_TYPE_AP) {
conn->may_use_optimistic_data = 0; entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
entry_conn->may_use_optimistic_data = 0;
}
conn->cpath_layer = NULL; /* don't keep a stale pointer */
conn->on_circuit = NULL; conn->on_circuit = NULL;
if (CIRCUIT_IS_ORIGIN(circ)) { if (CIRCUIT_IS_ORIGIN(circ)) {
@ -1286,7 +1290,7 @@ circuit_reset_failure_count(int timeout)
* Write the found or in-progress or launched circ into *circp. * Write the found or in-progress or launched circ into *circp.
*/ */
static int static int
circuit_get_open_circ_or_launch(edge_connection_t *conn, circuit_get_open_circ_or_launch(entry_connection_t *conn,
uint8_t desired_circuit_purpose, uint8_t desired_circuit_purpose,
origin_circuit_t **circp) origin_circuit_t **circp)
{ {
@ -1298,11 +1302,11 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
tor_assert(conn); tor_assert(conn);
tor_assert(circp); tor_assert(circp);
tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(ENTRY_TO_CONN(conn)->state == AP_CONN_STATE_CIRCUIT_WAIT);
check_exit_policy = check_exit_policy =
conn->socks_request->command == SOCKS_COMMAND_CONNECT && conn->socks_request->command == SOCKS_COMMAND_CONNECT &&
!conn->use_begindir && !conn->use_begindir &&
!connection_edge_is_rendezvous_stream(conn); !connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn));
want_onehop = conn->want_onehop; want_onehop = conn->want_onehop;
need_uptime = !conn->want_onehop && !conn->use_begindir && need_uptime = !conn->want_onehop && !conn->use_begindir &&
@ -1410,19 +1414,20 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) { if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
/* need to pick an intro point */ /* need to pick an intro point */
tor_assert(conn->rend_data); rend_data_t *rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data;
extend_info = rend_client_get_random_intro(conn->rend_data); tor_assert(rend_data);
extend_info = rend_client_get_random_intro(rend_data);
if (!extend_info) { if (!extend_info) {
log_info(LD_REND, log_info(LD_REND,
"No intro points for '%s': re-fetching service descriptor.", "No intro points for '%s': re-fetching service descriptor.",
safe_str_client(conn->rend_data->onion_address)); safe_str_client(rend_data->onion_address));
rend_client_refetch_v2_renddesc(conn->rend_data); rend_client_refetch_v2_renddesc(rend_data);
conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_RENDDESC_WAIT;
return 0; return 0;
} }
log_info(LD_REND,"Chose %s as intro point for '%s'.", log_info(LD_REND,"Chose %s as intro point for '%s'.",
extend_info_describe(extend_info), extend_info_describe(extend_info),
safe_str_client(conn->rend_data->onion_address)); safe_str_client(rend_data->onion_address));
} }
/* If we have specified a particular exit node for our /* If we have specified a particular exit node for our
@ -1511,7 +1516,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
rep_hist_note_used_internal(time(NULL), need_uptime, 1); rep_hist_note_used_internal(time(NULL), need_uptime, 1);
if (circ) { if (circ) {
/* write the service_id into circ */ /* write the service_id into circ */
circ->rend_data = rend_data_dup(conn->rend_data); circ->rend_data = rend_data_dup(ENTRY_TO_EDGE_CONN(conn)->rend_data);
if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND && if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
circ->_base.state == CIRCUIT_STATE_OPEN) circ->_base.state == CIRCUIT_STATE_OPEN)
rend_client_rendcirc_has_opened(circ); rend_client_rendcirc_has_opened(circ);
@ -1569,7 +1574,7 @@ optimistic_data_enabled(void)
* hop in circ's cpath if <b>cpath</b> is NULL. * hop in circ's cpath if <b>cpath</b> is NULL.
*/ */
static void static void
link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ, link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ,
crypt_path_t *cpath) crypt_path_t *cpath)
{ {
const node_t *exitnode; const node_t *exitnode;
@ -1578,29 +1583,29 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.", log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.",
circ->_base.n_circ_id); circ->_base.n_circ_id);
/* reset it, so we can measure circ timeouts */ /* reset it, so we can measure circ timeouts */
apconn->_base.timestamp_lastread = time(NULL); ENTRY_TO_CONN(apconn)->timestamp_lastread = time(NULL);
apconn->next_stream = circ->p_streams; ENTRY_TO_EDGE_CONN(apconn)->next_stream = circ->p_streams;
apconn->on_circuit = TO_CIRCUIT(circ); ENTRY_TO_EDGE_CONN(apconn)->on_circuit = TO_CIRCUIT(circ);
/* assert_connection_ok(conn, time(NULL)); */ /* assert_connection_ok(conn, time(NULL)); */
circ->p_streams = apconn; circ->p_streams = ENTRY_TO_EDGE_CONN(apconn);
if (cpath) { /* we were given one; use it */ if (cpath) { /* we were given one; use it */
tor_assert(cpath_is_on_circuit(circ, cpath)); tor_assert(cpath_is_on_circuit(circ, cpath));
apconn->cpath_layer = cpath; } else {
} else { /* use the last hop in the circuit */ /* use the last hop in the circuit */
tor_assert(circ->cpath); tor_assert(circ->cpath);
tor_assert(circ->cpath->prev); tor_assert(circ->cpath->prev);
tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN); tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
apconn->cpath_layer = circ->cpath->prev; cpath = circ->cpath->prev;
} }
ENTRY_TO_EDGE_CONN(apconn)->cpath_layer = cpath;
circ->isolation_any_streams_attached = 1; circ->isolation_any_streams_attached = 1;
connection_edge_update_circuit_isolation(apconn, circ, 0); connection_edge_update_circuit_isolation(apconn, circ, 0);
/* See if we can use optimistic data on this circuit */ /* See if we can use optimistic data on this circuit */
if (apconn->cpath_layer->extend_info && if (cpath->extend_info &&
(exitnode = node_get_by_id( (exitnode = node_get_by_id(cpath->extend_info->identity_digest)) &&
apconn->cpath_layer->extend_info->identity_digest)) &&
exitnode->rs) { exitnode->rs) {
/* Okay; we know what exit node this is. */ /* Okay; we know what exit node this is. */
if (optimistic_data_enabled() && if (optimistic_data_enabled() &&
@ -1642,7 +1647,7 @@ hostname_in_track_host_exits(const or_options_t *options, const char *address)
* <b>conn</b>'s destination. * <b>conn</b>'s destination.
*/ */
static void static void
consider_recording_trackhost(const edge_connection_t *conn, consider_recording_trackhost(const entry_connection_t *conn,
const origin_circuit_t *circ) const origin_circuit_t *circ)
{ {
const or_options_t *options = get_options(); const or_options_t *options = get_options();
@ -1680,18 +1685,19 @@ consider_recording_trackhost(const edge_connection_t *conn,
* indicated by <b>cpath</b>, or from the last hop in circ's cpath if * indicated by <b>cpath</b>, or from the last hop in circ's cpath if
* <b>cpath</b> is NULL. */ * <b>cpath</b> is NULL. */
int int
connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
origin_circuit_t *circ, origin_circuit_t *circ,
crypt_path_t *cpath) crypt_path_t *cpath)
{ {
connection_t *base_conn = ENTRY_TO_CONN(conn);
tor_assert(conn); tor_assert(conn);
tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT || tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT ||
conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT); base_conn->state == AP_CONN_STATE_CONTROLLER_WAIT);
tor_assert(conn->socks_request); tor_assert(conn->socks_request);
tor_assert(circ); tor_assert(circ);
tor_assert(circ->_base.state == CIRCUIT_STATE_OPEN); tor_assert(circ->_base.state == CIRCUIT_STATE_OPEN);
conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
if (!circ->_base.timestamp_dirty) if (!circ->_base.timestamp_dirty)
circ->_base.timestamp_dirty = time(NULL); circ->_base.timestamp_dirty = time(NULL);
@ -1721,21 +1727,22 @@ connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
/* XXXX this function should mark for close whenever it returns -1; /* XXXX this function should mark for close whenever it returns -1;
* its callers shouldn't have to worry about that. */ * its callers shouldn't have to worry about that. */
int int
connection_ap_handshake_attach_circuit(edge_connection_t *conn) connection_ap_handshake_attach_circuit(entry_connection_t *conn)
{ {
connection_t *base_conn = ENTRY_TO_CONN(conn);
int retval; int retval;
int conn_age; int conn_age;
int want_onehop; int want_onehop;
tor_assert(conn); tor_assert(conn);
tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(conn->socks_request); tor_assert(conn->socks_request);
want_onehop = conn->want_onehop; want_onehop = conn->want_onehop;
conn_age = (int)(time(NULL) - conn->_base.timestamp_created); conn_age = (int)(time(NULL) - base_conn->timestamp_created);
if (conn_age >= get_options()->SocksTimeout) { if (conn_age >= get_options()->SocksTimeout) {
int severity = (tor_addr_is_null(&conn->_base.addr) && !conn->_base.port) ? int severity = (tor_addr_is_null(&base_conn->addr) && !base_conn->port) ?
LOG_INFO : LOG_NOTICE; LOG_INFO : LOG_NOTICE;
log_fn(severity, LD_APP, log_fn(severity, LD_APP,
"Tried for %d seconds to get a connection to %s:%d. Giving up.", "Tried for %d seconds to get a connection to %s:%d. Giving up.",
@ -1744,7 +1751,8 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
return -1; return -1;
} }
if (!connection_edge_is_rendezvous_stream(conn)) { /* we're a general conn */ if (!connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn))) {
/* we're a general conn */
origin_circuit_t *circ=NULL; origin_circuit_t *circ=NULL;
if (conn->chosen_exit_name) { if (conn->chosen_exit_name) {
@ -1799,7 +1807,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
} else { /* we're a rendezvous conn */ } else { /* we're a rendezvous conn */
origin_circuit_t *rendcirc=NULL, *introcirc=NULL; origin_circuit_t *rendcirc=NULL, *introcirc=NULL;
tor_assert(!conn->cpath_layer); tor_assert(!ENTRY_TO_EDGE_CONN(conn)->cpath_layer);
/* start by finding a rendezvous circuit for us */ /* start by finding a rendezvous circuit for us */
@ -1855,7 +1863,8 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
!c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) { !c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) {
origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c); origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c);
if (oc->rend_data && if (oc->rend_data &&
!rend_cmp_service_ids(conn->rend_data->onion_address, !rend_cmp_service_ids(
ENTRY_TO_EDGE_CONN(conn)->rend_data->onion_address,
oc->rend_data->onion_address)) { oc->rend_data->onion_address)) {
log_info(LD_REND|LD_CIRC, "Closing introduction circuit that we " log_info(LD_REND|LD_CIRC, "Closing introduction circuit that we "
"built in parallel."); "built in parallel.");

View File

@ -14,7 +14,7 @@
void circuit_expire_building(void); void circuit_expire_building(void);
void circuit_remove_handled_ports(smartlist_t *needed_ports); void circuit_remove_handled_ports(smartlist_t *needed_ports);
int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port, int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port,
int min); int min);
#if 0 #if 0
int circuit_conforms_to_options(const origin_circuit_t *circ, int circuit_conforms_to_options(const origin_circuit_t *circ,
@ -45,10 +45,10 @@ origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
int flags); int flags);
origin_circuit_t *circuit_launch(uint8_t purpose, int flags); origin_circuit_t *circuit_launch(uint8_t purpose, int flags);
void circuit_reset_failure_count(int timeout); void circuit_reset_failure_count(int timeout);
int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, int connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
origin_circuit_t *circ, origin_circuit_t *circ,
crypt_path_t *cpath); crypt_path_t *cpath);
int connection_ap_handshake_attach_circuit(edge_connection_t *conn); int connection_ap_handshake_attach_circuit(entry_connection_t *conn);
int hostname_in_track_host_exits(const or_options_t *options, int hostname_in_track_host_exits(const or_options_t *options,
const char *address); const char *address);

View File

@ -243,16 +243,26 @@ or_connection_new(int socket_family)
return or_conn; return or_conn;
} }
/** Allocate and return a new entry_connection_t, initialized as by
* connection_init(). */
entry_connection_t *
entry_connection_new(int type, int socket_family)
{
entry_connection_t *entry_conn = tor_malloc_zero(sizeof(entry_connection_t));
tor_assert(type == CONN_TYPE_AP);
connection_init(time(NULL), ENTRY_TO_CONN(entry_conn), type, socket_family);
entry_conn->socks_request = socks_request_new();
return entry_conn;
}
/** Allocate and return a new edge_connection_t, initialized as by /** Allocate and return a new edge_connection_t, initialized as by
* connection_init(). */ * connection_init(). */
edge_connection_t * edge_connection_t *
edge_connection_new(int type, int socket_family) edge_connection_new(int type, int socket_family)
{ {
edge_connection_t *edge_conn = tor_malloc_zero(sizeof(edge_connection_t)); edge_connection_t *edge_conn = tor_malloc_zero(sizeof(edge_connection_t));
tor_assert(type == CONN_TYPE_EXIT || type == CONN_TYPE_AP); tor_assert(type == CONN_TYPE_EXIT);
connection_init(time(NULL), TO_CONN(edge_conn), type, socket_family); connection_init(time(NULL), TO_CONN(edge_conn), type, socket_family);
if (type == CONN_TYPE_AP)
edge_conn->socks_request = socks_request_new();
return edge_conn; return edge_conn;
} }
@ -291,9 +301,11 @@ connection_new(int type, int socket_family)
return TO_CONN(or_connection_new(socket_family)); return TO_CONN(or_connection_new(socket_family));
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
case CONN_TYPE_AP:
return TO_CONN(edge_connection_new(type, socket_family)); return TO_CONN(edge_connection_new(type, socket_family));
case CONN_TYPE_AP:
return ENTRY_TO_CONN(entry_connection_new(type, socket_family));
case CONN_TYPE_DIR: case CONN_TYPE_DIR:
return TO_CONN(dir_connection_new(socket_family)); return TO_CONN(dir_connection_new(socket_family));
@ -334,9 +346,11 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family)
conn->magic = OR_CONNECTION_MAGIC; conn->magic = OR_CONNECTION_MAGIC;
break; break;
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
case CONN_TYPE_AP:
conn->magic = EDGE_CONNECTION_MAGIC; conn->magic = EDGE_CONNECTION_MAGIC;
break; break;
case CONN_TYPE_AP:
conn->magic = ENTRY_CONNECTION_MAGIC;
break;
case CONN_TYPE_DIR: case CONN_TYPE_DIR:
conn->magic = DIR_CONNECTION_MAGIC; conn->magic = DIR_CONNECTION_MAGIC;
break; break;
@ -402,6 +416,10 @@ _connection_free(connection_t *conn)
memlen = sizeof(or_connection_t); memlen = sizeof(or_connection_t);
break; break;
case CONN_TYPE_AP: case CONN_TYPE_AP:
tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
mem = TO_ENTRY_CONN(conn);
memlen = sizeof(entry_connection_t);
break;
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC); tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
mem = TO_EDGE_CONN(conn); mem = TO_EDGE_CONN(conn);
@ -465,19 +483,21 @@ _connection_free(connection_t *conn)
smartlist_free(or_conn->active_circuit_pqueue); smartlist_free(or_conn->active_circuit_pqueue);
tor_free(or_conn->nickname); tor_free(or_conn->nickname);
} }
if (conn->type == CONN_TYPE_AP) {
entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
tor_free(entry_conn->chosen_exit_name);
tor_free(entry_conn->original_dest_address);
if (entry_conn->socks_request)
socks_request_free(entry_conn->socks_request);
if (entry_conn->pending_optimistic_data) {
generic_buffer_free(entry_conn->pending_optimistic_data);
}
if (entry_conn->sending_optimistic_data) {
generic_buffer_free(entry_conn->sending_optimistic_data);
}
}
if (CONN_IS_EDGE(conn)) { if (CONN_IS_EDGE(conn)) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn); rend_data_free(TO_EDGE_CONN(conn)->rend_data);
tor_free(edge_conn->chosen_exit_name);
tor_free(edge_conn->original_dest_address);
if (edge_conn->socks_request)
socks_request_free(edge_conn->socks_request);
if (edge_conn->pending_optimistic_data) {
generic_buffer_free(edge_conn->pending_optimistic_data);
}
if (edge_conn->sending_optimistic_data) {
generic_buffer_free(edge_conn->sending_optimistic_data);
}
rend_data_free(edge_conn->rend_data);
} }
if (conn->type == CONN_TYPE_CONTROL) { if (conn->type == CONN_TYPE_CONTROL) {
control_connection_t *control_conn = TO_CONTROL_CONN(conn); control_connection_t *control_conn = TO_CONTROL_CONN(conn);
@ -587,7 +607,7 @@ connection_about_to_close_connection(connection_t *conn)
connection_or_about_to_close(TO_OR_CONN(conn)); connection_or_about_to_close(TO_OR_CONN(conn));
break; break;
case CONN_TYPE_AP: case CONN_TYPE_AP:
connection_ap_about_to_close(TO_EDGE_CONN(conn)); connection_ap_about_to_close(TO_ENTRY_CONN(conn));
break; break;
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
connection_exit_about_to_close(TO_EDGE_CONN(conn)); connection_exit_about_to_close(TO_EDGE_CONN(conn));
@ -1211,20 +1231,20 @@ connection_init_accepted_conn(connection_t *conn,
control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW, 0); control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW, 0);
return connection_tls_start_handshake(TO_OR_CONN(conn), 1); return connection_tls_start_handshake(TO_OR_CONN(conn), 1);
case CONN_TYPE_AP: case CONN_TYPE_AP:
TO_EDGE_CONN(conn)->isolation_flags = listener->isolation_flags; TO_ENTRY_CONN(conn)->isolation_flags = listener->isolation_flags;
TO_EDGE_CONN(conn)->session_group = listener->session_group; TO_ENTRY_CONN(conn)->session_group = listener->session_group;
TO_EDGE_CONN(conn)->nym_epoch = get_signewnym_epoch(); TO_ENTRY_CONN(conn)->nym_epoch = get_signewnym_epoch();
TO_EDGE_CONN(conn)->socks_request->listener_type = listener->_base.type; TO_ENTRY_CONN(conn)->socks_request->listener_type = listener->_base.type;
switch (TO_CONN(listener)->type) { switch (TO_CONN(listener)->type) {
case CONN_TYPE_AP_LISTENER: case CONN_TYPE_AP_LISTENER:
conn->state = AP_CONN_STATE_SOCKS_WAIT; conn->state = AP_CONN_STATE_SOCKS_WAIT;
break; break;
case CONN_TYPE_AP_TRANS_LISTENER: case CONN_TYPE_AP_TRANS_LISTENER:
TO_EDGE_CONN(conn)->is_transparent_ap = 1; TO_ENTRY_CONN(conn)->is_transparent_ap = 1;
conn->state = AP_CONN_STATE_CIRCUIT_WAIT; conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
return connection_ap_process_transparent(TO_EDGE_CONN(conn)); return connection_ap_process_transparent(TO_ENTRY_CONN(conn));
case CONN_TYPE_AP_NATD_LISTENER: case CONN_TYPE_AP_NATD_LISTENER:
TO_EDGE_CONN(conn)->is_transparent_ap = 1; TO_ENTRY_CONN(conn)->is_transparent_ap = 1;
conn->state = AP_CONN_STATE_NATD_WAIT; conn->state = AP_CONN_STATE_NATD_WAIT;
break; break;
} }
@ -2616,8 +2636,10 @@ connection_handle_read_impl(connection_t *conn)
if (CONN_IS_EDGE(conn)) { if (CONN_IS_EDGE(conn)) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn); edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
connection_edge_end_errno(edge_conn); connection_edge_end_errno(edge_conn);
if (edge_conn->socks_request) /* broken, don't send a socks reply back */ if (conn->type == CONN_TYPE_AP && TO_ENTRY_CONN(conn)->socks_request) {
edge_conn->socks_request->has_finished = 1; /* broken, don't send a socks reply back */
TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
}
} }
connection_close_immediate(conn); /* Don't flush; connection is dead. */ connection_close_immediate(conn); /* Don't flush; connection is dead. */
connection_mark_for_close(conn); connection_mark_for_close(conn);
@ -2959,8 +2981,10 @@ connection_handle_event_cb(struct bufferevent *bufev, short event, void *arg)
edge_connection_t *edge_conn = TO_EDGE_CONN(conn); edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
if (!edge_conn->edge_has_sent_end) if (!edge_conn->edge_has_sent_end)
connection_edge_end_errno(edge_conn); connection_edge_end_errno(edge_conn);
if (edge_conn->socks_request) /* broken, don't send a socks reply back */ if (conn->type == CONN_TYPE_AP && TO_ENTRY_CONN(conn)->socks_request) {
edge_conn->socks_request->has_finished = 1; /* broken, don't send a socks reply back */
TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
}
} }
connection_close_immediate(conn); /* Connection is dead. */ connection_close_immediate(conn); /* Connection is dead. */
if (!conn->marked_for_close) if (!conn->marked_for_close)
@ -3495,8 +3519,7 @@ connection_get_by_type_state_rendquery(int type, int state,
type == CONN_TYPE_AP || type == CONN_TYPE_EXIT); type == CONN_TYPE_AP || type == CONN_TYPE_EXIT);
tor_assert(rendquery); tor_assert(rendquery);
SMARTLIST_FOREACH(conns, connection_t *, conn, SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
{
if (conn->type == type && if (conn->type == type &&
!conn->marked_for_close && !conn->marked_for_close &&
(!state || state == conn->state)) { (!state || state == conn->state)) {
@ -3511,7 +3534,7 @@ connection_get_by_type_state_rendquery(int type, int state,
TO_EDGE_CONN(conn)->rend_data->onion_address)) TO_EDGE_CONN(conn)->rend_data->onion_address))
return conn; return conn;
} }
}); } SMARTLIST_FOREACH_END(conn);
return NULL; return NULL;
} }
@ -3934,6 +3957,8 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(conn->magic == OR_CONNECTION_MAGIC); tor_assert(conn->magic == OR_CONNECTION_MAGIC);
break; break;
case CONN_TYPE_AP: case CONN_TYPE_AP:
tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
break;
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC); tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
break; break;
@ -4000,21 +4025,18 @@ assert_connection_ok(connection_t *conn, time_t now)
} }
if (CONN_IS_EDGE(conn)) { if (CONN_IS_EDGE(conn)) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
if (edge_conn->chosen_exit_optional || edge_conn->chosen_exit_retries) {
tor_assert(conn->type == CONN_TYPE_AP);
tor_assert(edge_conn->chosen_exit_name);
}
/* XXX unchecked: package window, deliver window. */ /* XXX unchecked: package window, deliver window. */
if (conn->type == CONN_TYPE_AP) { if (conn->type == CONN_TYPE_AP) {
entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
if (entry_conn->chosen_exit_optional || entry_conn->chosen_exit_retries)
tor_assert(entry_conn->chosen_exit_name);
tor_assert(edge_conn->socks_request); tor_assert(entry_conn->socks_request);
if (conn->state == AP_CONN_STATE_OPEN) { if (conn->state == AP_CONN_STATE_OPEN) {
tor_assert(edge_conn->socks_request->has_finished); tor_assert(entry_conn->socks_request->has_finished);
if (!conn->marked_for_close) { if (!conn->marked_for_close) {
tor_assert(edge_conn->cpath_layer); tor_assert(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer);
assert_cpath_layer_ok(edge_conn->cpath_layer); assert_cpath_layer_ok(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer);
} }
} }
} }
@ -4047,7 +4069,7 @@ assert_connection_ok(connection_t *conn, time_t now)
case CONN_TYPE_AP: case CONN_TYPE_AP:
tor_assert(conn->state >= _AP_CONN_STATE_MIN); tor_assert(conn->state >= _AP_CONN_STATE_MIN);
tor_assert(conn->state <= _AP_CONN_STATE_MAX); tor_assert(conn->state <= _AP_CONN_STATE_MAX);
tor_assert(TO_EDGE_CONN(conn)->socks_request); tor_assert(TO_ENTRY_CONN(conn)->socks_request);
break; break;
case CONN_TYPE_DIR: case CONN_TYPE_DIR:
tor_assert(conn->state >= _DIR_CONN_STATE_MIN); tor_assert(conn->state >= _DIR_CONN_STATE_MIN);

View File

@ -21,6 +21,7 @@ const char *conn_state_to_string(int type, int state);
dir_connection_t *dir_connection_new(int socket_family); dir_connection_t *dir_connection_new(int socket_family);
or_connection_t *or_connection_new(int socket_family); or_connection_t *or_connection_new(int socket_family);
edge_connection_t *edge_connection_new(int type, int socket_family); edge_connection_t *edge_connection_new(int type, int socket_family);
entry_connection_t *entry_connection_new(int type, int socket_family);
control_connection_t *control_connection_new(int socket_family); control_connection_t *control_connection_new(int socket_family);
listener_connection_t *listener_connection_new(int type, int socket_family); listener_connection_t *listener_connection_new(int type, int socket_family);
connection_t *connection_new(int type, int socket_family); connection_t *connection_new(int type, int socket_family);

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
#define connection_mark_unattached_ap(conn, endreason) \ #define connection_mark_unattached_ap(conn, endreason) \
_connection_mark_unattached_ap((conn), (endreason), __LINE__, _SHORT_FILE_) _connection_mark_unattached_ap((conn), (endreason), __LINE__, _SHORT_FILE_)
void _connection_mark_unattached_ap(edge_connection_t *conn, int endreason, void _connection_mark_unattached_ap(entry_connection_t *conn, int endreason,
int line, const char *file); int line, const char *file);
int connection_edge_reached_eof(edge_connection_t *conn); int connection_edge_reached_eof(edge_connection_t *conn);
int connection_edge_process_inbuf(edge_connection_t *conn, int connection_edge_process_inbuf(edge_connection_t *conn,
@ -27,22 +27,22 @@ int connection_edge_flushed_some(edge_connection_t *conn);
int connection_edge_finished_flushing(edge_connection_t *conn); int connection_edge_finished_flushing(edge_connection_t *conn);
int connection_edge_finished_connecting(edge_connection_t *conn); int connection_edge_finished_connecting(edge_connection_t *conn);
void connection_ap_about_to_close(edge_connection_t *edge_conn); void connection_ap_about_to_close(entry_connection_t *edge_conn);
void connection_exit_about_to_close(edge_connection_t *edge_conn); void connection_exit_about_to_close(edge_connection_t *edge_conn);
int connection_ap_handshake_send_begin(edge_connection_t *ap_conn); int connection_ap_handshake_send_begin(entry_connection_t *ap_conn);
int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn); int connection_ap_handshake_send_resolve(entry_connection_t *ap_conn);
edge_connection_t *connection_ap_make_link(connection_t *partner, entry_connection_t *connection_ap_make_link(connection_t *partner,
char *address, uint16_t port, char *address, uint16_t port,
const char *digest, const char *digest,
int session_group, int session_group,
int isolation_flags, int isolation_flags,
int use_begindir, int want_onehop); int use_begindir, int want_onehop);
void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, void connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
size_t replylen, size_t replylen,
int endreason); int endreason);
void connection_ap_handshake_socks_resolved(edge_connection_t *conn, void connection_ap_handshake_socks_resolved(entry_connection_t *conn,
int answer_type, int answer_type,
size_t answer_len, size_t answer_len,
const uint8_t *answer, const uint8_t *answer,
@ -53,17 +53,17 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ); int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
void connection_exit_connect(edge_connection_t *conn); void connection_exit_connect(edge_connection_t *conn);
int connection_edge_is_rendezvous_stream(edge_connection_t *conn); int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
int connection_ap_can_use_exit(const edge_connection_t *conn, int connection_ap_can_use_exit(const entry_connection_t *conn,
const node_t *exit); const node_t *exit);
void connection_ap_expire_beginning(void); void connection_ap_expire_beginning(void);
void connection_ap_attach_pending(void); void connection_ap_attach_pending(void);
void connection_ap_fail_onehop(const char *failed_digest, void connection_ap_fail_onehop(const char *failed_digest,
cpath_build_state_t *build_state); cpath_build_state_t *build_state);
void circuit_discard_optional_exit_enclaves(extend_info_t *info); void circuit_discard_optional_exit_enclaves(extend_info_t *info);
int connection_ap_detach_retriable(edge_connection_t *conn, int connection_ap_detach_retriable(entry_connection_t *conn,
origin_circuit_t *circ, origin_circuit_t *circ,
int reason); int reason);
int connection_ap_process_transparent(edge_connection_t *conn); int connection_ap_process_transparent(entry_connection_t *conn);
int address_is_invalid_destination(const char *address, int client); int address_is_invalid_destination(const char *address, int client);
@ -88,10 +88,10 @@ void client_dns_set_addressmap(const char *address, uint32_t val,
const char *addressmap_register_virtual_address(int type, char *new_address); const char *addressmap_register_virtual_address(int type, char *new_address);
void addressmap_get_mappings(smartlist_t *sl, time_t min_expires, void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
time_t max_expires, int want_expiry); time_t max_expires, int want_expiry);
int connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn, int connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn,
origin_circuit_t *circ, origin_circuit_t *circ,
crypt_path_t *cpath); crypt_path_t *cpath);
int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
origin_circuit_t *circ, origin_circuit_t *circ,
crypt_path_t *cpath); crypt_path_t *cpath);
@ -105,9 +105,10 @@ hostname_type_t parse_extended_hostname(char *address, int allowdotexit);
int get_pf_socket(void); int get_pf_socket(void);
#endif #endif
int connection_edge_compatible_with_circuit(const edge_connection_t *conn,
int connection_edge_compatible_with_circuit(const entry_connection_t *conn,
const origin_circuit_t *circ); const origin_circuit_t *circ);
int connection_edge_update_circuit_isolation(const edge_connection_t *conn, int connection_edge_update_circuit_isolation(const entry_connection_t *conn,
origin_circuit_t *circ, origin_circuit_t *circ,
int dry_run); int dry_run);
void circuit_clear_isolation(origin_circuit_t *circ); void circuit_clear_isolation(origin_circuit_t *circ);

View File

@ -177,7 +177,7 @@ static int handle_control_resolve(control_connection_t *conn, uint32_t len,
static int handle_control_usefeature(control_connection_t *conn, static int handle_control_usefeature(control_connection_t *conn,
uint32_t len, uint32_t len,
const char *body); const char *body);
static int write_stream_target_to_buf(edge_connection_t *conn, char *buf, static int write_stream_target_to_buf(entry_connection_t *conn, char *buf,
size_t len); size_t len);
static void orconn_target_get_name(char *buf, size_t len, static void orconn_target_get_name(char *buf, size_t len,
or_connection_t *conn); or_connection_t *conn);
@ -656,7 +656,7 @@ get_circ(const char *id)
} }
/** Given a text stream <b>id</b>, return the corresponding AP connection. */ /** Given a text stream <b>id</b>, return the corresponding AP connection. */
static edge_connection_t * static entry_connection_t *
get_stream(const char *id) get_stream(const char *id)
{ {
uint64_t n_id; uint64_t n_id;
@ -668,7 +668,7 @@ get_stream(const char *id)
conn = connection_get_by_global_id(n_id); conn = connection_get_by_global_id(n_id);
if (!conn || conn->type != CONN_TYPE_AP || conn->marked_for_close) if (!conn || conn->type != CONN_TYPE_AP || conn->marked_for_close)
return NULL; return NULL;
return TO_EDGE_CONN(conn); return TO_ENTRY_CONN(conn);
} }
/** Helper for setconf and resetconf. Acts like setconf, except /** Helper for setconf and resetconf. Acts like setconf, except
@ -1802,7 +1802,7 @@ getinfo_helper_events(control_connection_t *control_conn,
char buf[256]; char buf[256];
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) { SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
const char *state; const char *state;
edge_connection_t *conn; entry_connection_t *conn;
char *s; char *s;
size_t slen; size_t slen;
circuit_t *circ; circuit_t *circ;
@ -1812,8 +1812,8 @@ getinfo_helper_events(control_connection_t *control_conn,
base_conn->state == AP_CONN_STATE_SOCKS_WAIT || base_conn->state == AP_CONN_STATE_SOCKS_WAIT ||
base_conn->state == AP_CONN_STATE_NATD_WAIT) base_conn->state == AP_CONN_STATE_NATD_WAIT)
continue; continue;
conn = TO_EDGE_CONN(base_conn); conn = TO_ENTRY_CONN(base_conn);
switch (conn->_base.state) switch (base_conn->state)
{ {
case AP_CONN_STATE_CONTROLLER_WAIT: case AP_CONN_STATE_CONTROLLER_WAIT:
case AP_CONN_STATE_CIRCUIT_WAIT: case AP_CONN_STATE_CIRCUIT_WAIT:
@ -1832,17 +1832,17 @@ getinfo_helper_events(control_connection_t *control_conn,
state = "SUCCEEDED"; break; state = "SUCCEEDED"; break;
default: default:
log_warn(LD_BUG, "Asked for stream in unknown state %d", log_warn(LD_BUG, "Asked for stream in unknown state %d",
conn->_base.state); base_conn->state);
continue; continue;
} }
circ = circuit_get_by_edge_conn(conn); circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
if (circ && CIRCUIT_IS_ORIGIN(circ)) if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ); origin_circ = TO_ORIGIN_CIRCUIT(circ);
write_stream_target_to_buf(conn, buf, sizeof(buf)); write_stream_target_to_buf(conn, buf, sizeof(buf));
slen = strlen(buf)+strlen(state)+32; slen = strlen(buf)+strlen(state)+32;
s = tor_malloc(slen+1); s = tor_malloc(slen+1);
tor_snprintf(s, slen, "%lu %s %lu %s", tor_snprintf(s, slen, "%lu %s %lu %s",
(unsigned long) conn->_base.global_identifier,state, (unsigned long) base_conn->global_identifier,state,
origin_circ? origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul, (unsigned long)origin_circ->global_identifier : 0ul,
buf); buf);
@ -2462,7 +2462,7 @@ static int
handle_control_attachstream(control_connection_t *conn, uint32_t len, handle_control_attachstream(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
edge_connection_t *ap_conn = NULL; entry_connection_t *ap_conn = NULL;
origin_circuit_t *circ = NULL; origin_circuit_t *circ = NULL;
int zero_circ; int zero_circ;
smartlist_t *args; smartlist_t *args;
@ -2498,9 +2498,9 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
if (!ap_conn || (!zero_circ && !circ) || !hop_line_ok) if (!ap_conn || (!zero_circ && !circ) || !hop_line_ok)
return 0; return 0;
if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT && if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT &&
ap_conn->_base.state != AP_CONN_STATE_CONNECT_WAIT && ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONNECT_WAIT &&
ap_conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) { ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_RESOLVE_WAIT) {
connection_write_str_to_buf( connection_write_str_to_buf(
"555 Connection is not managed by controller.\r\n", "555 Connection is not managed by controller.\r\n",
conn); conn);
@ -2508,15 +2508,16 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
} }
/* Do we need to detach it first? */ /* Do we need to detach it first? */
if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT) { if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT) {
circuit_t *tmpcirc = circuit_get_by_edge_conn(ap_conn); edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
connection_edge_end(ap_conn, END_STREAM_REASON_TIMEOUT); circuit_t *tmpcirc = circuit_get_by_edge_conn(edge_conn);
connection_edge_end(edge_conn, END_STREAM_REASON_TIMEOUT);
/* Un-mark it as ending, since we're going to reuse it. */ /* Un-mark it as ending, since we're going to reuse it. */
ap_conn->edge_has_sent_end = 0; edge_conn->edge_has_sent_end = 0;
ap_conn->end_reason = 0; edge_conn->end_reason = 0;
if (tmpcirc) if (tmpcirc)
circuit_detach_stream(tmpcirc,ap_conn); circuit_detach_stream(tmpcirc, edge_conn);
ap_conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; TO_CONN(edge_conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
} }
if (circ && (circ->_base.state != CIRCUIT_STATE_OPEN)) { if (circ && (circ->_base.state != CIRCUIT_STATE_OPEN)) {
@ -2638,7 +2639,7 @@ static int
handle_control_redirectstream(control_connection_t *conn, uint32_t len, handle_control_redirectstream(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
edge_connection_t *ap_conn = NULL; entry_connection_t *ap_conn = NULL;
char *new_addr = NULL; char *new_addr = NULL;
uint16_t new_port = 0; uint16_t new_port = 0;
smartlist_t *args; smartlist_t *args;
@ -2686,7 +2687,7 @@ static int
handle_control_closestream(control_connection_t *conn, uint32_t len, handle_control_closestream(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
edge_connection_t *ap_conn=NULL; entry_connection_t *ap_conn=NULL;
uint8_t reason=0; uint8_t reason=0;
smartlist_t *args; smartlist_t *args;
int ok; int ok;
@ -3266,7 +3267,7 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
* <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on * <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on
* failure. */ * failure. */
static int static int
write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len) write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len)
{ {
char buf2[256]; char buf2[256];
if (conn->chosen_exit_name) if (conn->chosen_exit_name)
@ -3277,8 +3278,8 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
if (tor_snprintf(buf, len, "%s%s%s:%d", if (tor_snprintf(buf, len, "%s%s%s:%d",
conn->socks_request->address, conn->socks_request->address,
conn->chosen_exit_name ? buf2 : "", conn->chosen_exit_name ? buf2 : "",
!conn->chosen_exit_name && !conn->chosen_exit_name && connection_edge_is_rendezvous_stream(
connection_edge_is_rendezvous_stream(conn) ? ".onion" : "", ENTRY_TO_EDGE_CONN(conn)) ? ".onion" : "",
conn->socks_request->port)<0) conn->socks_request->port)<0)
return -1; return -1;
return 0; return 0;
@ -3287,7 +3288,7 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
/** Something has happened to the stream associated with AP connection /** Something has happened to the stream associated with AP connection
* <b>conn</b>: tell any interested control connections. */ * <b>conn</b>: tell any interested control connections. */
int int
control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp, control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
int reason_code) int reason_code)
{ {
char reason_buf[64]; char reason_buf[64];
@ -3359,7 +3360,7 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
if (tp == STREAM_EVENT_NEW) { if (tp == STREAM_EVENT_NEW) {
tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d", tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d",
TO_CONN(conn)->address, TO_CONN(conn)->port ); ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port);
} else { } else {
addrport_buf[0] = '\0'; addrport_buf[0] = '\0';
} }
@ -3367,12 +3368,12 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
if (tp == STREAM_EVENT_NEW_RESOLVE) { if (tp == STREAM_EVENT_NEW_RESOLVE) {
purpose = " PURPOSE=DNS_REQUEST"; purpose = " PURPOSE=DNS_REQUEST";
} else if (tp == STREAM_EVENT_NEW) { } else if (tp == STREAM_EVENT_NEW) {
if (conn->is_dns_request || if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request ||
(conn->socks_request && (conn->socks_request &&
SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command))) SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)))
purpose = " PURPOSE=DNS_REQUEST"; purpose = " PURPOSE=DNS_REQUEST";
else if (conn->use_begindir) { else if (conn->use_begindir) {
connection_t *linked = TO_CONN(conn)->linked_conn; connection_t *linked = ENTRY_TO_CONN(conn)->linked_conn;
int linked_dir_purpose = -1; int linked_dir_purpose = -1;
if (linked && linked->type == CONN_TYPE_DIR) if (linked && linked->type == CONN_TYPE_DIR)
linked_dir_purpose = linked->purpose; linked_dir_purpose = linked->purpose;
@ -3384,12 +3385,13 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
purpose = " PURPOSE=USER"; purpose = " PURPOSE=USER";
} }
circ = circuit_get_by_edge_conn(conn); circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
if (circ && CIRCUIT_IS_ORIGIN(circ)) if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ); origin_circ = TO_ORIGIN_CIRCUIT(circ);
send_control_event(EVENT_STREAM_STATUS, ALL_FORMATS, send_control_event(EVENT_STREAM_STATUS, ALL_FORMATS,
"650 STREAM "U64_FORMAT" %s %lu %s%s%s%s\r\n", "650 STREAM "U64_FORMAT" %s %lu %s%s%s%s\r\n",
U64_PRINTF_ARG(conn->_base.global_identifier), status, U64_PRINTF_ARG(ENTRY_TO_CONN(conn)->global_identifier),
status,
origin_circ? origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul, (unsigned long)origin_circ->global_identifier : 0ul,
buf, reason_buf, addrport_buf, purpose); buf, reason_buf, addrport_buf, purpose);

View File

@ -37,7 +37,7 @@ int control_event_is_interesting(int event);
int control_event_circuit_status(origin_circuit_t *circ, int control_event_circuit_status(origin_circuit_t *circ,
circuit_status_event_t e, int reason); circuit_status_event_t e, int reason);
int control_event_stream_status(edge_connection_t *conn, int control_event_stream_status(entry_connection_t *conn,
stream_status_event_t e, stream_status_event_t e,
int reason); int reason);
int control_event_or_conn_status(or_connection_t *conn, int control_event_or_conn_status(or_connection_t *conn,

View File

@ -972,7 +972,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
error indicates broken link in windowsland. */ error indicates broken link in windowsland. */
} }
} else { /* we want to connect via a tor connection */ } else { /* we want to connect via a tor connection */
edge_connection_t *linked_conn; entry_connection_t *linked_conn;
/* Anonymized tunneled connections can never share a circuit. /* Anonymized tunneled connections can never share a circuit.
* One-hop directory connections can share circuits with each other * One-hop directory connections can share circuits with each other
* but nothing else. */ * but nothing else. */
@ -1014,10 +1014,11 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
if_modified_since); if_modified_since);
connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT); connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
IF_HAS_BUFFEREVENT(TO_CONN(linked_conn), { IF_HAS_BUFFEREVENT(ENTRY_TO_CONN(linked_conn), {
connection_watch_events(TO_CONN(linked_conn), READ_EVENT|WRITE_EVENT); connection_watch_events(ENTRY_TO_CONN(linked_conn),
READ_EVENT|WRITE_EVENT);
}) ELSE_IF_NO_BUFFEREVENT }) ELSE_IF_NO_BUFFEREVENT
connection_start_reading(TO_CONN(linked_conn)); connection_start_reading(ENTRY_TO_CONN(linked_conn));
} }
} }

View File

@ -32,6 +32,7 @@ static void
evdns_server_callback(struct evdns_server_request *req, void *data_) evdns_server_callback(struct evdns_server_request *req, void *data_)
{ {
const listener_connection_t *listener = data_; const listener_connection_t *listener = data_;
entry_connection_t *entry_conn;
edge_connection_t *conn; edge_connection_t *conn;
int i = 0; int i = 0;
struct evdns_server_question *q = NULL; struct evdns_server_question *q = NULL;
@ -115,8 +116,9 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
} }
/* Make a new dummy AP connection, and attach the request to it. */ /* Make a new dummy AP connection, and attach the request to it. */
conn = edge_connection_new(CONN_TYPE_AP, AF_INET); entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; conn = ENTRY_TO_EDGE_CONN(entry_conn);
TO_CONN(conn)->state = AP_CONN_STATE_RESOLVE_WAIT;
conn->is_dns_request = 1; conn->is_dns_request = 1;
tor_addr_copy(&TO_CONN(conn)->addr, &tor_addr); tor_addr_copy(&TO_CONN(conn)->addr, &tor_addr);
@ -124,27 +126,27 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
TO_CONN(conn)->address = tor_dup_addr(&tor_addr); TO_CONN(conn)->address = tor_dup_addr(&tor_addr);
if (q->type == EVDNS_TYPE_A) if (q->type == EVDNS_TYPE_A)
conn->socks_request->command = SOCKS_COMMAND_RESOLVE; entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
else else
conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
strlcpy(conn->socks_request->address, q->name, strlcpy(entry_conn->socks_request->address, q->name,
sizeof(conn->socks_request->address)); sizeof(entry_conn->socks_request->address));
conn->socks_request->listener_type = listener->_base.type; entry_conn->socks_request->listener_type = listener->_base.type;
conn->dns_server_request = req; entry_conn->dns_server_request = req;
conn->isolation_flags = listener->isolation_flags; entry_conn->isolation_flags = listener->isolation_flags;
conn->session_group = listener->session_group; entry_conn->session_group = listener->session_group;
conn->nym_epoch = get_signewnym_epoch(); entry_conn->nym_epoch = get_signewnym_epoch();
if (connection_add(TO_CONN(conn)) < 0) { if (connection_add(ENTRY_TO_CONN(entry_conn)) < 0) {
log_warn(LD_APP, "Couldn't register dummy connection for DNS request"); log_warn(LD_APP, "Couldn't register dummy connection for DNS request");
evdns_server_request_respond(req, DNS_ERR_SERVERFAILED); evdns_server_request_respond(req, DNS_ERR_SERVERFAILED);
connection_free(TO_CONN(conn)); connection_free(ENTRY_TO_CONN(entry_conn));
return; return;
} }
control_event_stream_status(conn, STREAM_EVENT_NEW, 0); control_event_stream_status(entry_conn, STREAM_EVENT_NEW, 0);
/* Now, unless a controller asked us to leave streams unattached, /* Now, unless a controller asked us to leave streams unattached,
* throw the connection over to get rewritten (which will * throw the connection over to get rewritten (which will
@ -153,7 +155,7 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", log_info(LD_APP, "Passing request for %s to rewrite_and_attach.",
escaped_safe_str_client(q->name)); escaped_safe_str_client(q->name));
q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */ q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */
connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL);
/* Now, the connection is marked if it was bad. */ /* Now, the connection is marked if it was bad. */
log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.", log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.",
@ -169,28 +171,30 @@ evdns_server_callback(struct evdns_server_request *req, void *data_)
int int
dnsserv_launch_request(const char *name, int reverse) dnsserv_launch_request(const char *name, int reverse)
{ {
entry_connection_t *entry_conn;
edge_connection_t *conn; edge_connection_t *conn;
char *q_name; char *q_name;
/* Make a new dummy AP connection, and attach the request to it. */ /* Make a new dummy AP connection, and attach the request to it. */
conn = edge_connection_new(CONN_TYPE_AP, AF_INET); entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
conn = ENTRY_TO_EDGE_CONN(entry_conn);
conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
if (reverse) if (reverse)
conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
else else
conn->socks_request->command = SOCKS_COMMAND_RESOLVE; entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
conn->is_dns_request = 1; conn->is_dns_request = 1;
strlcpy(conn->socks_request->address, name, strlcpy(entry_conn->socks_request->address, name,
sizeof(conn->socks_request->address)); sizeof(entry_conn->socks_request->address));
conn->socks_request->listener_type = CONN_TYPE_CONTROL_LISTENER; entry_conn->socks_request->listener_type = CONN_TYPE_CONTROL_LISTENER;
conn->original_dest_address = tor_strdup(name); entry_conn->original_dest_address = tor_strdup(name);
conn->session_group = SESSION_GROUP_CONTROL_RESOLVE; entry_conn->session_group = SESSION_GROUP_CONTROL_RESOLVE;
conn->nym_epoch = get_signewnym_epoch(); entry_conn->nym_epoch = get_signewnym_epoch();
conn->isolation_flags = ISO_DEFAULT; entry_conn->isolation_flags = ISO_DEFAULT;
if (connection_add(TO_CONN(conn))<0) { if (connection_add(TO_CONN(conn))<0) {
log_warn(LD_APP, "Couldn't register dummy connection for RESOLVE request"); log_warn(LD_APP, "Couldn't register dummy connection for RESOLVE request");
@ -205,7 +209,7 @@ dnsserv_launch_request(const char *name, int reverse)
log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", log_info(LD_APP, "Passing request for %s to rewrite_and_attach.",
escaped_safe_str_client(name)); escaped_safe_str_client(name));
q_name = tor_strdup(name); /* q could be freed in rewrite_and_attach */ q_name = tor_strdup(name); /* q could be freed in rewrite_and_attach */
connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL);
/* Now, the connection is marked if it was bad. */ /* Now, the connection is marked if it was bad. */
log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.", log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.",
@ -217,7 +221,7 @@ dnsserv_launch_request(const char *name, int reverse)
/** If there is a pending request on <b>conn</b> that's waiting for an answer, /** If there is a pending request on <b>conn</b> that's waiting for an answer,
* send back an error and free the request. */ * send back an error and free the request. */
void void
dnsserv_reject_request(edge_connection_t *conn) dnsserv_reject_request(entry_connection_t *conn)
{ {
if (conn->dns_server_request) { if (conn->dns_server_request) {
evdns_server_request_respond(conn->dns_server_request, evdns_server_request_respond(conn->dns_server_request,
@ -263,7 +267,7 @@ evdns_get_orig_address(const struct evdns_server_request *req,
* <b>answer_len</b>, in <b>answer</b>, with TTL <b>ttl</b>. Doesn't do * <b>answer_len</b>, in <b>answer</b>, with TTL <b>ttl</b>. Doesn't do
* any caching; that's handled elsewhere. */ * any caching; that's handled elsewhere. */
void void
dnsserv_resolved(edge_connection_t *conn, dnsserv_resolved(entry_connection_t *conn,
int answer_type, int answer_type,
size_t answer_len, size_t answer_len,
const char *answer, const char *answer,

View File

@ -14,12 +14,12 @@
void dnsserv_configure_listener(connection_t *conn); void dnsserv_configure_listener(connection_t *conn);
void dnsserv_close_listener(connection_t *conn); void dnsserv_close_listener(connection_t *conn);
void dnsserv_resolved(edge_connection_t *conn, void dnsserv_resolved(entry_connection_t *conn,
int answer_type, int answer_type,
size_t answer_len, size_t answer_len,
const char *answer, const char *answer,
int ttl); int ttl);
void dnsserv_reject_request(edge_connection_t *conn); void dnsserv_reject_request(entry_connection_t *conn);
int dnsserv_launch_request(const char *name, int is_reverse); int dnsserv_launch_request(const char *name, int is_reverse);
#endif #endif

View File

@ -856,7 +856,7 @@ hibernate_go_dormant(time_t now)
connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING); connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING);
log_info(LD_NET,"Closing conn type %d", conn->type); log_info(LD_NET,"Closing conn type %d", conn->type);
if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */ if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */
connection_mark_unattached_ap(TO_EDGE_CONN(conn), connection_mark_unattached_ap(TO_ENTRY_CONN(conn),
END_STREAM_REASON_HIBERNATING); END_STREAM_REASON_HIBERNATING);
else else
connection_mark_for_close(conn); connection_mark_for_close(conn);

View File

@ -865,13 +865,13 @@ directory_all_unreachable(time_t now)
while ((conn = connection_get_by_type_state(CONN_TYPE_AP, while ((conn = connection_get_by_type_state(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT))) { AP_CONN_STATE_CIRCUIT_WAIT))) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn); entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
log_notice(LD_NET, log_notice(LD_NET,
"Is your network connection down? " "Is your network connection down? "
"Failing connection to '%s:%d'.", "Failing connection to '%s:%d'.",
safe_str_client(edge_conn->socks_request->address), safe_str_client(entry_conn->socks_request->address),
edge_conn->socks_request->port); entry_conn->socks_request->port);
connection_mark_unattached_ap(edge_conn, connection_mark_unattached_ap(entry_conn,
END_STREAM_REASON_NET_UNREACHABLE); END_STREAM_REASON_NET_UNREACHABLE);
} }
control_event_general_status(LOG_ERR, "DIR_ALL_UNREACHABLE"); control_event_general_status(LOG_ERR, "DIR_ALL_UNREACHABLE");

View File

@ -941,6 +941,7 @@ typedef struct socks_request_t socks_request_t;
#define BASE_CONNECTION_MAGIC 0x7C3C304Eu #define BASE_CONNECTION_MAGIC 0x7C3C304Eu
#define OR_CONNECTION_MAGIC 0x7D31FF03u #define OR_CONNECTION_MAGIC 0x7D31FF03u
#define EDGE_CONNECTION_MAGIC 0xF0374013u #define EDGE_CONNECTION_MAGIC 0xF0374013u
#define ENTRY_CONNECTION_MAGIC 0xbb4a5703
#define DIR_CONNECTION_MAGIC 0x9988ffeeu #define DIR_CONNECTION_MAGIC 0x9988ffeeu
#define CONTROL_CONNECTION_MAGIC 0x8abc765du #define CONTROL_CONNECTION_MAGIC 0x8abc765du
#define LISTENER_CONNECTION_MAGIC 0x1a1ac741u #define LISTENER_CONNECTION_MAGIC 0x1a1ac741u
@ -1173,27 +1174,27 @@ typedef struct or_connection_t {
* identity digest as this one. */ * identity digest as this one. */
} or_connection_t; } or_connection_t;
/** Subtype of connection_t for an "edge connection" -- that is, a socks (ap) /** Subtype of connection_t for an "edge connection" -- that is, an entry (ap)
* connection, or an exit. */ * connection, or an exit. */
typedef struct edge_connection_t { typedef struct edge_connection_t {
connection_t _base; connection_t _base;
struct edge_connection_t *next_stream; /**< Points to the next stream at this struct edge_connection_t *next_stream; /**< Points to the next stream at this
* edge, if any */ * edge, if any */
struct crypt_path_t *cpath_layer; /**< A pointer to which node in the circ
* this conn exits at. */
int package_window; /**< How many more relay cells can I send into the int package_window; /**< How many more relay cells can I send into the
* circuit? */ * circuit? */
int deliver_window; /**< How many more relay cells can end at me? */ int deliver_window; /**< How many more relay cells can end at me? */
/** Nickname of planned exit node -- used with .exit support. */
char *chosen_exit_name;
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
* only.) */
struct circuit_t *on_circuit; /**< The circuit (if any) that this edge struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
* connection is using. */ * connection is using. */
/** A pointer to which node in the circ this conn exits at. Set for AP
* connections and for hidden service exit connections. */
struct crypt_path_t *cpath_layer;
/** What rendezvous service are we querying for (if an AP) or providing (if
* an exit)? */
rend_data_t *rend_data;
uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
* connection. Exit connections only. */ * connection. Exit connections only. */
@ -1209,8 +1210,29 @@ typedef struct edge_connection_t {
/** Bytes written since last call to control_event_stream_bandwidth_used() */ /** Bytes written since last call to control_event_stream_bandwidth_used() */
uint32_t n_written; uint32_t n_written;
/** What rendezvous service are we querying for? (AP only) */ /** True iff this connection is for a DNS request only. */
rend_data_t *rend_data; unsigned int is_dns_request:1;
unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge
* connections. Set once we've set the stream end,
* and check in connection_about_to_close_connection().
*/
/** True iff we've blocked reading until the circuit has fewer queued
* cells. */
unsigned int edge_blocked_on_circ:1;
} edge_connection_t;
/** Subtype of edge_connection_t for an "entry connection" -- that is, a SOCKS
* connection, a DNS request, a TransPort connection or a NATD connection */
typedef struct entry_connection_t {
edge_connection_t _edge;
/** Nickname of planned exit node -- used with .exit support. */
char *chosen_exit_name;
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
* only.) */
/* === Isolation related, AP only. === */ /* === Isolation related, AP only. === */
/** AP only: based on which factors do we isolate this stream? */ /** AP only: based on which factors do we isolate this stream? */
@ -1231,6 +1253,19 @@ typedef struct edge_connection_t {
* already retried several times. */ * already retried several times. */
uint8_t num_socks_retries; uint8_t num_socks_retries;
/** For AP connections only: buffer for data that we have sent
* optimistically, which we might need to re-send if we have to
* retry this connection. */
generic_buffer_t *pending_optimistic_data;
/* For AP connections only: buffer for data that we previously sent
* optimistically which we are currently re-sending as we retry this
* connection. */
generic_buffer_t *sending_optimistic_data;
/** 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;
#define NUM_CIRCUITS_LAUNCHED_THRESHOLD 10 #define NUM_CIRCUITS_LAUNCHED_THRESHOLD 10
/** Number of times we've launched a circuit to handle this stream. If /** Number of times we've launched a circuit to handle this stream. If
* it gets too high, that could indicate an inconsistency between our * it gets too high, that could indicate an inconsistency between our
@ -1238,9 +1273,6 @@ typedef struct edge_connection_t {
* stream to one of the available circuits" logic. */ * stream to one of the available circuits" logic. */
unsigned int num_circuits_launched:4; unsigned int num_circuits_launched:4;
/** True iff this connection is for a DNS request only. */
unsigned int is_dns_request:1;
/** True iff this stream must attach to a one-hop circuit (e.g. for /** True iff this stream must attach to a one-hop circuit (e.g. for
* begin_dir). */ * begin_dir). */
unsigned int want_onehop:1; unsigned int want_onehop:1;
@ -1248,13 +1280,6 @@ typedef struct edge_connection_t {
* itself rather than BEGIN (either via onehop or via a whole circuit). */ * itself rather than BEGIN (either via onehop or via a whole circuit). */
unsigned int use_begindir:1; unsigned int use_begindir:1;
unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge
* connections. Set once we've set the stream end,
* and check in connection_about_to_close_connection().
*/
/** True iff we've blocked reading until the circuit has fewer queued
* cells. */
unsigned int edge_blocked_on_circ:1;
/** For AP connections only. If 1, and we fail to reach the chosen exit, /** For AP connections only. If 1, and we fail to reach the chosen exit,
* stop requiring it. */ * stop requiring it. */
unsigned int chosen_exit_optional:1; unsigned int chosen_exit_optional:1;
@ -1274,20 +1299,7 @@ typedef struct edge_connection_t {
*/ */
unsigned int may_use_optimistic_data : 1; unsigned int may_use_optimistic_data : 1;
/** For AP connections only: buffer for data that we have sent } entry_connection_t;
* optimistically, which we might need to re-send if we have to
* retry this connection. */
generic_buffer_t *pending_optimistic_data;
/* For AP connections only: buffer for data that we previously sent
* optimistically which we are currently re-sending as we retry this
* connection. */
generic_buffer_t *sending_optimistic_data;
/** 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;
} edge_connection_t;
/** Subtype of connection_t for an "directory connection" -- that is, an HTTP /** Subtype of connection_t for an "directory connection" -- that is, an HTTP
* connection to retrieve or serve directory material. */ * connection to retrieve or serve directory material. */
@ -1360,6 +1372,11 @@ typedef struct control_connection_t {
/** Helper macro: Given a pointer to to._base, of type from*, return &to. */ /** Helper macro: Given a pointer to to._base, of type from*, return &to. */
#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, _base)) #define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, _base))
/** Cast a entry_connection_t subtype pointer to a edge_connection_t **/
#define ENTRY_TO_EDGE_CONN(c) (&(((c))->_edge))
/** Cast a entry_connection_t subtype pointer to a connection_t **/
#define ENTRY_TO_CONN(c) (TO_CONN(ENTRY_TO_EDGE_CONN(c)))
/** Convert a connection_t* to an or_connection_t*; assert if the cast is /** Convert a connection_t* to an or_connection_t*; assert if the cast is
* invalid. */ * invalid. */
static or_connection_t *TO_OR_CONN(connection_t *); static or_connection_t *TO_OR_CONN(connection_t *);
@ -1369,6 +1386,12 @@ static dir_connection_t *TO_DIR_CONN(connection_t *);
/** Convert a connection_t* to an edge_connection_t*; assert if the cast is /** Convert a connection_t* to an edge_connection_t*; assert if the cast is
* invalid. */ * invalid. */
static edge_connection_t *TO_EDGE_CONN(connection_t *); static edge_connection_t *TO_EDGE_CONN(connection_t *);
/** Convert a connection_t* to an entry_connection_t*; assert if the cast is
* invalid. */
static entry_connection_t *TO_ENTRY_CONN(connection_t *);
/** Convert a edge_connection_t* to an entry_connection_t*; assert if the cast is
* invalid. */
static entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *);
/** Convert a connection_t* to an control_connection_t*; assert if the cast is /** Convert a connection_t* to an control_connection_t*; assert if the cast is
* invalid. */ * invalid. */
static control_connection_t *TO_CONTROL_CONN(connection_t *); static control_connection_t *TO_CONTROL_CONN(connection_t *);
@ -1388,9 +1411,20 @@ static INLINE dir_connection_t *TO_DIR_CONN(connection_t *c)
} }
static INLINE edge_connection_t *TO_EDGE_CONN(connection_t *c) static INLINE edge_connection_t *TO_EDGE_CONN(connection_t *c)
{ {
tor_assert(c->magic == EDGE_CONNECTION_MAGIC); tor_assert(c->magic == EDGE_CONNECTION_MAGIC ||
c->magic == ENTRY_CONNECTION_MAGIC);
return DOWNCAST(edge_connection_t, c); return DOWNCAST(edge_connection_t, c);
} }
static INLINE entry_connection_t *TO_ENTRY_CONN(connection_t *c)
{
tor_assert(c->magic == ENTRY_CONNECTION_MAGIC);
return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge._base);
}
static INLINE entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *c)
{
tor_assert(c->_base.magic == ENTRY_CONNECTION_MAGIC);
return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge);
}
static INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c) static INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c)
{ {
tor_assert(c->magic == CONTROL_CONNECTION_MAGIC); tor_assert(c->magic == CONTROL_CONNECTION_MAGIC);

View File

@ -649,6 +649,7 @@ connection_edge_send_command(edge_connection_t *fromconn,
{ {
/* XXXX NM Split this function into a separate versions per circuit type? */ /* XXXX NM Split this function into a separate versions per circuit type? */
circuit_t *circ; circuit_t *circ;
crypt_path_t *cpath_layer = fromconn->cpath_layer;
tor_assert(fromconn); tor_assert(fromconn);
circ = fromconn->on_circuit; circ = fromconn->on_circuit;
@ -663,7 +664,8 @@ connection_edge_send_command(edge_connection_t *fromconn,
if (!circ) { if (!circ) {
if (fromconn->_base.type == CONN_TYPE_AP) { if (fromconn->_base.type == CONN_TYPE_AP) {
log_info(LD_APP,"no circ. Closing conn."); log_info(LD_APP,"no circ. Closing conn.");
connection_mark_unattached_ap(fromconn, END_STREAM_REASON_INTERNAL); connection_mark_unattached_ap(EDGE_TO_ENTRY_CONN(fromconn),
END_STREAM_REASON_INTERNAL);
} else { } else {
log_info(LD_EXIT,"no circ. Closing conn."); log_info(LD_EXIT,"no circ. Closing conn.");
fromconn->edge_has_sent_end = 1; /* no circ to send to */ fromconn->edge_has_sent_end = 1; /* no circ to send to */
@ -675,7 +677,7 @@ connection_edge_send_command(edge_connection_t *fromconn,
return relay_send_command_from_edge(fromconn->stream_id, circ, return relay_send_command_from_edge(fromconn->stream_id, circ,
relay_command, payload, relay_command, payload,
payload_len, fromconn->cpath_layer); payload_len, cpath_layer);
} }
/** How many times will I retry a stream that fails due to DNS /** How many times will I retry a stream that fails due to DNS
@ -703,16 +705,17 @@ edge_reason_is_retriable(int reason)
static int static int
connection_ap_process_end_not_open( connection_ap_process_end_not_open(
relay_header_t *rh, cell_t *cell, origin_circuit_t *circ, relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
edge_connection_t *conn, crypt_path_t *layer_hint) entry_connection_t *conn, crypt_path_t *layer_hint)
{ {
struct in_addr in; struct in_addr in;
node_t *exitrouter; node_t *exitrouter;
int reason = *(cell->payload+RELAY_HEADER_SIZE); int reason = *(cell->payload+RELAY_HEADER_SIZE);
int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE; int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
(void) layer_hint; /* unused */ (void) layer_hint; /* unused */
if (rh->length > 0 && edge_reason_is_retriable(reason) && if (rh->length > 0 && edge_reason_is_retriable(reason) &&
!connection_edge_is_rendezvous_stream(conn) /* avoid retry if rend */ !connection_edge_is_rendezvous_stream(edge_conn) /* avoid retry if rend */
) { ) {
const char *chosen_exit_digest = const char *chosen_exit_digest =
circ->build_state->chosen_exit->identity_digest; circ->build_state->chosen_exit->identity_digest;
@ -840,7 +843,7 @@ connection_ap_process_end_not_open(
stream_end_reason_to_string(rh->length > 0 ? reason : -1)); stream_end_reason_to_string(rh->length > 0 ? reason : -1));
circuit_log_path(LOG_INFO,LD_APP,circ); circuit_log_path(LOG_INFO,LD_APP,circ);
/* need to test because of detach_retriable */ /* need to test because of detach_retriable */
if (!conn->_base.marked_for_close) if (!ENTRY_TO_CONN(conn)->marked_for_close)
connection_mark_unattached_ap(conn, control_reason); connection_mark_unattached_ap(conn, control_reason);
return 0; return 0;
} }
@ -849,7 +852,7 @@ connection_ap_process_end_not_open(
* dotted-quad representation of <b>new_addr</b> (given in host order), * dotted-quad representation of <b>new_addr</b> (given in host order),
* and send an appropriate REMAP event. */ * and send an appropriate REMAP event. */
static void static void
remap_event_helper(edge_connection_t *conn, uint32_t new_addr) remap_event_helper(entry_connection_t *conn, uint32_t new_addr)
{ {
struct in_addr in; struct in_addr in;
@ -875,7 +878,8 @@ connection_edge_process_relay_cell_not_open(
if (rh->command == RELAY_COMMAND_END) { if (rh->command == RELAY_COMMAND_END) {
if (CIRCUIT_IS_ORIGIN(circ) && conn->_base.type == CONN_TYPE_AP) { if (CIRCUIT_IS_ORIGIN(circ) && conn->_base.type == CONN_TYPE_AP) {
return connection_ap_process_end_not_open(rh, cell, return connection_ap_process_end_not_open(rh, cell,
TO_ORIGIN_CIRCUIT(circ), conn, TO_ORIGIN_CIRCUIT(circ),
EDGE_TO_ENTRY_CONN(conn),
layer_hint); layer_hint);
} else { } else {
/* we just got an 'end', don't need to send one */ /* we just got an 'end', don't need to send one */
@ -889,6 +893,7 @@ connection_edge_process_relay_cell_not_open(
if (conn->_base.type == CONN_TYPE_AP && if (conn->_base.type == CONN_TYPE_AP &&
rh->command == RELAY_COMMAND_CONNECTED) { rh->command == RELAY_COMMAND_CONNECTED) {
entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
tor_assert(CIRCUIT_IS_ORIGIN(circ)); tor_assert(CIRCUIT_IS_ORIGIN(circ));
if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) { if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) {
log_fn(LOG_PROTOCOL_WARN, LD_APP, log_fn(LOG_PROTOCOL_WARN, LD_APP,
@ -906,22 +911,23 @@ connection_edge_process_relay_cell_not_open(
log_info(LD_APP, "...but it claims the IP address was %s. Closing.", log_info(LD_APP, "...but it claims the IP address was %s. Closing.",
fmt_addr32(addr)); fmt_addr32(addr));
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL); connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); connection_mark_unattached_ap(entry_conn,
END_STREAM_REASON_TORPROTOCOL);
return 0; return 0;
} }
if (rh->length >= 8) if (rh->length >= 8)
ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4)); ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4));
else else
ttl = -1; ttl = -1;
client_dns_set_addressmap(conn->socks_request->address, addr, client_dns_set_addressmap(entry_conn->socks_request->address, addr,
conn->chosen_exit_name, ttl); entry_conn->chosen_exit_name, ttl);
remap_event_helper(conn, addr); remap_event_helper(entry_conn, addr);
} }
circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ)); circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
/* don't send a socks reply to transparent conns */ /* don't send a socks reply to transparent conns */
if (!conn->socks_request->has_finished) if (!entry_conn->socks_request->has_finished)
connection_ap_handshake_socks_reply(conn, NULL, 0, 0); connection_ap_handshake_socks_reply(entry_conn, NULL, 0, 0);
/* Was it a linked dir conn? If so, a dir request just started to /* Was it a linked dir conn? If so, a dir request just started to
* fetch something; this could be a bootstrap status milestone. */ * fetch something; this could be a bootstrap status milestone. */
@ -946,9 +952,9 @@ connection_edge_process_relay_cell_not_open(
} }
/* This is definitely a success, so forget about any pending data we /* This is definitely a success, so forget about any pending data we
* had sent. */ * had sent. */
if (conn->pending_optimistic_data) { if (entry_conn->pending_optimistic_data) {
generic_buffer_free(conn->pending_optimistic_data); generic_buffer_free(entry_conn->pending_optimistic_data);
conn->pending_optimistic_data = NULL; entry_conn->pending_optimistic_data = NULL;
} }
/* handle anything that might have queued */ /* handle anything that might have queued */
@ -964,17 +970,18 @@ connection_edge_process_relay_cell_not_open(
int ttl; int ttl;
int answer_len; int answer_len;
uint8_t answer_type; uint8_t answer_type;
entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) { if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got a 'resolved' cell while " log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got a 'resolved' cell while "
"not in state resolve_wait. Dropping."); "not in state resolve_wait. Dropping.");
return 0; return 0;
} }
tor_assert(SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)); tor_assert(SOCKS_COMMAND_IS_RESOLVE(entry_conn->socks_request->command));
answer_len = cell->payload[RELAY_HEADER_SIZE+1]; answer_len = cell->payload[RELAY_HEADER_SIZE+1];
if (rh->length < 2 || answer_len+2>rh->length) { if (rh->length < 2 || answer_len+2>rh->length) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Dropping malformed 'resolved' cell"); "Dropping malformed 'resolved' cell");
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL);
return 0; return 0;
} }
answer_type = cell->payload[RELAY_HEADER_SIZE]; answer_type = cell->payload[RELAY_HEADER_SIZE];
@ -989,14 +996,14 @@ connection_edge_process_relay_cell_not_open(
is_internal_IP(addr, 0)) { is_internal_IP(addr, 0)) {
log_info(LD_APP,"Got a resolve with answer %s. Rejecting.", log_info(LD_APP,"Got a resolve with answer %s. Rejecting.",
fmt_addr32(addr)); fmt_addr32(addr));
connection_ap_handshake_socks_resolved(conn, connection_ap_handshake_socks_resolved(entry_conn,
RESOLVED_TYPE_ERROR_TRANSIENT, RESOLVED_TYPE_ERROR_TRANSIENT,
0, NULL, 0, TIME_MAX); 0, NULL, 0, TIME_MAX);
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); connection_mark_unattached_ap(entry_conn,END_STREAM_REASON_TORPROTOCOL);
return 0; return 0;
} }
} }
connection_ap_handshake_socks_resolved(conn, connection_ap_handshake_socks_resolved(entry_conn,
answer_type, answer_type,
cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/ cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/
cell->payload+RELAY_HEADER_SIZE+2, /*answer*/ cell->payload+RELAY_HEADER_SIZE+2, /*answer*/
@ -1004,9 +1011,9 @@ connection_edge_process_relay_cell_not_open(
-1); -1);
if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) { if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2)); uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
remap_event_helper(conn, addr); remap_event_helper(entry_conn, addr);
} }
connection_mark_unattached_ap(conn, connection_mark_unattached_ap(entry_conn,
END_STREAM_REASON_DONE | END_STREAM_REASON_DONE |
END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
return 0; return 0;
@ -1164,9 +1171,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
conn->_base.s, conn->_base.s,
stream_end_reason_to_string(reason), stream_end_reason_to_string(reason),
conn->stream_id); conn->stream_id);
if (conn->socks_request && !conn->socks_request->has_finished) if (conn->_base.type == CONN_TYPE_AP) {
entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
if (entry_conn->socks_request &&
!entry_conn->socks_request->has_finished)
log_warn(LD_BUG, log_warn(LD_BUG,
"open stream hasn't sent socks answer yet? Closing."); "open stream hasn't sent socks answer yet? Closing.");
}
/* We just *got* an end; no reason to send one. */ /* We just *got* an end; no reason to send one. */
conn->edge_has_sent_end = 1; conn->edge_has_sent_end = 1;
if (!conn->end_reason) if (!conn->end_reason)
@ -1348,11 +1359,14 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
size_t amount_to_process, length; size_t amount_to_process, length;
char payload[CELL_PAYLOAD_SIZE]; char payload[CELL_PAYLOAD_SIZE];
circuit_t *circ; circuit_t *circ;
unsigned domain = conn->cpath_layer ? LD_APP : LD_EXIT; const unsigned domain = conn->_base.type == CONN_TYPE_AP ? LD_APP : LD_EXIT;
int sending_from_optimistic = 0; int sending_from_optimistic = 0;
const int sending_optimistically = const int sending_optimistically =
conn->_base.type == CONN_TYPE_AP && conn->_base.type == CONN_TYPE_AP &&
conn->_base.state != AP_CONN_STATE_OPEN; conn->_base.state != AP_CONN_STATE_OPEN;
entry_connection_t *entry_conn =
conn->_base.type == CONN_TYPE_AP ? EDGE_TO_ENTRY_CONN(conn) : NULL;
crypt_path_t *cpath_layer = conn->cpath_layer;
tor_assert(conn); tor_assert(conn);
@ -1375,7 +1389,7 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
return -1; return -1;
} }
if (circuit_consider_stop_edge_reading(circ, conn->cpath_layer)) if (circuit_consider_stop_edge_reading(circ, cpath_layer))
return 0; return 0;
if (conn->package_window <= 0) { if (conn->package_window <= 0) {
@ -1385,10 +1399,11 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
return 0; return 0;
} }
sending_from_optimistic = conn->sending_optimistic_data != NULL; sending_from_optimistic = entry_conn &&
entry_conn->sending_optimistic_data != NULL;
if (PREDICT_UNLIKELY(sending_from_optimistic)) { if (PREDICT_UNLIKELY(sending_from_optimistic)) {
amount_to_process = generic_buffer_len(conn->sending_optimistic_data); amount_to_process = generic_buffer_len(entry_conn->sending_optimistic_data);
if (PREDICT_UNLIKELY(!amount_to_process)) { if (PREDICT_UNLIKELY(!amount_to_process)) {
log_warn(LD_BUG, "sending_optimistic_data was non-NULL but empty"); log_warn(LD_BUG, "sending_optimistic_data was non-NULL but empty");
amount_to_process = connection_get_inbuf_len(TO_CONN(conn)); amount_to_process = connection_get_inbuf_len(TO_CONN(conn));
@ -1416,10 +1431,10 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
/* XXX023 We could be more efficient here by sometimes packing /* XXX023 We could be more efficient here by sometimes packing
* previously-sent optimistic data in the same cell with data * previously-sent optimistic data in the same cell with data
* from the inbuf. */ * from the inbuf. */
generic_buffer_get(conn->sending_optimistic_data, payload, length); generic_buffer_get(entry_conn->sending_optimistic_data, payload, length);
if (!generic_buffer_len(conn->sending_optimistic_data)) { if (!generic_buffer_len(entry_conn->sending_optimistic_data)) {
generic_buffer_free(conn->sending_optimistic_data); generic_buffer_free(entry_conn->sending_optimistic_data);
conn->sending_optimistic_data = NULL; entry_conn->sending_optimistic_data = NULL;
} }
} else { } else {
connection_fetch_from_buf(payload, length, TO_CONN(conn)); connection_fetch_from_buf(payload, length, TO_CONN(conn));
@ -1431,9 +1446,9 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
if (sending_optimistically && !sending_from_optimistic) { if (sending_optimistically && !sending_from_optimistic) {
/* This is new optimistic data; remember it in case we need to detach and /* This is new optimistic data; remember it in case we need to detach and
retry */ retry */
if (!conn->pending_optimistic_data) if (!entry_conn->pending_optimistic_data)
conn->pending_optimistic_data = generic_buffer_new(); entry_conn->pending_optimistic_data = generic_buffer_new();
generic_buffer_add(conn->pending_optimistic_data, payload, length); generic_buffer_add(entry_conn->pending_optimistic_data, payload, length);
} }
if (connection_edge_send_command(conn, RELAY_COMMAND_DATA, if (connection_edge_send_command(conn, RELAY_COMMAND_DATA,
@ -1441,18 +1456,18 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
/* circuit got marked for close, don't continue, don't need to mark conn */ /* circuit got marked for close, don't continue, don't need to mark conn */
return 0; return 0;
if (!conn->cpath_layer) { /* non-rendezvous exit */ if (!cpath_layer) { /* non-rendezvous exit */
tor_assert(circ->package_window > 0); tor_assert(circ->package_window > 0);
circ->package_window--; circ->package_window--;
} else { /* we're an AP, or an exit on a rendezvous circ */ } else { /* we're an AP, or an exit on a rendezvous circ */
tor_assert(conn->cpath_layer->package_window > 0); tor_assert(cpath_layer->package_window > 0);
conn->cpath_layer->package_window--; cpath_layer->package_window--;
} }
if (--conn->package_window <= 0) { /* is it 0 after decrement? */ if (--conn->package_window <= 0) { /* is it 0 after decrement? */
connection_stop_reading(TO_CONN(conn)); connection_stop_reading(TO_CONN(conn));
log_debug(domain,"conn->package_window reached 0."); log_debug(domain,"conn->package_window reached 0.");
circuit_consider_stop_edge_reading(circ, conn->cpath_layer); circuit_consider_stop_edge_reading(circ, cpath_layer);
return 0; /* don't process the inbuf any more */ return 0; /* don't process the inbuf any more */
} }
log_debug(domain,"conn->package_window is now %d",conn->package_window); log_debug(domain,"conn->package_window is now %d",conn->package_window);
@ -1491,7 +1506,7 @@ connection_edge_consider_sending_sendme(edge_connection_t *conn)
} }
while (conn->deliver_window <= STREAMWINDOW_START - STREAMWINDOW_INCREMENT) { while (conn->deliver_window <= STREAMWINDOW_START - STREAMWINDOW_INCREMENT) {
log_debug(conn->cpath_layer?LD_APP:LD_EXIT, log_debug(conn->_base.type == CONN_TYPE_AP ?LD_APP:LD_EXIT,
"Outbuf %d, Queuing stream sendme.", "Outbuf %d, Queuing stream sendme.",
(int)conn->_base.outbuf_flushlen); (int)conn->_base.outbuf_flushlen);
conn->deliver_window += STREAMWINDOW_INCREMENT; conn->deliver_window += STREAMWINDOW_INCREMENT;
@ -1693,9 +1708,10 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
if (layer_hint->package_window <= 0) { if (layer_hint->package_window <= 0) {
log_debug(domain,"yes, at-origin. stopped."); log_debug(domain,"yes, at-origin. stopped.");
for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn; for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn;
conn=conn->next_stream) conn=conn->next_stream) {
if (conn->cpath_layer == layer_hint) if (conn->cpath_layer == layer_hint)
connection_stop_reading(TO_CONN(conn)); connection_stop_reading(TO_CONN(conn));
}
return 1; return 1;
} }
return 0; return 0;

View File

@ -824,40 +824,42 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
void void
rend_client_desc_trynow(const char *query) rend_client_desc_trynow(const char *query)
{ {
edge_connection_t *conn; entry_connection_t *conn;
rend_cache_entry_t *entry; rend_cache_entry_t *entry;
const rend_data_t *rend_data;
time_t now = time(NULL); time_t now = time(NULL);
smartlist_t *conns = get_connection_array(); smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, _conn) { SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
if (_conn->type != CONN_TYPE_AP || if (base_conn->type != CONN_TYPE_AP ||
_conn->state != AP_CONN_STATE_RENDDESC_WAIT || base_conn->state != AP_CONN_STATE_RENDDESC_WAIT ||
_conn->marked_for_close) base_conn->marked_for_close)
continue; continue;
conn = TO_EDGE_CONN(_conn); conn = TO_ENTRY_CONN(base_conn);
if (!conn->rend_data) rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data;
if (!rend_data)
continue; continue;
if (rend_cmp_service_ids(query, conn->rend_data->onion_address)) if (rend_cmp_service_ids(query, rend_data->onion_address))
continue; continue;
assert_connection_ok(TO_CONN(conn), now); assert_connection_ok(base_conn, now);
if (rend_cache_lookup_entry(conn->rend_data->onion_address, -1, if (rend_cache_lookup_entry(rend_data->onion_address, -1,
&entry) == 1 && &entry) == 1 &&
rend_client_any_intro_points_usable(entry)) { rend_client_any_intro_points_usable(entry)) {
/* either this fetch worked, or it failed but there was a /* either this fetch worked, or it failed but there was a
* valid entry from before which we should reuse */ * valid entry from before which we should reuse */
log_info(LD_REND,"Rend desc is usable. Launching circuits."); log_info(LD_REND,"Rend desc is usable. Launching circuits.");
conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
/* restart their timeout values, so they get a fair shake at /* restart their timeout values, so they get a fair shake at
* connecting to the hidden service. */ * connecting to the hidden service. */
conn->_base.timestamp_created = now; base_conn->timestamp_created = now;
conn->_base.timestamp_lastread = now; base_conn->timestamp_lastread = now;
conn->_base.timestamp_lastwritten = now; base_conn->timestamp_lastwritten = now;
if (connection_ap_handshake_attach_circuit(conn) < 0) { if (connection_ap_handshake_attach_circuit(conn) < 0) {
/* it will never work */ /* it will never work */
log_warn(LD_REND,"Rendezvous attempt failed. Closing."); log_warn(LD_REND,"Rendezvous attempt failed. Closing.");
if (!conn->_base.marked_for_close) if (!base_conn->marked_for_close)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
} }
} else { /* 404, or fetch didn't get that far */ } else { /* 404, or fetch didn't get that far */
@ -866,7 +868,7 @@ rend_client_desc_trynow(const char *query)
safe_str_client(query)); safe_str_client(query));
connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED); connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
} }
} SMARTLIST_FOREACH_END(_conn); } SMARTLIST_FOREACH_END(base_conn);
} }
/** Return a newly allocated extend_info_t* for a randomly chosen introduction /** Return a newly allocated extend_info_t* for a randomly chosen introduction