r6908@Kushana: nickm | 2006-07-26 12:38:52 -0400

Refactor connection_t into edge, or, dir, control, and base subtypes.  This might save some RAM on busy exit servers, but really matters most in terms of correctness.


svn:r6906
This commit is contained in:
Nick Mathewson 2006-07-26 19:07:26 +00:00
parent 18771e851f
commit 4ff4577beb
20 changed files with 1275 additions and 1101 deletions

View file

@ -60,14 +60,13 @@ static void entry_guards_changed(void);
* Return it, or 0 if can't get a unique circ_id. * Return it, or 0 if can't get a unique circ_id.
*/ */
static uint16_t static uint16_t
get_unique_circ_id_by_conn(connection_t *conn) get_unique_circ_id_by_conn(or_connection_t *conn)
{ {
uint16_t test_circ_id; uint16_t test_circ_id;
uint16_t attempts=0; uint16_t attempts=0;
uint16_t high_bit; uint16_t high_bit;
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_OR);
high_bit = (conn->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0; high_bit = (conn->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
do { do {
/* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a /* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a
@ -277,7 +276,7 @@ int
circuit_handle_first_hop(origin_circuit_t *circ) circuit_handle_first_hop(origin_circuit_t *circ)
{ {
crypt_path_t *firsthop; crypt_path_t *firsthop;
connection_t *n_conn; or_connection_t *n_conn;
char tmpbuf[INET_NTOA_BUF_LEN]; char tmpbuf[INET_NTOA_BUF_LEN];
struct in_addr in; struct in_addr in;
@ -298,15 +297,15 @@ circuit_handle_first_hop(origin_circuit_t *circ)
/* If we don't have an open conn, or the conn we have is obsolete /* If we don't have an open conn, or the conn we have is obsolete
* (i.e. old or broken) and the other side will let us make a second * (i.e. old or broken) and the other side will let us make a second
* connection without dropping it immediately... */ * connection without dropping it immediately... */
if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN || if (!n_conn || n_conn->_base.state != OR_CONN_STATE_OPEN ||
(n_conn->is_obsolete && (n_conn->_base.or_is_obsolete &&
router_digest_version_as_new_as(firsthop->extend_info->identity_digest, router_digest_version_as_new_as(firsthop->extend_info->identity_digest,
"0.1.1.9-alpha-cvs"))) { "0.1.1.9-alpha-cvs"))) {
/* not currently connected */ /* not currently connected */
circ->_base.n_addr = firsthop->extend_info->addr; circ->_base.n_addr = firsthop->extend_info->addr;
circ->_base.n_port = firsthop->extend_info->port; circ->_base.n_port = firsthop->extend_info->port;
if (!n_conn || n_conn->is_obsolete) { /* launch the connection */ if (!n_conn || n_conn->_base.or_is_obsolete) { /* launch the connection */
n_conn = connection_or_connect(firsthop->extend_info->addr, n_conn = connection_or_connect(firsthop->extend_info->addr,
firsthop->extend_info->port, firsthop->extend_info->port,
firsthop->extend_info->identity_digest); firsthop->extend_info->identity_digest);
@ -323,8 +322,8 @@ circuit_handle_first_hop(origin_circuit_t *circ)
*/ */
return 0; return 0;
} else { /* it's already open. use it. */ } else { /* it's already open. use it. */
circ->_base.n_addr = n_conn->addr; circ->_base.n_addr = n_conn->_base.addr;
circ->_base.n_port = n_conn->port; circ->_base.n_port = n_conn->_base.port;
circ->_base.n_conn = n_conn; circ->_base.n_conn = n_conn;
log_debug(LD_CIRC,"Conn open. Delivering first onion skin."); log_debug(LD_CIRC,"Conn open. Delivering first onion skin.");
if (circuit_send_next_onion_skin(circ) < 0) { if (circuit_send_next_onion_skin(circ) < 0) {
@ -341,7 +340,7 @@ circuit_handle_first_hop(origin_circuit_t *circ)
* Status is 1 if connect succeeded, or 0 if connect failed. * Status is 1 if connect succeeded, or 0 if connect failed.
*/ */
void void
circuit_n_conn_done(connection_t *or_conn, int status) circuit_n_conn_done(or_connection_t *or_conn, int status)
{ {
extern smartlist_t *circuits_pending_or_conns; extern smartlist_t *circuits_pending_or_conns;
smartlist_t *changed_circs; smartlist_t *changed_circs;
@ -419,7 +418,6 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
tor_assert(circ); tor_assert(circ);
tor_assert(circ->n_conn); tor_assert(circ->n_conn);
tor_assert(circ->n_conn->type == CONN_TYPE_OR);
tor_assert(payload); tor_assert(payload);
tor_assert(cell_type == CELL_CREATE || cell_type == CELL_CREATE_FAST); tor_assert(cell_type == CELL_CREATE || cell_type == CELL_CREATE_FAST);
@ -621,7 +619,7 @@ circuit_note_clock_jumped(int seconds_elapsed)
int int
circuit_extend(cell_t *cell, circuit_t *circ) circuit_extend(cell_t *cell, circuit_t *circ)
{ {
connection_t *n_conn; or_connection_t *n_conn;
relay_header_t rh; relay_header_t rh;
char *onionskin; char *onionskin;
char *id_digest=NULL; char *id_digest=NULL;
@ -651,8 +649,8 @@ circuit_extend(cell_t *cell, circuit_t *circ)
/* If we don't have an open conn, or the conn we have is obsolete /* If we don't have an open conn, or the conn we have is obsolete
* (i.e. old or broken) and the other side will let us make a second * (i.e. old or broken) and the other side will let us make a second
* connection without dropping it immediately... */ * connection without dropping it immediately... */
if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN || if (!n_conn || n_conn->_base.state != OR_CONN_STATE_OPEN ||
(n_conn->is_obsolete && (n_conn->_base.or_is_obsolete &&
router_digest_version_as_new_as(id_digest,"0.1.1.9-alpha-cvs"))) { router_digest_version_as_new_as(id_digest,"0.1.1.9-alpha-cvs"))) {
struct in_addr in; struct in_addr in;
char tmpbuf[INET_NTOA_BUF_LEN]; char tmpbuf[INET_NTOA_BUF_LEN];
@ -668,9 +666,9 @@ circuit_extend(cell_t *cell, circuit_t *circ)
/* imprint the circuit with its future n_conn->id */ /* imprint the circuit with its future n_conn->id */
memcpy(circ->n_conn_id_digest, id_digest, DIGEST_LEN); memcpy(circ->n_conn_id_digest, id_digest, DIGEST_LEN);
if (n_conn && !n_conn->is_obsolete) { if (n_conn && !n_conn->_base.or_is_obsolete) {
circ->n_addr = n_conn->addr; circ->n_addr = n_conn->_base.addr;
circ->n_port = n_conn->port; circ->n_port = n_conn->_base.port;
} else { } else {
/* we should try to open a connection */ /* we should try to open a connection */
n_conn = connection_or_connect(circ->n_addr, circ->n_port, id_digest); n_conn = connection_or_connect(circ->n_addr, circ->n_port, id_digest);
@ -689,12 +687,12 @@ circuit_extend(cell_t *cell, circuit_t *circ)
} }
/* these may be different if the router connected to us from elsewhere */ /* these may be different if the router connected to us from elsewhere */
circ->n_addr = n_conn->addr; circ->n_addr = n_conn->_base.addr;
circ->n_port = n_conn->port; circ->n_port = n_conn->_base.port;
circ->n_conn = n_conn; circ->n_conn = n_conn;
memcpy(circ->n_conn_id_digest, n_conn->identity_digest, DIGEST_LEN); memcpy(circ->n_conn_id_digest, n_conn->identity_digest, DIGEST_LEN);
log_debug(LD_CIRC,"n_conn is %s:%u",n_conn->address,n_conn->port); log_debug(LD_CIRC,"n_conn is %s:%u",n_conn->_base.address,n_conn->_base.port);
if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0) if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0)
return -1; return -1;
@ -910,7 +908,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, char *payload,
connection_or_write_cell_to_buf(&cell, circ->p_conn); connection_or_write_cell_to_buf(&cell, circ->p_conn);
log_debug(LD_CIRC,"Finished sending 'created' cell."); log_debug(LD_CIRC,"Finished sending 'created' cell.");
if (!is_local_IP(circ->p_conn->addr) && if (!is_local_IP(circ->p_conn->_base.addr) &&
!connection_or_nonopen_was_started_here(circ->p_conn)) { !connection_or_nonopen_was_started_here(circ->p_conn)) {
/* record that we could process create cells from a non-local conn /* record that we could process create cells from a non-local conn
* that we didn't initiate; presumably this means that create cells * that we didn't initiate; presumably this means that create cells
@ -1048,8 +1046,9 @@ ap_stream_wants_exit_attention(connection_t *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 &&
!connection_edge_is_rendezvous_stream(conn) && !connection_edge_is_rendezvous_stream(TO_EDGE_CONN(conn)) &&
!circuit_stream_is_being_handled(conn, 0, MIN_CIRCUITS_HANDLING_STREAM)) !circuit_stream_is_being_handled(TO_EDGE_CONN(conn), 0,
MIN_CIRCUITS_HANDLING_STREAM))
return 1; return 1;
return 0; return 0;
} }
@ -1134,7 +1133,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
for (j = 0; j < n_connections; ++j) { /* iterate over connections */ for (j = 0; j < n_connections; ++j) { /* iterate over connections */
if (!ap_stream_wants_exit_attention(carray[j])) if (!ap_stream_wants_exit_attention(carray[j]))
continue; /* Skip everything but APs in CIRCUIT_WAIT */ continue; /* Skip everything but APs in CIRCUIT_WAIT */
if (connection_ap_can_use_exit(carray[j], router)) { if (connection_ap_can_use_exit(TO_EDGE_CONN(carray[j]), router)) {
++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

@ -33,7 +33,7 @@ static void circuit_free_cpath_node(crypt_path_t *victim);
* very important here, since we need to do it every time a cell arrives.) */ * very important here, since we need to do it every time a cell arrives.) */
typedef struct orconn_circid_circuit_map_t { typedef struct orconn_circid_circuit_map_t {
HT_ENTRY(orconn_circid_circuit_map_t) node; HT_ENTRY(orconn_circid_circuit_map_t) node;
connection_t *or_conn; or_connection_t *or_conn;
uint16_t circ_id; uint16_t circ_id;
circuit_t *circuit; circuit_t *circuit;
} orconn_circid_circuit_map_t; } orconn_circid_circuit_map_t;
@ -70,8 +70,8 @@ orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL;
static void static void
circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id, circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
connection_t *conn, or_connection_t *conn,
uint16_t old_id, connection_t *old_conn) uint16_t old_id, or_connection_t *old_conn)
{ {
orconn_circid_circuit_map_t search; orconn_circid_circuit_map_t search;
orconn_circid_circuit_map_t *found; orconn_circid_circuit_map_t *found;
@ -85,7 +85,7 @@ circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
} }
if (old_conn) { /* we may need to remove it from the conn-circid map */ if (old_conn) { /* we may need to remove it from the conn-circid map */
tor_assert(old_conn->magic == CONNECTION_MAGIC); tor_assert(old_conn->_base.magic == OR_CONNECTION_MAGIC);
search.circ_id = old_id; search.circ_id = old_id;
search.or_conn = old_conn; search.or_conn = old_conn;
found = HT_REMOVE(orconn_circid_map, &orconn_circid_circuit_map, &search); found = HT_REMOVE(orconn_circid_map, &orconn_circid_circuit_map, &search);
@ -119,10 +119,10 @@ circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
* to the (orconn,id)-\>circuit map. */ * to the (orconn,id)-\>circuit map. */
void void
circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id, circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
connection_t *conn) or_connection_t *conn)
{ {
uint16_t old_id; uint16_t old_id;
connection_t *old_conn; or_connection_t *old_conn;
old_id = circ->p_circ_id; old_id = circ->p_circ_id;
old_conn = circ->p_conn; old_conn = circ->p_conn;
@ -140,10 +140,10 @@ circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
* to the (orconn,id)-\>circuit map. */ * to the (orconn,id)-\>circuit map. */
void void
circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id, circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
connection_t *conn) or_connection_t *conn)
{ {
uint16_t old_id; uint16_t old_id;
connection_t *old_conn; or_connection_t *old_conn;
old_id = circ->n_circ_id; old_id = circ->n_circ_id;
old_conn = circ->n_conn; old_conn = circ->n_conn;
@ -279,7 +279,7 @@ origin_circuit_new(void)
} }
or_circuit_t * or_circuit_t *
or_circuit_new(uint16_t p_circ_id, connection_t *p_conn) or_circuit_new(uint16_t p_circ_id, or_connection_t *p_conn)
{ {
/* CircIDs */ /* CircIDs */
or_circuit_t *circ; or_circuit_t *circ;
@ -379,9 +379,9 @@ circuit_free_all(void)
if (! CIRCUIT_IS_ORIGIN(global_circuitlist)) { if (! CIRCUIT_IS_ORIGIN(global_circuitlist)) {
or_circuit_t *or_circ = TO_OR_CIRCUIT(global_circuitlist); or_circuit_t *or_circ = TO_OR_CIRCUIT(global_circuitlist);
while (or_circ->resolving_streams) { while (or_circ->resolving_streams) {
connection_t *next; edge_connection_t *next;
next = or_circ->resolving_streams->next_stream; next = or_circ->resolving_streams->next_stream;
connection_free(or_circ->resolving_streams); connection_free(TO_CONN(or_circ->resolving_streams));
or_circ->resolving_streams = next; or_circ->resolving_streams = next;
} }
} }
@ -439,7 +439,7 @@ void
circuit_dump_by_conn(connection_t *conn, int severity) circuit_dump_by_conn(connection_t *conn, int severity)
{ {
circuit_t *circ; circuit_t *circ;
connection_t *tmpconn; edge_connection_t *tmpconn;
for (circ=global_circuitlist;circ;circ = circ->next) { for (circ=global_circuitlist;circ;circ = circ->next) {
circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0; circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
@ -449,25 +449,26 @@ circuit_dump_by_conn(connection_t *conn, int severity)
if (! CIRCUIT_IS_ORIGIN(circ)) if (! CIRCUIT_IS_ORIGIN(circ))
p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_conn == conn) if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_conn &&
TO_CONN(TO_OR_CIRCUIT(circ)->p_conn) == conn)
circuit_dump_details(severity, circ, conn->poll_index, "App-ward", circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
p_circ_id, n_circ_id); p_circ_id, n_circ_id);
if (CIRCUIT_IS_ORIGIN(circ)) { if (CIRCUIT_IS_ORIGIN(circ)) {
for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn; for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
tmpconn=tmpconn->next_stream) { tmpconn=tmpconn->next_stream) {
if (tmpconn == conn) { if (TO_CONN(tmpconn) == conn) {
circuit_dump_details(severity, circ, conn->poll_index, "App-ward", circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
p_circ_id, n_circ_id); p_circ_id, n_circ_id);
} }
} }
} }
if (circ->n_conn == conn) if (circ->n_conn && TO_CONN(circ->n_conn) == conn)
circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward", circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
n_circ_id, p_circ_id); n_circ_id, p_circ_id);
if (! CIRCUIT_IS_ORIGIN(circ)) { if (! CIRCUIT_IS_ORIGIN(circ)) {
for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn; for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
tmpconn=tmpconn->next_stream) { tmpconn=tmpconn->next_stream) {
if (tmpconn == conn) { if (TO_CONN(tmpconn) == conn) {
circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward", circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
n_circ_id, p_circ_id); n_circ_id, p_circ_id);
} }
@ -476,7 +477,9 @@ circuit_dump_by_conn(connection_t *conn, int severity)
if (!circ->n_conn && circ->n_addr && circ->n_port && if (!circ->n_conn && circ->n_addr && circ->n_port &&
circ->n_addr == conn->addr && circ->n_addr == conn->addr &&
circ->n_port == conn->port && circ->n_port == conn->port &&
!memcmp(conn->identity_digest, circ->n_conn_id_digest, DIGEST_LEN)) { conn->type == CONN_TYPE_OR &&
!memcmp(TO_OR_CONN(conn)->identity_digest, circ->n_conn_id_digest,
DIGEST_LEN)) {
circuit_dump_details(severity, circ, conn->poll_index, circuit_dump_details(severity, circ, conn->poll_index,
(circ->state == CIRCUIT_STATE_OPEN && (circ->state == CIRCUIT_STATE_OPEN &&
!CIRCUIT_IS_ORIGIN(circ)) ? !CIRCUIT_IS_ORIGIN(circ)) ?
@ -509,13 +512,11 @@ circuit_get_by_global_id(uint32_t id)
* Return NULL if no such circuit exists. * Return NULL if no such circuit exists.
*/ */
static INLINE circuit_t * static INLINE circuit_t *
circuit_get_by_circid_orconn_impl(uint16_t circ_id, connection_t *conn) circuit_get_by_circid_orconn_impl(uint16_t circ_id, or_connection_t *conn)
{ {
orconn_circid_circuit_map_t search; orconn_circid_circuit_map_t search;
orconn_circid_circuit_map_t *found; orconn_circid_circuit_map_t *found;
tor_assert(conn->type == CONN_TYPE_OR);
if (_last_circid_orconn_ent && if (_last_circid_orconn_ent &&
circ_id == _last_circid_orconn_ent->circ_id && circ_id == _last_circid_orconn_ent->circ_id &&
conn == _last_circid_orconn_ent->or_conn) { conn == _last_circid_orconn_ent->or_conn) {
@ -560,7 +561,7 @@ circuit_get_by_circid_orconn_impl(uint16_t circ_id, connection_t *conn)
* Return NULL if no such circuit exists. * Return NULL if no such circuit exists.
*/ */
circuit_t * circuit_t *
circuit_get_by_circid_orconn(uint16_t circ_id, connection_t *conn) circuit_get_by_circid_orconn(uint16_t circ_id, or_connection_t *conn)
{ {
circuit_t *circ = circuit_get_by_circid_orconn_impl(circ_id, conn); circuit_t *circ = circuit_get_by_circid_orconn_impl(circ_id, conn);
if (!circ || circ->marked_for_close) if (!circ || circ->marked_for_close)
@ -575,7 +576,7 @@ circuit_get_by_circid_orconn(uint16_t circ_id, connection_t *conn)
* Return NULL if no such circuit exists. * Return NULL if no such circuit exists.
*/ */
int int
circuit_id_used_on_conn(uint16_t circ_id, connection_t *conn) circuit_id_used_on_conn(uint16_t circ_id, or_connection_t *conn)
{ {
circuit_t *circ = circuit_get_by_circid_orconn_impl(circ_id, conn); circuit_t *circ = circuit_get_by_circid_orconn_impl(circ_id, conn);
if (circ && circ->marked_for_close) if (circ && circ->marked_for_close)
@ -587,10 +588,9 @@ circuit_id_used_on_conn(uint16_t circ_id, connection_t *conn)
/** Return the circuit that a given edge connection is using. */ /** Return the circuit that a given edge connection is using. */
circuit_t * circuit_t *
circuit_get_by_edge_conn(connection_t *conn) circuit_get_by_edge_conn(edge_connection_t *conn)
{ {
circuit_t *circ; circuit_t *circ;
tor_assert(CONN_IS_EDGE(conn));
circ = conn->on_circuit; circ = conn->on_circuit;
tor_assert(!circ || tor_assert(!circ ||
@ -605,7 +605,7 @@ circuit_get_by_edge_conn(connection_t *conn)
* been marked already. * been marked already.
*/ */
void void
circuit_unlink_all_from_or_conn(connection_t *conn, int reason) circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason)
{ {
circuit_t *circ; circuit_t *circ;
for (circ = global_circuitlist; circ; circ = circ->next) { for (circ = global_circuitlist; circ; circ = circ->next) {
@ -820,8 +820,6 @@ void
_circuit_mark_for_close(circuit_t *circ, int reason, int line, _circuit_mark_for_close(circuit_t *circ, int reason, int line,
const char *file) const char *file)
{ {
connection_t *conn;
assert_circuit_ok(circ); assert_circuit_ok(circ);
tor_assert(line); tor_assert(line);
tor_assert(file); tor_assert(file);
@ -889,18 +887,19 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
if (! CIRCUIT_IS_ORIGIN(circ)) { if (! CIRCUIT_IS_ORIGIN(circ)) {
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ); or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
edge_connection_t *conn;
for (conn=or_circ->n_streams; conn; conn=conn->next_stream) for (conn=or_circ->n_streams; conn; conn=conn->next_stream)
connection_edge_destroy(or_circ->p_circ_id, conn); connection_edge_destroy(or_circ->p_circ_id, conn);
while (or_circ->resolving_streams) { while (or_circ->resolving_streams) {
conn = or_circ->resolving_streams; conn = or_circ->resolving_streams;
or_circ->resolving_streams = conn->next_stream; or_circ->resolving_streams = conn->next_stream;
if (!conn->marked_for_close) { if (!conn->_base.marked_for_close) {
/* The other side will see a DESTROY, and infer that the connections /* The other side will see a DESTROY, and infer that the connections
* are closing because the circuit is getting torn down. No need * are closing because the circuit is getting torn down. No need
* to send an end cell. */ * to send an end cell. */
conn->has_sent_end = 1; conn->_base.edge_has_sent_end = 1;
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
} }
conn->on_circuit = NULL; conn->on_circuit = NULL;
} }
@ -909,6 +908,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
connection_or_send_destroy(or_circ->p_circ_id, or_circ->p_conn, reason); connection_or_send_destroy(or_circ->p_circ_id, or_circ->p_conn, reason);
} else { } else {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
edge_connection_t *conn;
for (conn=ocirc->p_streams; conn; conn=conn->next_stream) for (conn=ocirc->p_streams; conn; conn=conn->next_stream)
connection_edge_destroy(circ->n_circ_id, conn); connection_edge_destroy(circ->n_circ_id, conn);
} }
@ -987,7 +987,7 @@ assert_cpath_ok(const crypt_path_t *cp)
void void
assert_circuit_ok(const circuit_t *c) assert_circuit_ok(const circuit_t *c)
{ {
connection_t *conn; edge_connection_t *conn;
const or_circuit_t *or_circ = NULL; const or_circuit_t *or_circ = NULL;
const origin_circuit_t *origin_circ = NULL; const origin_circuit_t *origin_circ = NULL;
@ -1002,24 +1002,22 @@ assert_circuit_ok(const circuit_t *c)
or_circ = TO_OR_CIRCUIT((circuit_t*)c); or_circ = TO_OR_CIRCUIT((circuit_t*)c);
if (c->n_conn) { if (c->n_conn) {
tor_assert(c->n_conn->type == CONN_TYPE_OR);
tor_assert(!memcmp(c->n_conn->identity_digest, c->n_conn_id_digest, tor_assert(!memcmp(c->n_conn->identity_digest, c->n_conn_id_digest,
DIGEST_LEN)); DIGEST_LEN));
if (c->n_circ_id) if (c->n_circ_id)
tor_assert(c == circuit_get_by_circid_orconn(c->n_circ_id, c->n_conn)); tor_assert(c == circuit_get_by_circid_orconn(c->n_circ_id, c->n_conn));
} }
if (or_circ && or_circ->p_conn) { if (or_circ && or_circ->p_conn) {
tor_assert(or_circ->p_conn->type == CONN_TYPE_OR);
if (or_circ->p_circ_id) if (or_circ->p_circ_id)
tor_assert(c == circuit_get_by_circid_orconn(or_circ->p_circ_id, tor_assert(c == circuit_get_by_circid_orconn(or_circ->p_circ_id,
or_circ->p_conn)); or_circ->p_conn));
} }
if (origin_circ) if (origin_circ)
for (conn = origin_circ->p_streams; conn; conn = conn->next_stream) for (conn = origin_circ->p_streams; conn; conn = conn->next_stream)
tor_assert(conn->type == CONN_TYPE_AP); tor_assert(conn->_base.type == CONN_TYPE_AP);
if (or_circ) if (or_circ)
for (conn = or_circ->n_streams; conn; conn = conn->next_stream) for (conn = or_circ->n_streams; conn; conn = conn->next_stream)
tor_assert(conn->type == CONN_TYPE_EXIT); tor_assert(conn->_base.type == CONN_TYPE_EXIT);
tor_assert(c->deliver_window >= 0); tor_assert(c->deliver_window >= 0);
tor_assert(c->package_window >= 0); tor_assert(c->package_window >= 0);

View file

@ -26,7 +26,7 @@ static void circuit_increment_failure_count(void);
* Else return 0. * Else return 0.
*/ */
static int static int
circuit_is_acceptable(circuit_t *circ, connection_t *conn, circuit_is_acceptable(circuit_t *circ, edge_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)
@ -155,7 +155,7 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
* 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(connection_t *conn, int must_be_open, uint8_t purpose, circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
int need_uptime, int need_internal) int need_uptime, int need_internal)
{ {
circuit_t *circ, *best=NULL; circuit_t *circ, *best=NULL;
@ -255,7 +255,7 @@ circuit_expire_building(time_t now)
if (victim->n_conn) if (victim->n_conn)
log_info(LD_CIRC,"Abandoning circ %s:%d:%d (state %d:%s, purpose %d)", log_info(LD_CIRC,"Abandoning circ %s:%d:%d (state %d:%s, purpose %d)",
victim->n_conn->address, victim->n_port, victim->n_circ_id, victim->n_conn->_base.address, victim->n_port, victim->n_circ_id,
victim->state, circuit_state_to_string(victim->state), victim->state, circuit_state_to_string(victim->state),
victim->purpose); victim->purpose);
else else
@ -296,7 +296,7 @@ circuit_remove_handled_ports(smartlist_t *needed_ports)
* Else return 0. * Else return 0.
*/ */
int int
circuit_stream_is_being_handled(connection_t *conn, uint16_t port, int min) circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port, int min)
{ {
circuit_t *circ; circuit_t *circ;
routerinfo_t *exitrouter; routerinfo_t *exitrouter;
@ -457,9 +457,9 @@ circuit_build_needed_circs(time_t now)
* lists of <b>circ</b>, then remove it from the list. * lists of <b>circ</b>, then remove it from the list.
*/ */
void void
circuit_detach_stream(circuit_t *circ, connection_t *conn) circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
{ {
connection_t *prevconn; edge_connection_t *prevconn;
tor_assert(circ); tor_assert(circ);
tor_assert(conn); tor_assert(conn);
@ -536,10 +536,11 @@ circuit_about_to_close_connection(connection_t *conn)
if (!connection_state_is_open(conn)) { if (!connection_state_is_open(conn)) {
/* Inform any pending (not attached) circs that they should /* Inform any pending (not attached) circs that they should
* give up. */ * give up. */
circuit_n_conn_done(conn, 0); circuit_n_conn_done(TO_OR_CONN(conn), 0);
} }
/* Now close all the attached circuits on it. */ /* Now close all the attached circuits on it. */
circuit_unlink_all_from_or_conn(conn, END_CIRC_REASON_OR_CONN_CLOSED); circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
END_CIRC_REASON_OR_CONN_CLOSED);
return; return;
} }
case CONN_TYPE_AP: case CONN_TYPE_AP:
@ -550,11 +551,11 @@ circuit_about_to_close_connection(connection_t *conn)
* been sent. But don't kill the circuit. * been sent. But don't kill the circuit.
*/ */
circ = circuit_get_by_edge_conn(conn); circ = circuit_get_by_edge_conn(TO_EDGE_CONN(conn));
if (!circ) if (!circ)
return; return;
circuit_detach_stream(circ, conn); circuit_detach_stream(circ, TO_EDGE_CONN(conn));
} }
} /* end switch */ } /* end switch */
} }
@ -683,7 +684,7 @@ circuit_build_failed(origin_circuit_t *circ)
circ->cpath->state != CPATH_STATE_OPEN) { circ->cpath->state != CPATH_STATE_OPEN) {
/* We failed at the first hop. If there's an OR connection /* We failed at the first hop. If there's an OR connection
to blame, blame it. */ to blame, blame it. */
connection_t *n_conn = NULL; or_connection_t *n_conn = NULL;
if (circ->_base.n_conn) { if (circ->_base.n_conn) {
n_conn = circ->_base.n_conn; n_conn = circ->_base.n_conn;
} else if (circ->_base.state == CIRCUIT_STATE_OR_WAIT) { } else if (circ->_base.state == CIRCUIT_STATE_OR_WAIT) {
@ -695,8 +696,8 @@ circuit_build_failed(origin_circuit_t *circ)
log_info(LD_OR, log_info(LD_OR,
"Our circuit failed to get a response from the first hop " "Our circuit failed to get a response from the first hop "
"(%s:%d). I'm going to try to rotate to a better connection.", "(%s:%d). I'm going to try to rotate to a better connection.",
n_conn->address, n_conn->port); n_conn->_base.address, n_conn->_base.port);
n_conn->is_obsolete = 1; n_conn->_base.or_is_obsolete = 1;
entry_guard_set_status(n_conn->identity_digest, 0); entry_guard_set_status(n_conn->identity_digest, 0);
} }
} }
@ -893,7 +894,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(connection_t *conn, circuit_get_open_circ_or_launch(edge_connection_t *conn,
uint8_t desired_circuit_purpose, uint8_t desired_circuit_purpose,
origin_circuit_t **circp) origin_circuit_t **circp)
{ {
@ -903,7 +904,7 @@ circuit_get_open_circ_or_launch(connection_t *conn,
tor_assert(conn); tor_assert(conn);
tor_assert(circp); tor_assert(circp);
tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
is_resolve = conn->socks_request->command == SOCKS_COMMAND_RESOLVE; is_resolve = conn->socks_request->command == SOCKS_COMMAND_RESOLVE;
need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts, need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts,
@ -966,7 +967,7 @@ circuit_get_open_circ_or_launch(connection_t *conn,
"No intro points for '%s': refetching service descriptor.", "No intro points for '%s': refetching service descriptor.",
safe_str(conn->rend_query)); safe_str(conn->rend_query));
rend_client_refetch_renddesc(conn->rend_query); rend_client_refetch_renddesc(conn->rend_query);
conn->state = AP_CONN_STATE_RENDDESC_WAIT; conn->_base.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'.",
@ -1033,13 +1034,13 @@ circuit_get_open_circ_or_launch(connection_t *conn,
* circ's cpath. * circ's cpath.
*/ */
static void static void
link_apconn_to_circ(connection_t *apconn, origin_circuit_t *circ) link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ)
{ {
/* add it into the linked list of streams on this circuit */ /* 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.", 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->timestamp_lastread = time(NULL); apconn->_base.timestamp_lastread = time(NULL);
apconn->next_stream = circ->p_streams; apconn->next_stream = circ->p_streams;
apconn->on_circuit = TO_CIRCUIT(circ); apconn->on_circuit = TO_CIRCUIT(circ);
/* assert_connection_ok(conn, time(NULL)); */ /* assert_connection_ok(conn, time(NULL)); */
@ -1054,7 +1055,7 @@ link_apconn_to_circ(connection_t *apconn, origin_circuit_t *circ)
/** If an exit wasn't specifically chosen, save the history for future /** If an exit wasn't specifically chosen, save the history for future
* use. */ * use. */
static void static void
consider_recording_trackhost(connection_t *conn, origin_circuit_t *circ) consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
{ {
int found_needle = 0; int found_needle = 0;
char *str; char *str;
@ -1108,18 +1109,17 @@ consider_recording_trackhost(connection_t *conn, origin_circuit_t *circ)
* send a begin or resolve cell as appropriate. Return values are as * send a begin or resolve cell as appropriate. Return values are as
* for connection_ap_handshake_attach_circuit. */ * for connection_ap_handshake_attach_circuit. */
int int
connection_ap_handshake_attach_chosen_circuit(connection_t *conn, connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
origin_circuit_t *circ) origin_circuit_t *circ)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_AP); tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT ||
tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT || conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT);
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->state = AP_CONN_STATE_CIRCUIT_WAIT; conn->_base.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);
@ -1146,19 +1146,18 @@ connection_ap_handshake_attach_chosen_circuit(connection_t *conn,
* right next step, and return 1. * right next step, and return 1.
*/ */
int int
connection_ap_handshake_attach_circuit(connection_t *conn) connection_ap_handshake_attach_circuit(edge_connection_t *conn)
{ {
int retval; int retval;
int conn_age; int conn_age;
int severity; int severity;
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_AP); tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(conn->socks_request); tor_assert(conn->socks_request);
conn_age = time(NULL) - conn->timestamp_created; conn_age = time(NULL) - conn->_base.timestamp_created;
severity = (!conn->addr && !conn->port) ? LOG_INFO : LOG_NOTICE; severity = (!conn->_base.addr && !conn->_base.port) ? LOG_INFO : LOG_NOTICE;
if (conn_age > get_options()->SocksTimeout) { if (conn_age > get_options()->SocksTimeout) {
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.",

View file

@ -27,10 +27,10 @@ uint64_t stats_n_relay_cells_processed = 0;
uint64_t stats_n_destroy_cells_processed = 0; uint64_t stats_n_destroy_cells_processed = 0;
/* These are the main four functions for processing cells */ /* These are the main four functions for processing cells */
static void command_process_create_cell(cell_t *cell, connection_t *conn); static void command_process_create_cell(cell_t *cell, or_connection_t *conn);
static void command_process_created_cell(cell_t *cell, connection_t *conn); static void command_process_created_cell(cell_t *cell, or_connection_t *conn);
static void command_process_relay_cell(cell_t *cell, connection_t *conn); static void command_process_relay_cell(cell_t *cell, or_connection_t *conn);
static void command_process_destroy_cell(cell_t *cell, connection_t *conn); static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn);
#ifdef KEEP_TIMING_STATS #ifdef KEEP_TIMING_STATS
/** This is a wrapper function around the actual function that processes the /** This is a wrapper function around the actual function that processes the
@ -38,8 +38,8 @@ static void command_process_destroy_cell(cell_t *cell, connection_t *conn);
* by the number of microseconds used by the call to <b>*func(cell, conn)</b>. * by the number of microseconds used by the call to <b>*func(cell, conn)</b>.
*/ */
static void static void
command_time_process_cell(cell_t *cell, connection_t *conn, int *time, command_time_process_cell(cell_t *cell, or_connection_t *conn, int *time,
void (*func)(cell_t *, connection_t *)) void (*func)(cell_t *, or_connection_t *))
{ {
struct timeval start, end; struct timeval start, end;
long time_passed; long time_passed;
@ -68,7 +68,7 @@ command_time_process_cell(cell_t *cell, connection_t *conn, int *time,
* process each type of cell. * process each type of cell.
*/ */
void void
command_process_cell(cell_t *cell, connection_t *conn) command_process_cell(cell_t *cell, or_connection_t *conn)
{ {
#ifdef KEEP_TIMING_STATS #ifdef KEEP_TIMING_STATS
/* how many of each cell have we seen so far this second? needs better /* how many of each cell have we seen so far this second? needs better
@ -159,7 +159,7 @@ command_process_cell(cell_t *cell, connection_t *conn)
* picked up again when the cpuworker finishes decrypting it. * picked up again when the cpuworker finishes decrypting it.
*/ */
static void static void
command_process_create_cell(cell_t *cell, connection_t *conn) command_process_create_cell(cell_t *cell, or_connection_t *conn)
{ {
or_circuit_t *circ; or_circuit_t *circ;
int id_is_high; int id_is_high;
@ -191,7 +191,7 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received CREATE cell (circID %d) for known circ. " "Received CREATE cell (circID %d) for known circ. "
"Dropping (age %d).", "Dropping (age %d).",
cell->circ_id, (int)(time(NULL) - conn->timestamp_created)); cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created));
if (router) if (router)
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Details: nickname \"%s\", platform %s.", "Details: nickname \"%s\", platform %s.",
@ -241,7 +241,7 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
* extend to the next hop in the circuit if necessary. * extend to the next hop in the circuit if necessary.
*/ */
static void static void
command_process_created_cell(cell_t *cell, connection_t *conn) command_process_created_cell(cell_t *cell, or_connection_t *conn)
{ {
circuit_t *circ; circuit_t *circ;
@ -290,7 +290,7 @@ command_process_created_cell(cell_t *cell, connection_t *conn)
* circuit_receive_relay_cell() for actual processing. * circuit_receive_relay_cell() for actual processing.
*/ */
static void static void
command_process_relay_cell(cell_t *cell, connection_t *conn) command_process_relay_cell(cell_t *cell, or_connection_t *conn)
{ {
circuit_t *circ; circuit_t *circ;
int reason; int reason;
@ -300,7 +300,7 @@ command_process_relay_cell(cell_t *cell, connection_t *conn)
if (!circ) { if (!circ) {
log_debug(LD_OR, log_debug(LD_OR,
"unknown circuit %d on connection from %s:%d. Dropping.", "unknown circuit %d on connection from %s:%d. Dropping.",
cell->circ_id, conn->address, conn->port); cell->circ_id, conn->_base.address, conn->_base.port);
return; return;
} }
@ -345,7 +345,7 @@ command_process_relay_cell(cell_t *cell, connection_t *conn)
* and passes the destroy cell onward if necessary). * and passes the destroy cell onward if necessary).
*/ */
static void static void
command_process_destroy_cell(cell_t *cell, connection_t *conn) command_process_destroy_cell(cell_t *cell, or_connection_t *conn)
{ {
circuit_t *circ; circuit_t *circ;
uint8_t reason; uint8_t reason;
@ -354,7 +354,7 @@ command_process_destroy_cell(cell_t *cell, connection_t *conn)
reason = (uint8_t)cell->payload[0]; reason = (uint8_t)cell->payload[0];
if (!circ) { if (!circ) {
log_info(LD_OR,"unknown circuit %d on connection from %s:%d. Dropping.", log_info(LD_OR,"unknown circuit %d on connection from %s:%d. Dropping.",
cell->circ_id, conn->address, conn->port); cell->circ_id, conn->_base.address, conn->_base.port);
return; return;
} }
log_debug(LD_OR,"Received for circID %d.",cell->circ_id); log_debug(LD_OR,"Received for circID %d.",cell->circ_id);

View file

@ -18,7 +18,7 @@ static connection_t *connection_create_listener(const char *listenaddress,
uint16_t listenport, int type); uint16_t listenport, int type);
static int connection_init_accepted_conn(connection_t *conn); static int connection_init_accepted_conn(connection_t *conn);
static int connection_handle_listener_read(connection_t *conn, int new_type); static int connection_handle_listener_read(connection_t *conn, int new_type);
static int connection_receiver_bucket_should_increase(connection_t *conn); static int connection_receiver_bucket_should_increase(or_connection_t *conn);
static int connection_finished_flushing(connection_t *conn); static int connection_finished_flushing(connection_t *conn);
static int connection_flushed_some(connection_t *conn); static int connection_flushed_some(connection_t *conn);
static int connection_finished_connecting(connection_t *conn); static int connection_finished_connecting(connection_t *conn);
@ -161,9 +161,35 @@ connection_new(int type)
static uint32_t n_connections_allocated = 0; static uint32_t n_connections_allocated = 0;
connection_t *conn; connection_t *conn;
time_t now = time(NULL); time_t now = time(NULL);
size_t length;
uint32_t magic;
conn = tor_malloc_zero(sizeof(connection_t)); switch (type) {
conn->magic = CONNECTION_MAGIC; case CONN_TYPE_OR:
length = sizeof(or_connection_t);
magic = OR_CONNECTION_MAGIC;
break;
case CONN_TYPE_EXIT:
case CONN_TYPE_AP:
length = sizeof(edge_connection_t);
magic = EDGE_CONNECTION_MAGIC;
break;
case CONN_TYPE_DIR:
length = sizeof(dir_connection_t);
magic = DIR_CONNECTION_MAGIC;
break;
case CONN_TYPE_CONTROL:
length = sizeof(control_connection_t);
magic = CONTROL_CONNECTION_MAGIC;
break;
default:
length = sizeof(connection_t);
magic = BASE_CONNECTION_MAGIC;
break;
}
conn = tor_malloc_zero(length);
conn->magic = magic;
conn->s = -1; /* give it a default of 'not used' */ conn->s = -1; /* give it a default of 'not used' */
conn->poll_index = -1; /* also default to 'not used' */ conn->poll_index = -1; /* also default to 'not used' */
conn->global_identifier = n_connections_allocated++; conn->global_identifier = n_connections_allocated++;
@ -174,10 +200,11 @@ connection_new(int type)
conn->outbuf = buf_new(); conn->outbuf = buf_new();
} }
if (type == CONN_TYPE_AP) { if (type == CONN_TYPE_AP) {
conn->socks_request = tor_malloc_zero(sizeof(socks_request_t)); TO_EDGE_CONN(conn)->socks_request =
tor_malloc_zero(sizeof(socks_request_t));
} }
if (type == CONN_TYPE_OR)
conn->next_circ_id = crypto_rand_int(1<<15); TO_OR_CONN(conn)->next_circ_id = crypto_rand_int(1<<15);
conn->timestamp_created = now; conn->timestamp_created = now;
conn->timestamp_lastread = now; conn->timestamp_lastread = now;
@ -209,28 +236,72 @@ connection_unregister(connection_t *conn)
static void static void
_connection_free(connection_t *conn) _connection_free(connection_t *conn)
{ {
tor_assert(conn->magic == CONNECTION_MAGIC); void *mem;
switch (conn->type) {
case CONN_TYPE_OR:
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
mem = TO_OR_CONN(conn);
break;
case CONN_TYPE_AP:
case CONN_TYPE_EXIT:
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
mem = TO_EDGE_CONN(conn);
break;
case CONN_TYPE_DIR:
tor_assert(conn->magic == DIR_CONNECTION_MAGIC);
mem = TO_DIR_CONN(conn);
break;
case CONN_TYPE_CONTROL:
tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC);
mem = TO_CONTROL_CONN(conn);
break;
default:
tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
mem = conn;
break;
}
if (!connection_is_listener(conn)) { if (!connection_is_listener(conn)) {
buf_free(conn->inbuf); buf_free(conn->inbuf);
buf_free(conn->outbuf); buf_free(conn->outbuf);
} }
tor_free(conn->address); tor_free(conn->address);
tor_free(conn->chosen_exit_name);
if (connection_speaks_cells(conn)) { if (connection_speaks_cells(conn)) {
if (conn->tls) { or_connection_t *or_conn = TO_OR_CONN(conn);
tor_tls_free(conn->tls); if (or_conn->tls) {
conn->tls = NULL; tor_tls_free(or_conn->tls);
or_conn->tls = NULL;
} }
tor_free(or_conn->nickname);
}
if (CONN_IS_EDGE(conn)) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
tor_free(edge_conn->chosen_exit_name);
tor_free(edge_conn->socks_request);
}
if (conn->type == CONN_TYPE_CONTROL) {
control_connection_t *control_conn = TO_CONTROL_CONN(conn);
tor_free(control_conn->incoming_cmd);
} }
tor_free(conn->nickname);
tor_free(conn->socks_request);
tor_free(conn->incoming_cmd);
tor_free(conn->read_event); /* Probably already freed by connection_free. */ tor_free(conn->read_event); /* Probably already freed by connection_free. */
tor_free(conn->write_event); /* Probably already freed by connection_free. */ tor_free(conn->write_event); /* Probably already freed by connection_free. */
tor_free(conn->requested_resource);
if (conn->type == CONN_TYPE_DIR) {
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
tor_free(dir_conn->requested_resource);
if (dir_conn->zlib_state)
tor_zlib_free(dir_conn->zlib_state);
if (dir_conn->fingerprint_stack) {
SMARTLIST_FOREACH(dir_conn->fingerprint_stack, char *, cp, tor_free(cp));
smartlist_free(dir_conn->fingerprint_stack);
}
if (dir_conn->cached_dir)
cached_dir_decref(dir_conn->cached_dir);
}
if (conn->s >= 0) { if (conn->s >= 0) {
log_debug(LD_NET,"closing fd %d.",conn->s); log_debug(LD_NET,"closing fd %d.",conn->s);
@ -238,21 +309,13 @@ _connection_free(connection_t *conn)
} }
if (conn->type == CONN_TYPE_OR && if (conn->type == CONN_TYPE_OR &&
!tor_digest_is_zero(conn->identity_digest)) { !tor_digest_is_zero(TO_OR_CONN(conn)->identity_digest)) {
log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest"); log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest");
connection_or_remove_from_identity_map(conn); connection_or_remove_from_identity_map(TO_OR_CONN(conn));
} }
if (conn->zlib_state)
tor_zlib_free(conn->zlib_state);
if (conn->fingerprint_stack) {
SMARTLIST_FOREACH(conn->fingerprint_stack, char *, cp, tor_free(cp));
smartlist_free(conn->fingerprint_stack);
}
if (conn->cached_dir)
cached_dir_decref(conn->cached_dir);
memset(conn, 0xAA, sizeof(connection_t)); /* poison memory */ memset(conn, 0xAA, sizeof(connection_t)); /* poison memory */
tor_free(conn); tor_free(mem);
} }
/** Make sure <b>conn</b> isn't in any of the global conn lists; then free it. /** Make sure <b>conn</b> isn't in any of the global conn lists; then free it.
@ -266,12 +329,12 @@ connection_free(connection_t *conn)
if (connection_speaks_cells(conn)) { if (connection_speaks_cells(conn)) {
if (conn->state == OR_CONN_STATE_OPEN) if (conn->state == OR_CONN_STATE_OPEN)
directory_set_dirty(); directory_set_dirty();
if (!tor_digest_is_zero(conn->identity_digest)) { if (!tor_digest_is_zero(TO_OR_CONN(conn)->identity_digest)) {
connection_or_remove_from_identity_map(conn); connection_or_remove_from_identity_map(TO_OR_CONN(conn));
} }
} }
if (conn->type == CONN_TYPE_CONTROL) { if (conn->type == CONN_TYPE_CONTROL) {
conn->event_mask = 0; TO_CONTROL_CONN(conn)->event_mask = 0;
control_update_global_event_mask(); control_update_global_event_mask();
} }
connection_unregister(conn); connection_unregister(conn);
@ -297,7 +360,7 @@ connection_free_all(void)
/* We don't want to log any messages to controllers. */ /* We don't want to log any messages to controllers. */
for (i=0;i<n;i++) for (i=0;i<n;i++)
if (carray[i]->type == CONN_TYPE_CONTROL) if (carray[i]->type == CONN_TYPE_CONTROL)
carray[i]->event_mask = 0; TO_CONTROL_CONN(carray[i])->event_mask = 0;
control_update_global_event_mask(); control_update_global_event_mask();
/* Unlink everything from the identity map. */ /* Unlink everything from the identity map. */
@ -326,11 +389,14 @@ void
connection_about_to_close_connection(connection_t *conn) connection_about_to_close_connection(connection_t *conn)
{ {
circuit_t *circ; circuit_t *circ;
dir_connection_t *dir_conn;
or_connection_t *or_conn;
edge_connection_t *edge_conn;
assert(conn->marked_for_close); assert(conn->marked_for_close);
if (CONN_IS_EDGE(conn)) { if (CONN_IS_EDGE(conn)) {
if (!conn->has_sent_end) { if (!conn->edge_has_sent_end) {
log_warn(LD_BUG, "Harmless bug: Edge connection (marked at %s:%d) " log_warn(LD_BUG, "Harmless bug: Edge connection (marked at %s:%d) "
"hasn't sent end yet?", "hasn't sent end yet?",
conn->marked_for_close_file, conn->marked_for_close); conn->marked_for_close_file, conn->marked_for_close);
@ -340,23 +406,25 @@ connection_about_to_close_connection(connection_t *conn)
switch (conn->type) { switch (conn->type) {
case CONN_TYPE_DIR: case CONN_TYPE_DIR:
dir_conn = TO_DIR_CONN(conn);
if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) { if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
/* It's a directory connection and connecting or fetching /* It's a directory connection and connecting or fetching
* failed: forget about this router, and maybe try again. */ * failed: forget about this router, and maybe try again. */
connection_dir_request_failed(conn); connection_dir_request_failed(dir_conn);
// XXX if it's rend desc we may want to retry -RD // XXX if it's rend desc we may want to retry -RD
} }
if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC) if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC)
rend_client_desc_here(conn->rend_query); /* give it a try */ rend_client_desc_here(dir_conn->rend_query); /* give it a try */
break; break;
case CONN_TYPE_OR: case CONN_TYPE_OR:
or_conn = TO_OR_CONN(conn);
/* Remember why we're closing this connection. */ /* Remember why we're closing this connection. */
if (conn->state != OR_CONN_STATE_OPEN) { if (conn->state != OR_CONN_STATE_OPEN) {
if (connection_or_nonopen_was_started_here(conn)) { if (connection_or_nonopen_was_started_here(or_conn)) {
rep_hist_note_connect_failed(conn->identity_digest, time(NULL)); rep_hist_note_connect_failed(or_conn->identity_digest, time(NULL));
entry_guard_set_status(conn->identity_digest, 0); entry_guard_set_status(or_conn->identity_digest, 0);
router_set_status(conn->identity_digest, 0); router_set_status(or_conn->identity_digest, 0);
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED); control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED);
} }
} else if (conn->hold_open_until_flushed) { } else if (conn->hold_open_until_flushed) {
/* XXXX009 We used to have an arg that told us whether we closed the /* XXXX009 We used to have an arg that told us whether we closed the
@ -368,30 +436,32 @@ connection_about_to_close_connection(connection_t *conn)
* flushing still get noted as dead, not disconnected. But this is an * flushing still get noted as dead, not disconnected. But this is an
* improvement. -NM * improvement. -NM
*/ */
rep_hist_note_disconnect(conn->identity_digest, time(NULL)); rep_hist_note_disconnect(or_conn->identity_digest, time(NULL));
control_event_or_conn_status(conn, OR_CONN_EVENT_CLOSED); control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED);
} else if (conn->identity_digest) { } else if (or_conn->identity_digest) {
rep_hist_note_connection_died(conn->identity_digest, time(NULL)); rep_hist_note_connection_died(or_conn->identity_digest, time(NULL));
control_event_or_conn_status(conn, OR_CONN_EVENT_CLOSED); control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED);
} }
break; break;
case CONN_TYPE_AP: case CONN_TYPE_AP:
if (conn->socks_request->has_finished == 0) { edge_conn = TO_EDGE_CONN(conn);
if (edge_conn->socks_request->has_finished == 0) {
/* since conn gets removed right after this function finishes, /* since conn gets removed right after this function finishes,
* there's no point trying to send back a reply at this point. */ * there's no point trying to send back a reply at this point. */
log_warn(LD_BUG,"Bug: Closing stream (marked at %s:%d) without sending" log_warn(LD_BUG,"Bug: Closing stream (marked at %s:%d) without sending"
" back a socks reply.", " back a socks reply.",
conn->marked_for_close_file, conn->marked_for_close); conn->marked_for_close_file, conn->marked_for_close);
} else { } else {
control_event_stream_status(conn, STREAM_EVENT_CLOSED); control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED);
} }
break; break;
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
edge_conn = TO_EDGE_CONN(conn);
if (conn->state == EXIT_CONN_STATE_RESOLVING) { if (conn->state == EXIT_CONN_STATE_RESOLVING) {
circ = circuit_get_by_edge_conn(conn); circ = circuit_get_by_edge_conn(edge_conn);
if (circ) if (circ)
circuit_detach_stream(circ, conn); circuit_detach_stream(circ, edge_conn);
connection_dns_remove(conn); connection_dns_remove(edge_conn);
} }
break; break;
case CONN_TYPE_DNSWORKER: case CONN_TYPE_DNSWORKER:
@ -731,8 +801,8 @@ connection_init_accepted_conn(connection_t *conn)
switch (conn->type) { switch (conn->type) {
case CONN_TYPE_OR: case CONN_TYPE_OR:
control_event_or_conn_status(conn, OR_CONN_EVENT_NEW); control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW);
return connection_tls_start_handshake(conn, 1); return connection_tls_start_handshake(TO_OR_CONN(conn), 1);
case CONN_TYPE_AP: case CONN_TYPE_AP:
conn->state = AP_CONN_STATE_SOCKS_WAIT; conn->state = AP_CONN_STATE_SOCKS_WAIT;
break; break;
@ -1006,9 +1076,11 @@ connection_bucket_read_limit(connection_t *conn)
if (at_most > global_read_bucket) if (at_most > global_read_bucket)
at_most = global_read_bucket; at_most = global_read_bucket;
if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) {
if (at_most > conn->receiver_bucket) or_connection_t *or_conn = TO_OR_CONN(conn);
at_most = conn->receiver_bucket; if (at_most > or_conn->receiver_bucket)
at_most = or_conn->receiver_bucket;
}
if (at_most < 0) if (at_most < 0)
return 0; return 0;
@ -1052,7 +1124,7 @@ connection_read_bucket_decrement(connection_t *conn, int num_read)
{ {
global_read_bucket -= num_read; global_read_bucket -= num_read;
if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) { if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) {
conn->receiver_bucket -= num_read; TO_OR_CONN(conn)->receiver_bucket -= num_read;
} }
} }
@ -1069,7 +1141,7 @@ connection_consider_empty_buckets(connection_t *conn)
} }
if (connection_speaks_cells(conn) && if (connection_speaks_cells(conn) &&
conn->state == OR_CONN_STATE_OPEN && conn->state == OR_CONN_STATE_OPEN &&
conn->receiver_bucket <= 0) { TO_OR_CONN(conn)->receiver_bucket <= 0) {
LOG_FN_CONN(conn, LOG_FN_CONN(conn,
(LOG_DEBUG,LD_NET,"receiver bucket exhausted. Pausing.")); (LOG_DEBUG,LD_NET,"receiver bucket exhausted. Pausing."));
conn->wants_to_read = 1; conn->wants_to_read = 1;
@ -1114,12 +1186,15 @@ connection_bucket_refill(struct timeval *now)
for (i=0;i<n;i++) { for (i=0;i<n;i++) {
conn = carray[i]; conn = carray[i];
if (connection_receiver_bucket_should_increase(conn)) { if (connection_speaks_cells(conn)) {
conn->receiver_bucket += conn->bandwidthrate; or_connection_t *or_conn = TO_OR_CONN(conn);
if (conn->receiver_bucket > conn->bandwidthburst) if (connection_receiver_bucket_should_increase(or_conn)) {
conn->receiver_bucket = conn->bandwidthburst; or_conn->receiver_bucket += or_conn->bandwidthrate;
//log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, if (or_conn->receiver_bucket > or_conn->bandwidthburst)
// conn->receiver_bucket); or_conn->receiver_bucket = or_conn->bandwidthburst;
//log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i,
// conn->receiver_bucket);
}
} }
if (conn->wants_to_read == 1 /* it's marked to turn reading back on now */ if (conn->wants_to_read == 1 /* it's marked to turn reading back on now */
@ -1128,7 +1203,7 @@ connection_bucket_refill(struct timeval *now)
* not the best place to check this.) */ * not the best place to check this.) */
&& (!connection_speaks_cells(conn) || && (!connection_speaks_cells(conn) ||
conn->state != OR_CONN_STATE_OPEN || conn->state != OR_CONN_STATE_OPEN ||
conn->receiver_bucket > 0)) { TO_OR_CONN(conn)->receiver_bucket > 0)) {
/* and either a non-cell conn or a cell conn with non-empty bucket */ /* and either a non-cell conn or a cell conn with non-empty bucket */
LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,"waking up conn (fd %d)",conn->s)); LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,"waking up conn (fd %d)",conn->s));
conn->wants_to_read = 0; conn->wants_to_read = 0;
@ -1145,15 +1220,12 @@ connection_bucket_refill(struct timeval *now)
* should add another pile of tokens to it? * should add another pile of tokens to it?
*/ */
static int static int
connection_receiver_bucket_should_increase(connection_t *conn) connection_receiver_bucket_should_increase(or_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
if (!connection_speaks_cells(conn)) if (conn->_base.state != OR_CONN_STATE_OPEN)
return 0; /* edge connections don't use receiver_buckets */
if (conn->state != OR_CONN_STATE_OPEN)
return 0; /* only open connections play the rate limiting game */ return 0; /* only open connections play the rate limiting game */
if (conn->receiver_bucket >= conn->bandwidthburst) if (conn->receiver_bucket >= conn->bandwidthburst)
return 0; return 0;
@ -1200,15 +1272,15 @@ loop_again:
/* There's a read error; kill the connection.*/ /* There's a read error; kill the connection.*/
connection_close_immediate(conn); /* Don't flush; connection is dead. */ connection_close_immediate(conn); /* Don't flush; connection is dead. */
if (CONN_IS_EDGE(conn)) { if (CONN_IS_EDGE(conn)) {
connection_edge_end_errno(conn, conn->cpath_layer); edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
if (conn->socks_request) /* broken, so don't send a socks reply back */ connection_edge_end_errno(edge_conn, edge_conn->cpath_layer);
conn->socks_request->has_finished = 1; if (edge_conn->socks_request) /* broken, don't send a socks reply back */
edge_conn->socks_request->has_finished = 1;
} }
connection_mark_for_close(conn); connection_mark_for_close(conn);
return -1; return -1;
} }
if (CONN_IS_EDGE(conn) && if (CONN_IS_EDGE(conn) && try_to_read != max_to_read) {
try_to_read != max_to_read) {
/* instruct it not to try to package partial cells. */ /* instruct it not to try to package partial cells. */
if (connection_process_inbuf(conn, 0) < 0) { if (connection_process_inbuf(conn, 0) < 0) {
return -1; return -1;
@ -1265,29 +1337,32 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
if (connection_speaks_cells(conn) && if (connection_speaks_cells(conn) &&
conn->state > OR_CONN_STATE_PROXY_READING) { conn->state > OR_CONN_STATE_PROXY_READING) {
int pending; int pending;
or_connection_t *or_conn = TO_OR_CONN(conn);
if (conn->state == OR_CONN_STATE_HANDSHAKING) { if (conn->state == OR_CONN_STATE_HANDSHAKING) {
/* continue handshaking even if global token bucket is empty */ /* continue handshaking even if global token bucket is empty */
return connection_tls_continue_handshake(conn); return connection_tls_continue_handshake(or_conn);
} }
log_debug(LD_NET, log_debug(LD_NET,
"%d: starting, inbuf_datalen %d (%d pending in tls object)." "%d: starting, inbuf_datalen %d (%d pending in tls object)."
" at_most %d.", " at_most %d.",
conn->s,(int)buf_datalen(conn->inbuf), conn->s,(int)buf_datalen(conn->inbuf),
tor_tls_get_pending_bytes(conn->tls), at_most); tor_tls_get_pending_bytes(or_conn->tls), at_most);
/* else open, or closing */ /* else open, or closing */
result = read_to_buf_tls(conn->tls, at_most, conn->inbuf); result = read_to_buf_tls(or_conn->tls, at_most, conn->inbuf);
switch (result) { switch (result) {
case TOR_TLS_CLOSE: case TOR_TLS_CLOSE:
log_info(LD_NET,"TLS connection closed on read. Closing. " log_info(LD_NET,"TLS connection closed on read. Closing. "
"(Nickname %s, address %s", "(Nickname %s, address %s",
conn->nickname ? conn->nickname : "not set", conn->address); or_conn->nickname ? or_conn->nickname : "not set",
conn->address);
return -1; return -1;
case TOR_TLS_ERROR: case TOR_TLS_ERROR:
log_info(LD_NET,"tls error. breaking (nickname %s, address %s).", log_info(LD_NET,"tls error. breaking (nickname %s, address %s).",
conn->nickname ? conn->nickname : "not set", conn->address); or_conn->nickname ? or_conn->nickname : "not set",
conn->address);
return -1; return -1;
case TOR_TLS_WANTWRITE: case TOR_TLS_WANTWRITE:
connection_start_writing(conn); connection_start_writing(conn);
@ -1299,12 +1374,12 @@ connection_read_to_buf(connection_t *conn, int *max_to_read)
default: default:
break; break;
} }
pending = tor_tls_get_pending_bytes(conn->tls); pending = tor_tls_get_pending_bytes(or_conn->tls);
if (pending) { if (pending) {
/* XXXX If we have any pending bytes, read them now. This *can* /* XXXX If we have any pending bytes, read them now. This *can*
* take us over our read allotment, but really we shouldn't be * take us over our read allotment, but really we shouldn't be
* believing that SSL bytes are the same as TCP bytes anyway. */ * believing that SSL bytes are the same as TCP bytes anyway. */
int r2 = read_to_buf_tls(conn->tls, pending, conn->inbuf); int r2 = read_to_buf_tls(or_conn->tls, pending, conn->inbuf);
if (r2<0) { if (r2<0) {
log_warn(LD_BUG, "Bug: apparently, reading pending bytes can fail."); log_warn(LD_BUG, "Bug: apparently, reading pending bytes can fail.");
return -1; return -1;
@ -1409,7 +1484,8 @@ connection_handle_write(connection_t *conn)
log_warn(LD_BUG, log_warn(LD_BUG,
"getsockopt() syscall failed?! Please report to tor-ops."); "getsockopt() syscall failed?! Please report to tor-ops.");
if (CONN_IS_EDGE(conn)) if (CONN_IS_EDGE(conn))
connection_edge_end_errno(conn, conn->cpath_layer); connection_edge_end_errno(TO_EDGE_CONN(conn),
TO_EDGE_CONN(conn)->cpath_layer);
connection_mark_for_close(conn); connection_mark_for_close(conn);
return -1; return -1;
} }
@ -1418,7 +1494,8 @@ connection_handle_write(connection_t *conn)
if (!ERRNO_IS_CONN_EINPROGRESS(e)) { if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
log_info(LD_NET,"in-progress connect failed. Removing."); log_info(LD_NET,"in-progress connect failed. Removing.");
if (CONN_IS_EDGE(conn)) if (CONN_IS_EDGE(conn))
connection_edge_end_errno(conn, conn->cpath_layer); connection_edge_end_errno(TO_EDGE_CONN(conn),
TO_EDGE_CONN(conn)->cpath_layer);
connection_close_immediate(conn); connection_close_immediate(conn);
connection_mark_for_close(conn); connection_mark_for_close(conn);
@ -1426,7 +1503,7 @@ connection_handle_write(connection_t *conn)
* ignores unrecognized routers * ignores unrecognized routers
*/ */
if (conn->type == CONN_TYPE_OR && !get_options()->HttpsProxy) if (conn->type == CONN_TYPE_OR && !get_options()->HttpsProxy)
router_set_status(conn->identity_digest, 0); router_set_status(TO_OR_CONN(conn)->identity_digest, 0);
return -1; return -1;
} else { } else {
return 0; /* no change, see if next time is better */ return 0; /* no change, see if next time is better */
@ -1441,9 +1518,10 @@ connection_handle_write(connection_t *conn)
if (connection_speaks_cells(conn) && if (connection_speaks_cells(conn) &&
conn->state > OR_CONN_STATE_PROXY_READING) { conn->state > OR_CONN_STATE_PROXY_READING) {
or_connection_t *or_conn = TO_OR_CONN(conn);
if (conn->state == OR_CONN_STATE_HANDSHAKING) { if (conn->state == OR_CONN_STATE_HANDSHAKING) {
connection_stop_writing(conn); connection_stop_writing(conn);
if (connection_tls_continue_handshake(conn) < 0) { if (connection_tls_continue_handshake(or_conn) < 0) {
/* Don't flush; connection is dead. */ /* Don't flush; connection is dead. */
connection_close_immediate(conn); connection_close_immediate(conn);
connection_mark_for_close(conn); connection_mark_for_close(conn);
@ -1453,7 +1531,7 @@ connection_handle_write(connection_t *conn)
} }
/* else open, or closing */ /* else open, or closing */
result = flush_buf_tls(conn->tls, conn->outbuf, result = flush_buf_tls(or_conn->tls, conn->outbuf,
max_to_write, &conn->outbuf_flushlen); max_to_write, &conn->outbuf_flushlen);
switch (result) { switch (result) {
case TOR_TLS_ERROR: case TOR_TLS_ERROR:
@ -1491,7 +1569,8 @@ connection_handle_write(connection_t *conn)
max_to_write, &conn->outbuf_flushlen)); max_to_write, &conn->outbuf_flushlen));
if (result < 0) { if (result < 0) {
if (CONN_IS_EDGE(conn)) if (CONN_IS_EDGE(conn))
connection_edge_end_errno(conn, conn->cpath_layer); connection_edge_end_errno(TO_EDGE_CONN(conn),
TO_EDGE_CONN(conn)->cpath_layer);
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);
@ -1521,16 +1600,17 @@ connection_handle_write(connection_t *conn)
/* A controller event has just happened with such urgency that we /* A controller event has just happened with such urgency that we
* need to write it onto controller <b>conn</b> immediately. */ * need to write it onto controller <b>conn</b> immediately. */
void void
_connection_controller_force_write(connection_t *conn) _connection_controller_force_write(control_connection_t *control_conn)
{ {
/* XXX This is hideous code duplication, but raising it seems a little /* XXX This is hideous code duplication, but raising it seems a little
* tricky for now. Think more about this one. We only call it for * tricky for now. Think more about this one. We only call it for
* EVENT_ERR_MSG, so messing with buckets a little isn't such a big problem. * EVENT_ERR_MSG, so messing with buckets a little isn't such a big problem.
*/ */
int result; int result;
tor_assert(conn); connection_t *conn;
tor_assert(!conn->tls); tor_assert(control_conn);
tor_assert(conn->type == CONN_TYPE_CONTROL); conn = TO_CONN(control_conn);
if (conn->marked_for_close || conn->s < 0) if (conn->marked_for_close || conn->s < 0)
return; return;
@ -1580,7 +1660,7 @@ connection_write_to_buf(const char *string, size_t len, connection_t *conn)
wrong compared to our max outbuf size. close the whole circuit. */ wrong compared to our max outbuf size. close the whole circuit. */
log_warn(LD_NET, log_warn(LD_NET,
"write_to_buf failed. Closing circuit (fd %d).", conn->s); "write_to_buf failed. Closing circuit (fd %d).", conn->s);
circuit_mark_for_close(circuit_get_by_edge_conn(conn), circuit_mark_for_close(circuit_get_by_edge_conn(TO_EDGE_CONN(conn)),
END_CIRC_REASON_INTERNAL); END_CIRC_REASON_INTERNAL);
} else { } else {
log_warn(LD_NET, log_warn(LD_NET,
@ -1595,15 +1675,17 @@ connection_write_to_buf(const char *string, size_t len, connection_t *conn)
} }
void void
connection_write_to_buf_zlib(connection_t *conn, connection_write_to_buf_zlib(dir_connection_t *dir_conn,
tor_zlib_state_t *state, tor_zlib_state_t *state,
const char *data, size_t data_len, const char *data, size_t data_len,
int done) int done)
{ {
int r; int r;
size_t old_datalen; size_t old_datalen;
connection_t *conn;
if (!data_len) if (!data_len)
return; return;
conn = TO_CONN(dir_conn);
/* if it's marked for close, only allow write if we mean to flush it */ /* if it's marked for close, only allow write if we mean to flush it */
if (conn->marked_for_close && !conn->hold_open_until_flushed) if (conn->marked_for_close && !conn->hold_open_until_flushed)
return; return;
@ -1614,18 +1696,9 @@ connection_write_to_buf_zlib(connection_t *conn,
conn->outbuf, state, data, data_len, conn->outbuf, state, data, data_len,
done)); done));
if (r < 0) { if (r < 0) {
if (CONN_IS_EDGE(conn)) { log_warn(LD_NET,
/* if it failed, it means we have our package/delivery windows set "write_to_buf failed. Closing connection (fd %d).", conn->s);
wrong compared to our max outbuf size. close the whole circuit. */ connection_mark_for_close(conn);
log_warn(LD_NET,
"write_to_buf failed. Closing circuit (fd %d).", conn->s);
circuit_mark_for_close(circuit_get_by_edge_conn(conn),
END_CIRC_REASON_INTERNAL);
} else {
log_warn(LD_NET,
"write_to_buf failed. Closing connection (fd %d).", conn->s);
connection_mark_for_close(conn);
}
return; return;
} }
@ -1635,11 +1708,12 @@ connection_write_to_buf_zlib(connection_t *conn,
/** Return the conn to addr/port that has the most recent /** Return the conn to addr/port that has the most recent
* timestamp_created, or NULL if no such conn exists. */ * timestamp_created, or NULL if no such conn exists. */
connection_t * or_connection_t *
connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port) connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port)
{ {
int i, n; int i, n;
connection_t *conn, *best=NULL; connection_t *conn;
or_connection_t *best=NULL;
connection_t **carray; connection_t **carray;
get_connection_array(&carray,&n); get_connection_array(&carray,&n);
@ -1649,8 +1723,8 @@ connection_or_exact_get_by_addr_port(uint32_t addr, uint16_t port)
conn->addr == addr && conn->addr == addr &&
conn->port == port && conn->port == port &&
!conn->marked_for_close && !conn->marked_for_close &&
(!best || best->timestamp_created < conn->timestamp_created)) (!best || best->_base.timestamp_created < conn->timestamp_created))
best = conn; best = TO_OR_CONN(conn);
} }
return best; return best;
} }
@ -1772,14 +1846,22 @@ connection_get_by_type_state_rendquery(int type, int state,
connection_t *conn; connection_t *conn;
connection_t **carray; connection_t **carray;
tor_assert(type == CONN_TYPE_DIR ||
type == CONN_TYPE_AP || type == CONN_TYPE_EXIT);
get_connection_array(&carray,&n); get_connection_array(&carray,&n);
for (i=0;i<n;i++) { for (i=0;i<n;i++) {
conn = carray[i]; conn = carray[i];
if (conn->type == type && if (conn->type == type &&
!conn->marked_for_close && !conn->marked_for_close &&
(!state || state == conn->state) && (!state || state == conn->state)) {
!rend_cmp_service_ids(rendquery, conn->rend_query)) if (type == CONN_TYPE_DIR &&
return conn; rend_cmp_service_ids(rendquery, TO_DIR_CONN(conn)->rend_query))
return conn;
else if (CONN_IS_EDGE(conn) &&
rend_cmp_service_ids(rendquery, TO_EDGE_CONN(conn)->rend_query))
return conn;
}
} }
return NULL; return NULL;
} }
@ -1949,18 +2031,18 @@ connection_process_inbuf(connection_t *conn, int package_partial)
switch (conn->type) { switch (conn->type) {
case CONN_TYPE_OR: case CONN_TYPE_OR:
return connection_or_process_inbuf(conn); return connection_or_process_inbuf(TO_OR_CONN(conn));
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
case CONN_TYPE_AP: case CONN_TYPE_AP:
return connection_edge_process_inbuf(conn, package_partial); return connection_edge_process_inbuf(TO_EDGE_CONN(conn), package_partial);
case CONN_TYPE_DIR: case CONN_TYPE_DIR:
return connection_dir_process_inbuf(conn); return connection_dir_process_inbuf(TO_DIR_CONN(conn));
case CONN_TYPE_DNSWORKER: case CONN_TYPE_DNSWORKER:
return connection_dns_process_inbuf(conn); return connection_dns_process_inbuf(conn);
case CONN_TYPE_CPUWORKER: case CONN_TYPE_CPUWORKER:
return connection_cpu_process_inbuf(conn); return connection_cpu_process_inbuf(conn);
case CONN_TYPE_CONTROL: case CONN_TYPE_CONTROL:
return connection_control_process_inbuf(conn); return connection_control_process_inbuf(TO_CONTROL_CONN(conn));
default: default:
log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type); log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type);
tor_fragile_assert(); tor_fragile_assert();
@ -1974,7 +2056,7 @@ connection_flushed_some(connection_t *conn)
{ {
if (conn->type == CONN_TYPE_DIR && if (conn->type == CONN_TYPE_DIR &&
conn->state == DIR_CONN_STATE_SERVER_WRITING) conn->state == DIR_CONN_STATE_SERVER_WRITING)
return connection_dirserv_flushed_some(conn); return connection_dirserv_flushed_some(TO_DIR_CONN(conn));
else else
return 0; return 0;
} }
@ -1994,18 +2076,18 @@ connection_finished_flushing(connection_t *conn)
switch (conn->type) { switch (conn->type) {
case CONN_TYPE_OR: case CONN_TYPE_OR:
return connection_or_finished_flushing(conn); return connection_or_finished_flushing(TO_OR_CONN(conn));
case CONN_TYPE_AP: case CONN_TYPE_AP:
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
return connection_edge_finished_flushing(conn); return connection_edge_finished_flushing(TO_EDGE_CONN(conn));
case CONN_TYPE_DIR: case CONN_TYPE_DIR:
return connection_dir_finished_flushing(conn); return connection_dir_finished_flushing(TO_DIR_CONN(conn));
case CONN_TYPE_DNSWORKER: case CONN_TYPE_DNSWORKER:
return connection_dns_finished_flushing(conn); return connection_dns_finished_flushing(conn);
case CONN_TYPE_CPUWORKER: case CONN_TYPE_CPUWORKER:
return connection_cpu_finished_flushing(conn); return connection_cpu_finished_flushing(conn);
case CONN_TYPE_CONTROL: case CONN_TYPE_CONTROL:
return connection_control_finished_flushing(conn); return connection_control_finished_flushing(TO_CONTROL_CONN(conn));
default: default:
log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type); log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type);
tor_fragile_assert(); tor_fragile_assert();
@ -2026,11 +2108,11 @@ connection_finished_connecting(connection_t *conn)
switch (conn->type) switch (conn->type)
{ {
case CONN_TYPE_OR: case CONN_TYPE_OR:
return connection_or_finished_connecting(conn); return connection_or_finished_connecting(TO_OR_CONN(conn));
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
return connection_edge_finished_connecting(conn); return connection_edge_finished_connecting(TO_EDGE_CONN(conn));
case CONN_TYPE_DIR: case CONN_TYPE_DIR:
return connection_dir_finished_connecting(conn); return connection_dir_finished_connecting(TO_DIR_CONN(conn));
default: default:
log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type); log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type);
tor_fragile_assert(); tor_fragile_assert();
@ -2044,18 +2126,18 @@ connection_reached_eof(connection_t *conn)
{ {
switch (conn->type) { switch (conn->type) {
case CONN_TYPE_OR: case CONN_TYPE_OR:
return connection_or_reached_eof(conn); return connection_or_reached_eof(TO_OR_CONN(conn));
case CONN_TYPE_AP: case CONN_TYPE_AP:
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
return connection_edge_reached_eof(conn); return connection_edge_reached_eof(TO_EDGE_CONN(conn));
case CONN_TYPE_DIR: case CONN_TYPE_DIR:
return connection_dir_reached_eof(conn); return connection_dir_reached_eof(TO_DIR_CONN(conn));
case CONN_TYPE_DNSWORKER: case CONN_TYPE_DNSWORKER:
return connection_dns_reached_eof(conn); return connection_dns_reached_eof(conn);
case CONN_TYPE_CPUWORKER: case CONN_TYPE_CPUWORKER:
return connection_cpu_reached_eof(conn); return connection_cpu_reached_eof(conn);
case CONN_TYPE_CONTROL: case CONN_TYPE_CONTROL:
return connection_control_reached_eof(conn); return connection_control_reached_eof(TO_CONTROL_CONN(conn));
default: default:
log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type); log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type);
tor_fragile_assert(); tor_fragile_assert();
@ -2071,9 +2153,26 @@ assert_connection_ok(connection_t *conn, time_t now)
{ {
(void) now; /* XXXX unused. */ (void) now; /* XXXX unused. */
tor_assert(conn); tor_assert(conn);
tor_assert(conn->magic == CONNECTION_MAGIC);
tor_assert(conn->type >= _CONN_TYPE_MIN); tor_assert(conn->type >= _CONN_TYPE_MIN);
tor_assert(conn->type <= _CONN_TYPE_MAX); tor_assert(conn->type <= _CONN_TYPE_MAX);
switch (conn->type) {
case CONN_TYPE_OR:
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
break;
case CONN_TYPE_AP:
case CONN_TYPE_EXIT:
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
break;
case CONN_TYPE_DIR:
tor_assert(conn->magic == DIR_CONNECTION_MAGIC);
break;
case CONN_TYPE_CONTROL:
tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC);
break;
default:
tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
break;
}
if (conn->outbuf_flushlen > 0) { if (conn->outbuf_flushlen > 0) {
tor_assert(connection_is_writing(conn) || conn->wants_to_write); tor_assert(connection_is_writing(conn) || conn->wants_to_write);
@ -2100,9 +2199,8 @@ assert_connection_ok(connection_t *conn, time_t now)
*/ */
#endif #endif
if (conn->type != CONN_TYPE_OR) { if (conn->type == CONN_TYPE_OR) {
tor_assert(!conn->tls); or_connection_t *or_conn = TO_OR_CONN(conn);
} else {
if (conn->state == OR_CONN_STATE_OPEN) { if (conn->state == OR_CONN_STATE_OPEN) {
/* tor_assert(conn->bandwidth > 0); */ /* tor_assert(conn->bandwidth > 0); */
/* the above isn't necessarily true: if we just did a TLS /* the above isn't necessarily true: if we just did a TLS
@ -2115,42 +2213,30 @@ assert_connection_ok(connection_t *conn, time_t now)
// tor_assert(conn->addr && conn->port); // tor_assert(conn->addr && conn->port);
tor_assert(conn->address); tor_assert(conn->address);
if (conn->state > OR_CONN_STATE_PROXY_READING) if (conn->state > OR_CONN_STATE_PROXY_READING)
tor_assert(conn->tls); tor_assert(or_conn->tls);
} }
if (! CONN_IS_EDGE(conn)) { if (CONN_IS_EDGE(conn)) {
tor_assert(!conn->stream_id); edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
tor_assert(!conn->next_stream);
tor_assert(!conn->cpath_layer);
tor_assert(!conn->package_window);
tor_assert(!conn->deliver_window);
#if 0
tor_assert(!conn->done_sending);
tor_assert(!conn->done_receiving);
#endif
} else {
/* XXX unchecked: package window, deliver window. */ /* XXX unchecked: package window, deliver window. */
} if (conn->type == CONN_TYPE_AP) {
if (conn->type == CONN_TYPE_AP) {
tor_assert(conn->socks_request); tor_assert(edge_conn->socks_request);
if (conn->state == AP_CONN_STATE_OPEN) { if (conn->state == AP_CONN_STATE_OPEN) {
tor_assert(conn->socks_request->has_finished); tor_assert(edge_conn->socks_request->has_finished);
if (!conn->marked_for_close) { if (!conn->marked_for_close) {
tor_assert(conn->cpath_layer); tor_assert(edge_conn->cpath_layer);
assert_cpath_layer_ok(conn->cpath_layer); assert_cpath_layer_ok(edge_conn->cpath_layer);
}
} }
} }
} else { if (conn->type == CONN_TYPE_EXIT) {
tor_assert(!conn->socks_request); tor_assert(conn->purpose == EXIT_PURPOSE_CONNECT ||
} conn->purpose == EXIT_PURPOSE_RESOLVE);
if (conn->type == CONN_TYPE_EXIT) { }
tor_assert(conn->purpose == EXIT_PURPOSE_CONNECT ||
conn->purpose == EXIT_PURPOSE_RESOLVE);
} else if (conn->type != CONN_TYPE_DIR) {
tor_assert(!conn->purpose); /* only used for dir types currently */
} }
if (conn->type != CONN_TYPE_DIR) { if (conn->type != CONN_TYPE_DIR) {
tor_assert(!conn->requested_resource); tor_assert(!conn->purpose); /* only used for dir types currently */
} }
switch (conn->type) switch (conn->type)
@ -2164,7 +2250,7 @@ assert_connection_ok(connection_t *conn, time_t now)
case CONN_TYPE_OR: case CONN_TYPE_OR:
tor_assert(conn->state >= _OR_CONN_STATE_MIN); tor_assert(conn->state >= _OR_CONN_STATE_MIN);
tor_assert(conn->state <= _OR_CONN_STATE_MAX); tor_assert(conn->state <= _OR_CONN_STATE_MAX);
tor_assert(conn->n_circuits >= 0); tor_assert(TO_OR_CONN(conn)->n_circuits >= 0);
break; break;
case CONN_TYPE_EXIT: case CONN_TYPE_EXIT:
tor_assert(conn->state >= _EXIT_CONN_STATE_MIN); tor_assert(conn->state >= _EXIT_CONN_STATE_MIN);
@ -2175,7 +2261,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(conn->socks_request); tor_assert(TO_EDGE_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

@ -16,22 +16,22 @@ const char connection_edge_c_id[] =
/* List of exit_redirect_t */ /* List of exit_redirect_t */
static smartlist_t *redirect_exit_list = NULL; static smartlist_t *redirect_exit_list = NULL;
static int connection_ap_handshake_process_socks(connection_t *conn); static int connection_ap_handshake_process_socks(edge_connection_t *conn);
/** An AP stream has failed/finished. If it hasn't already sent back /** An AP stream has failed/finished. If it hasn't already sent back
* a socks reply, send one now (based on endreason). Also set * a socks reply, send one now (based on endreason). Also set
* has_sent_end to 1, and mark the conn. * has_sent_end to 1, and mark the conn.
*/ */
void void
_connection_mark_unattached_ap(connection_t *conn, int endreason, _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
int line, const char *file) int line, const char *file)
{ {
tor_assert(conn->type == CONN_TYPE_AP); tor_assert(conn->_base.type == CONN_TYPE_AP);
conn->has_sent_end = 1; /* no circ yet */ conn->_base.edge_has_sent_end = 1; /* no circ yet */
if (conn->marked_for_close) { if (conn->_base.marked_for_close) {
/* This call will warn as appropriate. */ /* This call will warn as appropriate. */
_connection_mark_for_close(conn, line, file); _connection_mark_for_close(TO_CONN(conn), line, file);
return; return;
} }
@ -51,27 +51,28 @@ _connection_mark_unattached_ap(connection_t *conn, int endreason,
0, NULL, -1); 0, NULL, -1);
} }
_connection_mark_for_close(conn, line, file); _connection_mark_for_close(TO_CONN(conn), line, file);
conn->hold_open_until_flushed = 1; conn->_base.hold_open_until_flushed = 1;
} }
/** There was an EOF. Send an end and mark the connection for close. /** There was an EOF. Send an end and mark the connection for close.
*/ */
int int
connection_edge_reached_eof(connection_t *conn) connection_edge_reached_eof(edge_connection_t *conn)
{ {
if (buf_datalen(conn->inbuf) && connection_state_is_open(conn)) { if (buf_datalen(conn->_base.inbuf) &&
connection_state_is_open(TO_CONN(conn))) {
/* it still has stuff to process. don't let it die yet. */ /* it still has stuff to process. don't let it die yet. */
return 0; return 0;
} }
log_info(LD_EDGE,"conn (fd %d) reached eof. Closing.", conn->s); log_info(LD_EDGE,"conn (fd %d) reached eof. Closing.", conn->_base.s);
if (!conn->marked_for_close) { if (!conn->_base.marked_for_close) {
/* only mark it if not already marked. it's possible to /* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */ * get the 'end' right around when the client hangs up on us. */
connection_edge_end(conn, END_STREAM_REASON_DONE, conn->cpath_layer); connection_edge_end(conn, END_STREAM_REASON_DONE, conn->cpath_layer);
if (conn->socks_request) /* eof, so don't send a socks reply back */ if (conn->socks_request) /* eof, so don't send a socks reply back */
conn->socks_request->has_finished = 1; conn->socks_request->has_finished = 1;
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
} }
return 0; return 0;
} }
@ -86,12 +87,11 @@ connection_edge_reached_eof(connection_t *conn)
* else return 0. * else return 0.
*/ */
int int
connection_edge_process_inbuf(connection_t *conn, int package_partial) connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(CONN_IS_EDGE(conn));
switch (conn->state) { switch (conn->_base.state) {
case AP_CONN_STATE_SOCKS_WAIT: case AP_CONN_STATE_SOCKS_WAIT:
if (connection_ap_handshake_process_socks(conn) < 0) { if (connection_ap_handshake_process_socks(conn) < 0) {
/* already marked */ /* already marked */
@ -102,7 +102,7 @@ connection_edge_process_inbuf(connection_t *conn, int package_partial)
case EXIT_CONN_STATE_OPEN: case EXIT_CONN_STATE_OPEN:
if (connection_edge_package_raw_inbuf(conn, package_partial) < 0) { if (connection_edge_package_raw_inbuf(conn, package_partial) < 0) {
/* (We already sent an end cell if possible) */ /* (We already sent an end cell if possible) */
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return -1; return -1;
} }
return 0; return 0;
@ -114,13 +114,13 @@ connection_edge_process_inbuf(connection_t *conn, int package_partial)
case AP_CONN_STATE_CONTROLLER_WAIT: case AP_CONN_STATE_CONTROLLER_WAIT:
log_info(LD_EDGE, log_info(LD_EDGE,
"data from edge while in '%s' state. Leaving it on buffer.", "data from edge while in '%s' state. Leaving it on buffer.",
conn_state_to_string(conn->type, conn->state)); conn_state_to_string(conn->_base.type, conn->_base.state));
return 0; return 0;
} }
log_warn(LD_BUG,"Bug: Got unexpected state %d. Closing.",conn->state); log_warn(LD_BUG,"Bug: Got unexpected state %d. Closing.",conn->_base.state);
tor_fragile_assert(); tor_fragile_assert();
connection_edge_end(conn, END_STREAM_REASON_INTERNAL, conn->cpath_layer); connection_edge_end(conn, END_STREAM_REASON_INTERNAL, conn->cpath_layer);
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return -1; return -1;
} }
@ -128,19 +128,17 @@ connection_edge_process_inbuf(connection_t *conn, int package_partial)
* Mark it for close and return 0. * Mark it for close and return 0.
*/ */
int int
connection_edge_destroy(uint16_t circ_id, connection_t *conn) connection_edge_destroy(uint16_t circ_id, edge_connection_t *conn)
{ {
tor_assert(CONN_IS_EDGE(conn)); if (!conn->_base.marked_for_close) {
if (!conn->marked_for_close) {
log_info(LD_EDGE, log_info(LD_EDGE,
"CircID %d: At an edge. Marking connection for close.", circ_id); "CircID %d: At an edge. Marking connection for close.", circ_id);
if (conn->type == CONN_TYPE_AP) { if (conn->_base.type == CONN_TYPE_AP) {
connection_mark_unattached_ap(conn, END_STREAM_REASON_DESTROY); connection_mark_unattached_ap(conn, END_STREAM_REASON_DESTROY);
} else { } else {
conn->has_sent_end = 1; /* closing the circuit, nothing to send to */ conn->_base.edge_has_sent_end = 1; /* closing the circuit, nothing to send to */
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
conn->hold_open_until_flushed = 1; conn->_base.hold_open_until_flushed = 1;
} }
} }
conn->cpath_layer = NULL; conn->cpath_layer = NULL;
@ -157,44 +155,46 @@ connection_edge_destroy(uint16_t circ_id, connection_t *conn)
* else return 0. * else return 0.
*/ */
int int
connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_layer) connection_edge_end(edge_connection_t *conn, char reason,
crypt_path_t *cpath_layer)
{ {
char payload[RELAY_PAYLOAD_SIZE]; char payload[RELAY_PAYLOAD_SIZE];
size_t payload_len=1; size_t payload_len=1;
circuit_t *circ; circuit_t *circ;
if (conn->has_sent_end) { if (conn->_base.edge_has_sent_end) {
log_warn(LD_BUG,"Harmless bug: Calling connection_edge_end (reason %d) " log_warn(LD_BUG,"Harmless bug: Calling connection_edge_end (reason %d) "
"on an already ended stream?", reason); "on an already ended stream?", reason);
tor_fragile_assert(); tor_fragile_assert();
return -1; return -1;
} }
if (conn->marked_for_close) { if (conn->_base.marked_for_close) {
log_warn(LD_BUG, log_warn(LD_BUG,
"Bug: called on conn that's already marked for close at %s:%d.", "Bug: called on conn that's already marked for close at %s:%d.",
conn->marked_for_close_file, conn->marked_for_close); conn->_base.marked_for_close_file, conn->_base.marked_for_close);
return 0; return 0;
} }
payload[0] = reason; payload[0] = reason;
if (reason == END_STREAM_REASON_EXITPOLICY && if (reason == END_STREAM_REASON_EXITPOLICY &&
!connection_edge_is_rendezvous_stream(conn)) { !connection_edge_is_rendezvous_stream(conn)) {
set_uint32(payload+1, htonl(conn->addr)); set_uint32(payload+1, htonl(conn->_base.addr));
set_uint32(payload+5, htonl(dns_clip_ttl(conn->address_ttl))); set_uint32(payload+5, htonl(dns_clip_ttl(conn->address_ttl)));
payload_len += 8; payload_len += 8;
} }
circ = circuit_get_by_edge_conn(conn); circ = circuit_get_by_edge_conn(conn);
if (circ && !circ->marked_for_close) { if (circ && !circ->marked_for_close) {
log_debug(LD_EDGE,"Marking conn (fd %d) and sending end.",conn->s); log_debug(LD_EDGE,"Marking conn (fd %d) and sending end.",conn->_base.s);
connection_edge_send_command(conn, circ, RELAY_COMMAND_END, connection_edge_send_command(conn, circ, RELAY_COMMAND_END,
payload, payload_len, cpath_layer); payload, payload_len, cpath_layer);
} else { } else {
log_debug(LD_EDGE,"Marking conn (fd %d); no circ to send end.",conn->s); log_debug(LD_EDGE,"Marking conn (fd %d); no circ to send end.",
conn->_base.s);
} }
conn->has_sent_end = 1; conn->_base.edge_has_sent_end = 1;
return 0; return 0;
} }
@ -203,11 +203,11 @@ connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_layer)
* an appropriate relay end cell to <b>cpath_layer</b>. * an appropriate relay end cell to <b>cpath_layer</b>.
**/ **/
int int
connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer) connection_edge_end_errno(edge_connection_t *conn, crypt_path_t *cpath_layer)
{ {
uint8_t reason; uint8_t reason;
tor_assert(conn); tor_assert(conn);
reason = (uint8_t)errno_to_end_reason(tor_socket_errno(conn->s)); reason = (uint8_t)errno_to_end_reason(tor_socket_errno(conn->_base.s));
return connection_edge_end(conn, reason, cpath_layer); return connection_edge_end(conn, reason, cpath_layer);
} }
@ -222,15 +222,14 @@ connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer)
* return 0. * return 0.
*/ */
int int
connection_edge_finished_flushing(connection_t *conn) connection_edge_finished_flushing(edge_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(CONN_IS_EDGE(conn));
switch (conn->state) { switch (conn->_base.state) {
case AP_CONN_STATE_OPEN: case AP_CONN_STATE_OPEN:
case EXIT_CONN_STATE_OPEN: case EXIT_CONN_STATE_OPEN:
connection_stop_writing(conn); connection_stop_writing(TO_CONN(conn));
connection_edge_consider_sending_sendme(conn); connection_edge_consider_sending_sendme(conn);
return 0; return 0;
case AP_CONN_STATE_SOCKS_WAIT: case AP_CONN_STATE_SOCKS_WAIT:
@ -238,10 +237,10 @@ connection_edge_finished_flushing(connection_t *conn)
case AP_CONN_STATE_CIRCUIT_WAIT: case AP_CONN_STATE_CIRCUIT_WAIT:
case AP_CONN_STATE_CONNECT_WAIT: case AP_CONN_STATE_CONNECT_WAIT:
case AP_CONN_STATE_CONTROLLER_WAIT: case AP_CONN_STATE_CONTROLLER_WAIT:
connection_stop_writing(conn); connection_stop_writing(TO_CONN(conn));
return 0; return 0;
default: default:
log_warn(LD_BUG,"BUG: called in unexpected state %d.", conn->state); log_warn(LD_BUG,"BUG: called in unexpected state %d.", conn->_base.state);
tor_fragile_assert(); tor_fragile_assert();
return -1; return -1;
} }
@ -252,13 +251,15 @@ connection_edge_finished_flushing(connection_t *conn)
* data, deliver 'CONNECTED' relay cells as appropriate, and check * data, deliver 'CONNECTED' relay cells as appropriate, and check
* any pending data that may have been received. */ * any pending data that may have been received. */
int int
connection_edge_finished_connecting(connection_t *conn) connection_edge_finished_connecting(edge_connection_t *edge_conn)
{ {
char valbuf[INET_NTOA_BUF_LEN]; char valbuf[INET_NTOA_BUF_LEN];
connection_t *conn;
struct in_addr in; struct in_addr in;
tor_assert(conn); tor_assert(edge_conn);
tor_assert(conn->type == CONN_TYPE_EXIT); tor_assert(edge_conn->_base.type == CONN_TYPE_EXIT);
conn = TO_CONN(edge_conn);
tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING); tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING);
in.s_addr = htonl(conn->addr); in.s_addr = htonl(conn->addr);
@ -272,23 +273,27 @@ connection_edge_finished_connecting(connection_t *conn)
* cells */ * cells */
connection_start_writing(conn); connection_start_writing(conn);
/* deliver a 'connected' relay cell back through the circuit. */ /* deliver a 'connected' relay cell back through the circuit. */
if (connection_edge_is_rendezvous_stream(conn)) { if (connection_edge_is_rendezvous_stream(edge_conn)) {
if (connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), if (connection_edge_send_command(edge_conn,
circuit_get_by_edge_conn(edge_conn),
RELAY_COMMAND_CONNECTED, NULL, 0, RELAY_COMMAND_CONNECTED, NULL, 0,
conn->cpath_layer) < 0) edge_conn->cpath_layer) < 0)
return 0; /* circuit is closed, don't continue */ return 0; /* circuit is closed, don't continue */
} else { } else {
char connected_payload[8]; char connected_payload[8];
set_uint32(connected_payload, htonl(conn->addr)); set_uint32(connected_payload, htonl(conn->addr));
set_uint32(connected_payload+4, set_uint32(connected_payload+4,
htonl(dns_clip_ttl(conn->address_ttl))); htonl(dns_clip_ttl(edge_conn->address_ttl)));
if (connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), if (connection_edge_send_command(edge_conn,
RELAY_COMMAND_CONNECTED, connected_payload, 8, conn->cpath_layer) < 0) circuit_get_by_edge_conn(edge_conn),
RELAY_COMMAND_CONNECTED,
connected_payload, 8,
edge_conn->cpath_layer) < 0)
return 0; /* circuit is closed, don't continue */ return 0; /* circuit is closed, don't continue */
} }
tor_assert(conn->package_window > 0); tor_assert(edge_conn->package_window > 0);
/* in case the server has written anything */ /* in case the server has written anything */
return connection_edge_process_inbuf(conn, 1); return connection_edge_process_inbuf(edge_conn, 1);
} }
/** Define a schedule for how long to wait between retrying /** Define a schedule for how long to wait between retrying
@ -297,7 +302,7 @@ connection_edge_finished_connecting(connection_t *conn)
* 10 seconds for the second, and 15 seconds for each retry after * 10 seconds for the second, and 15 seconds for each retry after
* that. Hopefully this will improve the expected experience. */ * that. Hopefully this will improve the expected experience. */
static int static int
compute_socks_timeout(connection_t *conn) compute_socks_timeout(edge_connection_t *conn)
{ {
if (conn->num_socks_retries == 0) if (conn->num_socks_retries == 0)
return 5; return 5;
@ -319,7 +324,7 @@ void
connection_ap_expire_beginning(void) connection_ap_expire_beginning(void)
{ {
connection_t **carray; connection_t **carray;
connection_t *conn; edge_connection_t *conn;
circuit_t *circ; circuit_t *circ;
const char *nickname; const char *nickname;
int n, i; int n, i;
@ -331,24 +336,24 @@ connection_ap_expire_beginning(void)
get_connection_array(&carray, &n); get_connection_array(&carray, &n);
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
conn = carray[i]; if (carray[i]->type != CONN_TYPE_AP)
if (conn->type != CONN_TYPE_AP)
continue; continue;
conn = TO_EDGE_CONN(carray[i]);
/* if it's an internal bridge connection, don't yell its status. */ /* if it's an internal bridge connection, don't yell its status. */
severity = (!conn->addr && !conn->port) ? LOG_INFO : LOG_NOTICE; severity = (!conn->_base.addr && !conn->_base.port) ? LOG_INFO : LOG_NOTICE;
if (conn->state == AP_CONN_STATE_CONTROLLER_WAIT) { if (conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT) {
if (now - conn->timestamp_lastread >= options->SocksTimeout) { if (now - conn->_base.timestamp_lastread >= options->SocksTimeout) {
log_fn(severity, LD_APP, "Closing unattached stream."); log_fn(severity, LD_APP, "Closing unattached stream.");
connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT); connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
} }
continue; continue;
} }
if (conn->state != AP_CONN_STATE_RESOLVE_WAIT && if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT &&
conn->state != AP_CONN_STATE_CONNECT_WAIT) conn->_base.state != AP_CONN_STATE_CONNECT_WAIT)
continue; continue;
cutoff = compute_socks_timeout(conn); cutoff = compute_socks_timeout(conn);
if (now - conn->timestamp_lastread < cutoff) if (now - conn->_base.timestamp_lastread < cutoff)
continue; continue;
circ = circuit_get_by_edge_conn(conn); circ = circuit_get_by_edge_conn(conn);
if (!circ) { /* it's vanished? */ if (!circ) { /* it's vanished? */
@ -358,11 +363,11 @@ connection_ap_expire_beginning(void)
continue; continue;
} }
if (circ->purpose == CIRCUIT_PURPOSE_C_REND_JOINED) { if (circ->purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
if (now - conn->timestamp_lastread > options->SocksTimeout) { if (now - conn->_base.timestamp_lastread > options->SocksTimeout) {
log_fn(severity, LD_REND, log_fn(severity, LD_REND,
"Rend stream is %d seconds late. Giving up on address" "Rend stream is %d seconds late. Giving up on address"
" '%s.onion'.", " '%s.onion'.",
(int)(now - conn->timestamp_lastread), (int)(now - conn->_base.timestamp_lastread),
safe_str(conn->socks_request->address)); safe_str(conn->socks_request->address));
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT, connection_edge_end(conn, END_STREAM_REASON_TIMEOUT,
conn->cpath_layer); conn->cpath_layer);
@ -376,20 +381,20 @@ connection_ap_expire_beginning(void)
log_fn(cutoff < 15 ? LOG_INFO : severity, LD_APP, log_fn(cutoff < 15 ? LOG_INFO : severity, LD_APP,
"We tried for %d seconds to connect to '%s' using exit '%s'." "We tried for %d seconds to connect to '%s' using exit '%s'."
" Retrying on a new circuit.", " Retrying on a new circuit.",
(int)(now - conn->timestamp_lastread), (int)(now - conn->_base.timestamp_lastread),
safe_str(conn->socks_request->address), safe_str(conn->socks_request->address),
nickname ? nickname : "*unnamed*"); nickname ? nickname : "*unnamed*");
/* send an end down the circuit */ /* send an end down the circuit */
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer); connection_edge_end(conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer);
/* un-mark it as ending, since we're going to reuse it */ /* un-mark it as ending, since we're going to reuse it */
conn->has_sent_end = 0; conn->_base.edge_has_sent_end = 0;
/* kludge to make us not try this circuit again, yet to allow /* kludge to make us not try this circuit again, yet to allow
* current streams on it to survive if they can: make it * current streams on it to survive if they can: make it
* unattractive to use for new streams */ * unattractive to use for new streams */
tor_assert(circ->timestamp_dirty); tor_assert(circ->timestamp_dirty);
circ->timestamp_dirty -= options->MaxCircuitDirtiness; circ->timestamp_dirty -= options->MaxCircuitDirtiness;
/* give our stream another 'cutoff' seconds to try */ /* give our stream another 'cutoff' seconds to try */
conn->timestamp_lastread += cutoff; conn->_base.timestamp_lastread += cutoff;
conn->num_socks_retries++; conn->num_socks_retries++;
/* move it back into 'pending' state, and try to attach. */ /* move it back into 'pending' state, and try to attach. */
if (connection_ap_detach_retriable(conn, TO_ORIGIN_CIRCUIT(circ))<0) { if (connection_ap_detach_retriable(conn, TO_ORIGIN_CIRCUIT(circ))<0) {
@ -406,6 +411,7 @@ connection_ap_attach_pending(void)
{ {
connection_t **carray; connection_t **carray;
connection_t *conn; connection_t *conn;
edge_connection_t *edge_conn;
int n, i; int n, i;
get_connection_array(&carray, &n); get_connection_array(&carray, &n);
@ -416,8 +422,9 @@ connection_ap_attach_pending(void)
conn->type != CONN_TYPE_AP || conn->type != CONN_TYPE_AP ||
conn->state != AP_CONN_STATE_CIRCUIT_WAIT) conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
continue; continue;
if (connection_ap_handshake_attach_circuit(conn) < 0) { edge_conn = TO_EDGE_CONN(conn);
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); if (connection_ap_handshake_attach_circuit(edge_conn) < 0) {
connection_mark_unattached_ap(edge_conn, END_STREAM_REASON_CANT_ATTACH);
} }
} }
} }
@ -430,16 +437,16 @@ connection_ap_attach_pending(void)
* Returns -1 on err, 1 on success, 0 on not-yet-sure. * Returns -1 on err, 1 on success, 0 on not-yet-sure.
*/ */
int int
connection_ap_detach_retriable(connection_t *conn, origin_circuit_t *circ) connection_ap_detach_retriable(edge_connection_t *conn, origin_circuit_t *circ)
{ {
control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE); control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE);
conn->timestamp_lastread = time(NULL); conn->_base.timestamp_lastread = time(NULL);
if (! get_options()->LeaveStreamsUnattached) { if (! get_options()->LeaveStreamsUnattached) {
conn->state = AP_CONN_STATE_CIRCUIT_WAIT; conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
circuit_detach_stream(TO_CIRCUIT(circ),conn); circuit_detach_stream(TO_CIRCUIT(circ),conn);
return connection_ap_handshake_attach_circuit(conn); return connection_ap_handshake_attach_circuit(conn);
} else { } else {
conn->state = AP_CONN_STATE_CONTROLLER_WAIT; conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
circuit_detach_stream(TO_CIRCUIT(circ),conn); circuit_detach_stream(TO_CIRCUIT(circ),conn);
return 0; return 0;
} }
@ -1011,7 +1018,7 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
* rendezvous descriptor is already here and fresh enough). * rendezvous descriptor is already here and fresh enough).
*/ */
int int
connection_ap_handshake_rewrite_and_attach(connection_t *conn, connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
origin_circuit_t *circ) origin_circuit_t *circ)
{ {
socks_request_t *socks = conn->socks_request; socks_request_t *socks = conn->socks_request;
@ -1137,7 +1144,7 @@ connection_ap_handshake_rewrite_and_attach(connection_t *conn,
/* help predict this next time */ /* help predict this next time */
rep_hist_note_used_port(socks->port, time(NULL)); rep_hist_note_used_port(socks->port, time(NULL));
} }
conn->state = AP_CONN_STATE_CIRCUIT_WAIT; conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
if ((circ && if ((circ &&
connection_ap_handshake_attach_chosen_circuit(conn, circ) < 0) || connection_ap_handshake_attach_chosen_circuit(conn, circ) < 0) ||
(!circ && (!circ &&
@ -1182,21 +1189,21 @@ connection_ap_handshake_rewrite_and_attach(connection_t *conn,
return -1; return -1;
} }
if (r==0) { if (r==0) {
conn->state = AP_CONN_STATE_RENDDESC_WAIT; conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
log_info(LD_REND, "Unknown descriptor %s. Fetching.", log_info(LD_REND, "Unknown descriptor %s. Fetching.",
safe_str(conn->rend_query)); safe_str(conn->rend_query));
rend_client_refetch_renddesc(conn->rend_query); rend_client_refetch_renddesc(conn->rend_query);
} else { /* r > 0 */ } else { /* r > 0 */
#define NUM_SECONDS_BEFORE_REFETCH (60*15) #define NUM_SECONDS_BEFORE_REFETCH (60*15)
if (time(NULL) - entry->received < NUM_SECONDS_BEFORE_REFETCH) { if (time(NULL) - entry->received < NUM_SECONDS_BEFORE_REFETCH) {
conn->state = AP_CONN_STATE_CIRCUIT_WAIT; conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
log_info(LD_REND, "Descriptor is here and fresh enough. Great."); log_info(LD_REND, "Descriptor is here and fresh enough. Great.");
if (connection_ap_handshake_attach_circuit(conn) < 0) { if (connection_ap_handshake_attach_circuit(conn) < 0) {
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return -1; return -1;
} }
} else { } else {
conn->state = AP_CONN_STATE_RENDDESC_WAIT; conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
log_info(LD_REND, "Stale descriptor %s. Refetching.", log_info(LD_REND, "Stale descriptor %s. Refetching.",
safe_str(conn->rend_query)); safe_str(conn->rend_query));
rend_client_refetch_renddesc(conn->rend_query); rend_client_refetch_renddesc(conn->rend_query);
@ -1218,25 +1225,25 @@ connection_ap_handshake_rewrite_and_attach(connection_t *conn,
* for close), else return 0. * for close), else return 0.
*/ */
static int static int
connection_ap_handshake_process_socks(connection_t *conn) connection_ap_handshake_process_socks(edge_connection_t *conn)
{ {
socks_request_t *socks; socks_request_t *socks;
int sockshere; int sockshere;
or_options_t *options = get_options(); or_options_t *options = get_options();
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_AP); tor_assert(conn->_base.type == CONN_TYPE_AP);
tor_assert(conn->state == AP_CONN_STATE_SOCKS_WAIT); tor_assert(conn->_base.state == AP_CONN_STATE_SOCKS_WAIT);
tor_assert(conn->socks_request); tor_assert(conn->socks_request);
socks = conn->socks_request; socks = conn->socks_request;
log_debug(LD_APP,"entered."); log_debug(LD_APP,"entered.");
sockshere = fetch_from_buf_socks(conn->inbuf, socks, sockshere = fetch_from_buf_socks(conn->_base.inbuf, socks,
options->TestSocks, options->SafeSocks); options->TestSocks, options->SafeSocks);
if (sockshere == 0) { if (sockshere == 0) {
if (socks->replylen) { if (socks->replylen) {
connection_write_to_buf(socks->reply, socks->replylen, conn); connection_write_to_buf(socks->reply, socks->replylen, TO_CONN(conn));
/* zero it out so we can do another round of negotiation */ /* zero it out so we can do another round of negotiation */
socks->replylen = 0; socks->replylen = 0;
} else { } else {
@ -1263,7 +1270,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE); control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE);
if (options->LeaveStreamsUnattached) { if (options->LeaveStreamsUnattached) {
conn->state = AP_CONN_STATE_CONTROLLER_WAIT; conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
return 0; return 0;
} }
return connection_ap_handshake_rewrite_and_attach(conn, NULL); return connection_ap_handshake_rewrite_and_attach(conn, NULL);
@ -1275,7 +1282,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
static uint16_t static uint16_t
get_unique_stream_id_by_circ(origin_circuit_t *circ) get_unique_stream_id_by_circ(origin_circuit_t *circ)
{ {
connection_t *tmpconn; edge_connection_t *tmpconn;
uint16_t test_stream_id; uint16_t test_stream_id;
uint32_t attempts=0; uint32_t attempts=0;
@ -1300,14 +1307,14 @@ again:
* If ap_conn is broken, mark it for close and return -1. Else return 0. * If ap_conn is broken, mark it for close and return -1. Else return 0.
*/ */
int int
connection_ap_handshake_send_begin(connection_t *ap_conn, connection_ap_handshake_send_begin(edge_connection_t *ap_conn,
origin_circuit_t *circ) origin_circuit_t *circ)
{ {
char payload[CELL_PAYLOAD_SIZE]; char payload[CELL_PAYLOAD_SIZE];
int payload_len; int payload_len;
tor_assert(ap_conn->type == CONN_TYPE_AP); tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
tor_assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(ap_conn->socks_request); tor_assert(ap_conn->socks_request);
ap_conn->stream_id = get_unique_stream_id_by_circ(circ); ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
@ -1334,9 +1341,9 @@ connection_ap_handshake_send_begin(connection_t *ap_conn,
ap_conn->package_window = STREAMWINDOW_START; ap_conn->package_window = STREAMWINDOW_START;
ap_conn->deliver_window = STREAMWINDOW_START; ap_conn->deliver_window = STREAMWINDOW_START;
ap_conn->state = AP_CONN_STATE_CONNECT_WAIT; ap_conn->_base.state = AP_CONN_STATE_CONNECT_WAIT;
log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d", log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d",
ap_conn->s, circ->_base.n_circ_id); ap_conn->_base.s, circ->_base.n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT); control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT);
return 0; return 0;
} }
@ -1347,14 +1354,14 @@ connection_ap_handshake_send_begin(connection_t *ap_conn,
* If ap_conn is broken, mark it for close and return -1. Else return 0. * If ap_conn is broken, mark it for close and return -1. Else return 0.
*/ */
int int
connection_ap_handshake_send_resolve(connection_t *ap_conn, connection_ap_handshake_send_resolve(edge_connection_t *ap_conn,
origin_circuit_t *circ) origin_circuit_t *circ)
{ {
int payload_len; int payload_len;
const char *string_addr; const char *string_addr;
tor_assert(ap_conn->type == CONN_TYPE_AP); tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
tor_assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(ap_conn->socks_request); tor_assert(ap_conn->socks_request);
tor_assert(ap_conn->socks_request->command == SOCKS_COMMAND_RESOLVE); tor_assert(ap_conn->socks_request->command == SOCKS_COMMAND_RESOLVE);
tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL); tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL);
@ -1378,9 +1385,9 @@ connection_ap_handshake_send_resolve(connection_t *ap_conn,
string_addr, payload_len, ap_conn->cpath_layer) < 0) string_addr, payload_len, ap_conn->cpath_layer) < 0)
return -1; /* circuit is closed, don't continue */ return -1; /* circuit is closed, don't continue */
ap_conn->state = AP_CONN_STATE_RESOLVE_WAIT; ap_conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d", log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d",
ap_conn->s, circ->_base.n_circ_id); ap_conn->_base.s, circ->_base.n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE); control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE);
return 0; return 0;
} }
@ -1395,7 +1402,7 @@ int
connection_ap_make_bridge(char *address, uint16_t port) connection_ap_make_bridge(char *address, uint16_t port)
{ {
int fd[2]; int fd[2];
connection_t *conn; edge_connection_t *conn;
int err; int err;
log_info(LD_APP,"Making AP bridge to %s:%d ...",safe_str(address),port); log_info(LD_APP,"Making AP bridge to %s:%d ...",safe_str(address),port);
@ -1413,8 +1420,8 @@ connection_ap_make_bridge(char *address, uint16_t port)
set_socket_nonblocking(fd[0]); set_socket_nonblocking(fd[0]);
set_socket_nonblocking(fd[1]); set_socket_nonblocking(fd[1]);
conn = connection_new(CONN_TYPE_AP); conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP));
conn->s = fd[0]; conn->_base.s = fd[0];
/* populate conn->socks_request */ /* populate conn->socks_request */
@ -1426,18 +1433,18 @@ connection_ap_make_bridge(char *address, uint16_t port)
conn->socks_request->port = port; conn->socks_request->port = port;
conn->socks_request->command = SOCKS_COMMAND_CONNECT; conn->socks_request->command = SOCKS_COMMAND_CONNECT;
conn->address = tor_strdup("(local bridge)"); conn->_base.address = tor_strdup("(local bridge)");
conn->addr = 0; conn->_base.addr = 0;
conn->port = 0; conn->_base.port = 0;
if (connection_add(conn) < 0) { /* no space, forget it */ if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */
connection_free(conn); /* this closes fd[0] */ connection_free(TO_CONN(conn)); /* this closes fd[0] */
tor_close_socket(fd[1]); tor_close_socket(fd[1]);
return -1; return -1;
} }
conn->state = AP_CONN_STATE_CIRCUIT_WAIT; conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
connection_start_reading(conn); connection_start_reading(TO_CONN(conn));
/* attaching to a dirty circuit is fine */ /* attaching to a dirty circuit is fine */
if (connection_ap_handshake_attach_circuit(conn) < 0) { if (connection_ap_handshake_attach_circuit(conn) < 0) {
@ -1456,7 +1463,7 @@ connection_ap_make_bridge(char *address, uint16_t port)
* in the socks extensions document. * in the socks extensions document.
**/ **/
void void
connection_ap_handshake_socks_resolved(connection_t *conn, connection_ap_handshake_socks_resolved(edge_connection_t *conn,
int answer_type, int answer_type,
size_t answer_len, size_t answer_len,
const char *answer, const char *answer,
@ -1523,7 +1530,7 @@ connection_ap_handshake_socks_resolved(connection_t *conn,
* If <b>reply</b> is undefined, <b>status</b> can't be 0. * If <b>reply</b> is undefined, <b>status</b> can't be 0.
*/ */
void void
connection_ap_handshake_socks_reply(connection_t *conn, char *reply, connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
size_t replylen, size_t replylen,
socks5_reply_status_t status) { socks5_reply_status_t status) {
char buf[256]; char buf[256];
@ -1538,7 +1545,7 @@ connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
return; return;
} }
if (replylen) { /* we already have a reply in mind */ if (replylen) { /* we already have a reply in mind */
connection_write_to_buf(reply, replylen, conn); connection_write_to_buf(reply, replylen, TO_CONN(conn));
conn->socks_request->has_finished = 1; conn->socks_request->has_finished = 1;
return; return;
} }
@ -1548,7 +1555,7 @@ connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
#define SOCKS4_REJECT 91 #define SOCKS4_REJECT 91
buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT); buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT);
/* leave version, destport, destip zero */ /* leave version, destport, destip zero */
connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, conn); connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, TO_CONN(conn));
} else if (conn->socks_request->socks_version == 5) { } else if (conn->socks_request->socks_version == 5) {
buf[0] = 5; /* version 5 */ buf[0] = 5; /* version 5 */
buf[1] = (char)status; buf[1] = (char)status;
@ -1556,7 +1563,7 @@ connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
buf[3] = 1; /* ipv4 addr */ buf[3] = 1; /* ipv4 addr */
memset(buf+4,0,6); /* Set external addr/port to 0. memset(buf+4,0,6); /* Set external addr/port to 0.
The spec doesn't seem to say what to do here. -RD */ The spec doesn't seem to say what to do here. -RD */
connection_write_to_buf(buf,10,conn); connection_write_to_buf(buf,10,TO_CONN(conn));
} }
/* If socks_version isn't 4 or 5, don't send anything. /* If socks_version isn't 4 or 5, don't send anything.
* This can happen in the case of AP bridges. */ * This can happen in the case of AP bridges. */
@ -1583,7 +1590,7 @@ connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
int int
connection_exit_begin_conn(cell_t *cell, circuit_t *circ) connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
{ {
connection_t *n_stream; edge_connection_t *n_stream;
relay_header_t rh; relay_header_t rh;
char *address=NULL; char *address=NULL;
uint16_t port; uint16_t port;
@ -1623,11 +1630,11 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
#endif #endif
log_debug(LD_EXIT,"Creating new exit connection."); log_debug(LD_EXIT,"Creating new exit connection.");
n_stream = connection_new(CONN_TYPE_EXIT); n_stream = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT));
n_stream->purpose = EXIT_PURPOSE_CONNECT; n_stream->_base.purpose = EXIT_PURPOSE_CONNECT;
n_stream->stream_id = rh.stream_id; n_stream->stream_id = rh.stream_id;
n_stream->port = port; n_stream->_base.port = port;
/* leave n_stream->s at -1, because it's not yet valid */ /* leave n_stream->s at -1, because it's not yet valid */
n_stream->package_window = STREAMWINDOW_START; n_stream->package_window = STREAMWINDOW_START;
n_stream->deliver_window = STREAMWINDOW_START; n_stream->deliver_window = STREAMWINDOW_START;
@ -1635,18 +1642,18 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) { if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ); origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
log_debug(LD_REND,"begin is for rendezvous. configuring stream."); log_debug(LD_REND,"begin is for rendezvous. configuring stream.");
n_stream->address = tor_strdup("(rendezvous)"); n_stream->_base.address = tor_strdup("(rendezvous)");
n_stream->state = EXIT_CONN_STATE_CONNECTING; n_stream->_base.state = EXIT_CONN_STATE_CONNECTING;
strlcpy(n_stream->rend_query, origin_circ->rend_query, strlcpy(n_stream->rend_query, origin_circ->rend_query,
sizeof(n_stream->rend_query)); sizeof(n_stream->rend_query));
tor_assert(connection_edge_is_rendezvous_stream(n_stream)); tor_assert(connection_edge_is_rendezvous_stream(n_stream));
assert_circuit_ok(circ); assert_circuit_ok(circ);
if (rend_service_set_connection_addr_port(n_stream, origin_circ) < 0) { if (rend_service_set_connection_addr_port(n_stream, origin_circ) < 0) {
log_info(LD_REND,"Didn't find rendezvous service (port %d)", log_info(LD_REND,"Didn't find rendezvous service (port %d)",
n_stream->port); n_stream->_base.port);
connection_edge_end(n_stream, END_STREAM_REASON_EXITPOLICY, connection_edge_end(n_stream, END_STREAM_REASON_EXITPOLICY,
n_stream->cpath_layer); n_stream->cpath_layer);
connection_free(n_stream); connection_free(TO_CONN(n_stream));
/* knock the whole thing down, somebody screwed up */ /* knock the whole thing down, somebody screwed up */
circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED); circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
tor_free(address); tor_free(address);
@ -1667,14 +1674,14 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
return 0; return 0;
} }
tor_strlower(address); tor_strlower(address);
n_stream->address = address; n_stream->_base.address = address;
n_stream->state = EXIT_CONN_STATE_RESOLVEFAILED; n_stream->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
/* default to failed, change in dns_resolve if it turns out not to fail */ /* default to failed, change in dns_resolve if it turns out not to fail */
if (we_are_hibernating()) { if (we_are_hibernating()) {
connection_edge_end(n_stream, END_STREAM_REASON_HIBERNATING, connection_edge_end(n_stream, END_STREAM_REASON_HIBERNATING,
n_stream->cpath_layer); n_stream->cpath_layer);
connection_free(n_stream); connection_free(TO_CONN(n_stream));
return 0; return 0;
} }
log_debug(LD_EXIT,"about to start the dns_resolve()."); log_debug(LD_EXIT,"about to start the dns_resolve().");
@ -1713,7 +1720,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
int int
connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
{ {
connection_t *dummy_conn; edge_connection_t *dummy_conn;
relay_header_t rh; relay_header_t rh;
assert_circuit_ok(TO_CIRCUIT(circ)); assert_circuit_ok(TO_CIRCUIT(circ));
@ -1726,13 +1733,13 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
* resolved; but if we didn't store them in a connection like this, * resolved; but if we didn't store them in a connection like this,
* the housekeeping in dns.c would get way more complicated.) * the housekeeping in dns.c would get way more complicated.)
*/ */
dummy_conn = connection_new(CONN_TYPE_EXIT); dummy_conn = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT));
dummy_conn->stream_id = rh.stream_id; dummy_conn->stream_id = rh.stream_id;
dummy_conn->address = tor_strndup(cell->payload+RELAY_HEADER_SIZE, dummy_conn->_base.address = tor_strndup(cell->payload+RELAY_HEADER_SIZE,
rh.length); rh.length);
dummy_conn->port = 0; dummy_conn->_base.port = 0;
dummy_conn->state = EXIT_CONN_STATE_RESOLVEFAILED; dummy_conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
dummy_conn->purpose = EXIT_PURPOSE_RESOLVE; dummy_conn->_base.purpose = EXIT_PURPOSE_RESOLVE;
/* send it off to the gethostbyname farm */ /* send it off to the gethostbyname farm */
switch (dns_resolve(dummy_conn)) { switch (dns_resolve(dummy_conn)) {
@ -1740,8 +1747,8 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
/* Connection freed; don't touch it. */ /* Connection freed; don't touch it. */
return 0; return 0;
case 1: /* The result was cached; a resolved cell was sent. */ case 1: /* The result was cached; a resolved cell was sent. */
if (!dummy_conn->marked_for_close) if (!dummy_conn->_base.marked_for_close)
connection_free(dummy_conn); connection_free(TO_CONN(dummy_conn));
return 0; return 0;
case 0: /* resolve added to pending list */ case 0: /* resolve added to pending list */
dummy_conn->next_stream = circ->resolving_streams; dummy_conn->next_stream = circ->resolving_streams;
@ -1761,17 +1768,19 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
* streams must not reveal what IP they connected to.) * streams must not reveal what IP they connected to.)
*/ */
void void
connection_exit_connect(connection_t *conn) connection_exit_connect(edge_connection_t *edge_conn)
{ {
uint32_t addr; uint32_t addr;
uint16_t port; uint16_t port;
connection_t *conn = TO_CONN(edge_conn);
if (!connection_edge_is_rendezvous_stream(conn) && if (!connection_edge_is_rendezvous_stream(edge_conn) &&
router_compare_to_my_exit_policy(conn)) { router_compare_to_my_exit_policy(edge_conn)) {
log_info(LD_EXIT,"%s:%d failed exit policy. Closing.", log_info(LD_EXIT,"%s:%d failed exit policy. Closing.",
escaped_safe_str(conn->address), conn->port); escaped_safe_str(conn->address), conn->port);
connection_edge_end(conn, END_STREAM_REASON_EXITPOLICY, conn->cpath_layer); connection_edge_end(edge_conn, END_STREAM_REASON_EXITPOLICY,
circuit_detach_stream(circuit_get_by_edge_conn(conn), conn); edge_conn->cpath_layer);
circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
connection_free(conn); connection_free(conn);
return; return;
} }
@ -1802,8 +1811,8 @@ connection_exit_connect(connection_t *conn)
log_debug(LD_EXIT,"about to try connecting"); log_debug(LD_EXIT,"about to try connecting");
switch (connection_connect(conn, conn->address, addr, port)) { switch (connection_connect(conn, conn->address, addr, port)) {
case -1: case -1:
connection_edge_end_errno(conn, conn->cpath_layer); connection_edge_end_errno(edge_conn, edge_conn->cpath_layer);
circuit_detach_stream(circuit_get_by_edge_conn(conn), conn); circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
connection_free(conn); connection_free(conn);
return; return;
case 0: case 0:
@ -1825,20 +1834,20 @@ connection_exit_connect(connection_t *conn)
connection_watch_events(conn, EV_READ); connection_watch_events(conn, EV_READ);
/* also, deliver a 'connected' cell back through the circuit. */ /* also, deliver a 'connected' cell back through the circuit. */
if (connection_edge_is_rendezvous_stream(conn)) { /* rendezvous stream */ if (connection_edge_is_rendezvous_stream(edge_conn)) { /* rendezvous stream */
/* don't send an address back! */ /* don't send an address back! */
connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), connection_edge_send_command(edge_conn, circuit_get_by_edge_conn(edge_conn),
RELAY_COMMAND_CONNECTED, RELAY_COMMAND_CONNECTED,
NULL, 0, conn->cpath_layer); NULL, 0, edge_conn->cpath_layer);
} else { /* normal stream */ } else { /* normal stream */
/* This must be the original address, not the redirected address. */ /* This must be the original address, not the redirected address. */
char connected_payload[8]; char connected_payload[8];
set_uint32(connected_payload, htonl(conn->addr)); set_uint32(connected_payload, htonl(conn->addr));
set_uint32(connected_payload+4, set_uint32(connected_payload+4,
htonl(dns_clip_ttl(conn->address_ttl))); htonl(dns_clip_ttl(edge_conn->address_ttl)));
connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), connection_edge_send_command(edge_conn, circuit_get_by_edge_conn(edge_conn),
RELAY_COMMAND_CONNECTED, RELAY_COMMAND_CONNECTED,
connected_payload, 8, conn->cpath_layer); connected_payload, 8, edge_conn->cpath_layer);
} }
} }
@ -1846,7 +1855,7 @@ connection_exit_connect(connection_t *conn)
* it is a general stream. * it is a general stream.
*/ */
int int
connection_edge_is_rendezvous_stream(connection_t *conn) connection_edge_is_rendezvous_stream(edge_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
if (*conn->rend_query) /* XXX */ if (*conn->rend_query) /* XXX */
@ -1860,10 +1869,10 @@ connection_edge_is_rendezvous_stream(connection_t *conn)
* resolved.) * resolved.)
*/ */
int int
connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit) connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_AP); tor_assert(conn->_base.type == CONN_TYPE_AP);
tor_assert(conn->socks_request); tor_assert(conn->socks_request);
tor_assert(exit); tor_assert(exit);

View file

@ -19,8 +19,8 @@ const char connection_or_c_id[] =
#define TIGHT_CERT_ALLOW_SKEW (90*60) #define TIGHT_CERT_ALLOW_SKEW (90*60)
static int connection_tls_finish_handshake(connection_t *conn); static int connection_tls_finish_handshake(or_connection_t *conn);
static int connection_or_process_cells_from_inbuf(connection_t *conn); static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
/**************************************************************/ /**************************************************************/
@ -32,11 +32,10 @@ static digestmap_t *orconn_identity_map = NULL;
/** If conn is listed in orconn_identity_map, remove it, and clear /** If conn is listed in orconn_identity_map, remove it, and clear
* conn->identity_digest. */ * conn->identity_digest. */
void void
connection_or_remove_from_identity_map(connection_t *conn) connection_or_remove_from_identity_map(or_connection_t *conn)
{ {
connection_t *tmp; or_connection_t *tmp;
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_OR);
if (!orconn_identity_map) if (!orconn_identity_map)
return; return;
tmp = digestmap_get(orconn_identity_map, conn->identity_digest); tmp = digestmap_get(orconn_identity_map, conn->identity_digest);
@ -73,8 +72,9 @@ connection_or_clear_identity_map(void)
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
connection_t* conn = carray[i]; connection_t* conn = carray[i];
if (conn->type == CONN_TYPE_OR) { if (conn->type == CONN_TYPE_OR) {
memset(conn->identity_digest, 0, DIGEST_LEN); or_connection_t *or_conn = TO_OR_CONN(conn);
conn->next_with_same_id = NULL; memset(or_conn->identity_digest, 0, DIGEST_LEN);
or_conn->next_with_same_id = NULL;
} }
} }
@ -87,11 +87,10 @@ connection_or_clear_identity_map(void)
/** Change conn->identity_digest to digest, and add conn into /** Change conn->identity_digest to digest, and add conn into
* orconn_digest_map. */ * orconn_digest_map. */
static void static void
connection_or_set_identity_digest(connection_t *conn, const char *digest) connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
{ {
connection_t *tmp; or_connection_t *tmp;
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_OR);
tor_assert(digest); tor_assert(digest);
if (!orconn_identity_map) if (!orconn_identity_map)
@ -136,10 +135,10 @@ cell_unpack(cell_t *dest, const char *src)
} }
int int
connection_or_reached_eof(connection_t *conn) connection_or_reached_eof(or_connection_t *conn)
{ {
log_info(LD_OR,"OR connection reached EOF. Closing."); log_info(LD_OR,"OR connection reached EOF. Closing.");
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return 0; return 0;
} }
@ -149,13 +148,14 @@ connection_or_reached_eof(connection_t *conn)
* and hope for better luck next time. * and hope for better luck next time.
*/ */
static int static int
connection_or_read_proxy_response(connection_t *conn) connection_or_read_proxy_response(or_connection_t *or_conn)
{ {
char *headers; char *headers;
char *reason=NULL; char *reason=NULL;
int status_code; int status_code;
time_t date_header; time_t date_header;
int compression; int compression;
connection_t *conn = TO_CONN(or_conn);
switch (fetch_from_buf_http(conn->inbuf, switch (fetch_from_buf_http(conn->inbuf,
&headers, MAX_HEADERS_SIZE, &headers, MAX_HEADERS_SIZE,
@ -185,7 +185,7 @@ connection_or_read_proxy_response(connection_t *conn)
"HTTPS connect to '%s' successful! (200 %s) Starting TLS.", "HTTPS connect to '%s' successful! (200 %s) Starting TLS.",
conn->address, escaped(reason)); conn->address, escaped(reason));
tor_free(reason); tor_free(reason);
if (connection_tls_start_handshake(conn, 0) < 0) { if (connection_tls_start_handshake(or_conn, 0) < 0) {
/* TLS handshaking error of some kind. */ /* TLS handshaking error of some kind. */
connection_mark_for_close(conn); connection_mark_for_close(conn);
@ -209,12 +209,11 @@ connection_or_read_proxy_response(connection_t *conn)
* (else do nothing). * (else do nothing).
*/ */
int int
connection_or_process_inbuf(connection_t *conn) connection_or_process_inbuf(or_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_OR);
switch (conn->state) { switch (conn->_base.state) {
case OR_CONN_STATE_PROXY_READING: case OR_CONN_STATE_PROXY_READING:
return connection_or_read_proxy_response(conn); return connection_or_read_proxy_response(conn);
case OR_CONN_STATE_OPEN: case OR_CONN_STATE_OPEN:
@ -233,24 +232,22 @@ connection_or_process_inbuf(connection_t *conn)
* return 0. * return 0.
*/ */
int int
connection_or_finished_flushing(connection_t *conn) connection_or_finished_flushing(or_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_OR); assert_connection_ok(TO_CONN(conn),0);
assert_connection_ok(conn,0); switch (conn->_base.state) {
switch (conn->state) {
case OR_CONN_STATE_PROXY_FLUSHING: case OR_CONN_STATE_PROXY_FLUSHING:
log_debug(LD_OR,"finished sending CONNECT to proxy."); log_debug(LD_OR,"finished sending CONNECT to proxy.");
conn->state = OR_CONN_STATE_PROXY_READING; conn->_base.state = OR_CONN_STATE_PROXY_READING;
connection_stop_writing(conn); connection_stop_writing(TO_CONN(conn));
break; break;
case OR_CONN_STATE_OPEN: case OR_CONN_STATE_OPEN:
connection_stop_writing(conn); connection_stop_writing(TO_CONN(conn));
break; break;
default: default:
log_err(LD_BUG,"BUG: called in unexpected state %d.", conn->state); log_err(LD_BUG,"BUG: called in unexpected state %d.", conn->_base.state);
tor_fragile_assert(); tor_fragile_assert();
return -1; return -1;
} }
@ -260,10 +257,11 @@ connection_or_finished_flushing(connection_t *conn)
/** Connected handler for OR connections: begin the TLS handshake. /** Connected handler for OR connections: begin the TLS handshake.
*/ */
int int
connection_or_finished_connecting(connection_t *conn) connection_or_finished_connecting(or_connection_t *or_conn)
{ {
tor_assert(conn); connection_t *conn;
tor_assert(conn->type == CONN_TYPE_OR); tor_assert(or_conn);
conn = TO_CONN(or_conn);
tor_assert(conn->state == OR_CONN_STATE_CONNECTING); tor_assert(conn->state == OR_CONN_STATE_CONNECTING);
log_debug(LD_OR,"OR connect() to router at %s:%u finished.", log_debug(LD_OR,"OR connect() to router at %s:%u finished.",
@ -298,7 +296,7 @@ connection_or_finished_connecting(connection_t *conn)
return 0; return 0;
} }
if (connection_tls_start_handshake(conn, 0) < 0) { if (connection_tls_start_handshake(or_conn, 0) < 0) {
/* TLS handshaking error of some kind. */ /* TLS handshaking error of some kind. */
connection_mark_for_close(conn); connection_mark_for_close(conn);
return -1; return -1;
@ -310,7 +308,7 @@ connection_or_finished_connecting(connection_t *conn)
* have an addr/port/id_digest, then fill in as much as we can. Start * have an addr/port/id_digest, then fill in as much as we can. Start
* by checking to see if this describes a router we know. */ * by checking to see if this describes a router we know. */
static void static void
connection_or_init_conn_from_address(connection_t *conn, connection_or_init_conn_from_address(or_connection_t *conn,
uint32_t addr, uint16_t port, uint32_t addr, uint16_t port,
const char *id_digest, const char *id_digest,
int started_here) int started_here)
@ -320,19 +318,19 @@ connection_or_init_conn_from_address(connection_t *conn,
conn->bandwidthrate = (int)options->BandwidthRate; conn->bandwidthrate = (int)options->BandwidthRate;
conn->receiver_bucket = conn->bandwidthburst = (int)options->BandwidthBurst; conn->receiver_bucket = conn->bandwidthburst = (int)options->BandwidthBurst;
connection_or_set_identity_digest(conn, id_digest); connection_or_set_identity_digest(conn, id_digest);
conn->addr = addr; conn->_base.addr = addr;
conn->port = port; conn->_base.port = port;
if (r) { if (r) {
if (!started_here) { if (!started_here) {
/* Override the addr/port, so our log messages will make sense. /* Override the addr/port, so our log messages will make sense.
* This is dangerous, since if we ever try looking up a conn by * This is dangerous, since if we ever try looking up a conn by
* its actual addr/port, we won't remember. Careful! */ * its actual addr/port, we won't remember. Careful! */
conn->addr = r->addr; conn->_base.addr = r->addr;
conn->port = r->or_port; conn->_base.port = r->or_port;
} }
conn->nickname = tor_strdup(r->nickname); conn->nickname = tor_strdup(r->nickname);
tor_free(conn->address); tor_free(conn->_base.address);
conn->address = tor_strdup(r->address); conn->_base.address = tor_strdup(r->address);
} else { } else {
const char *n; const char *n;
/* If we're an authoritative directory server, we may know a /* If we're an authoritative directory server, we may know a
@ -346,8 +344,8 @@ connection_or_init_conn_from_address(connection_t *conn,
base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1, base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
conn->identity_digest, DIGEST_LEN); conn->identity_digest, DIGEST_LEN);
} }
tor_free(conn->address); tor_free(conn->_base.address);
conn->address = tor_dup_addr(addr); conn->_base.address = tor_dup_addr(addr);
} }
} }
@ -360,11 +358,11 @@ connection_or_init_conn_from_address(connection_t *conn,
* 4) Then if there are any non-empty conns, ignore empty conns. * 4) Then if there are any non-empty conns, ignore empty conns.
* 5) Of the remaining conns, prefer newer conns. * 5) Of the remaining conns, prefer newer conns.
*/ */
connection_t * or_connection_t *
connection_or_get_by_identity_digest(const char *digest) connection_or_get_by_identity_digest(const char *digest)
{ {
int newer; int newer;
connection_t *conn, *best=NULL; or_connection_t *conn, *best=NULL;
if (!orconn_identity_map) if (!orconn_identity_map)
return NULL; return NULL;
@ -372,26 +370,26 @@ connection_or_get_by_identity_digest(const char *digest)
conn = digestmap_get(orconn_identity_map, digest); conn = digestmap_get(orconn_identity_map, digest);
for (; conn; conn = conn->next_with_same_id) { for (; conn; conn = conn->next_with_same_id) {
tor_assert(conn->magic == CONNECTION_MAGIC); tor_assert(conn->_base.magic == OR_CONNECTION_MAGIC);
tor_assert(conn->type == CONN_TYPE_OR); tor_assert(conn->_base.type == CONN_TYPE_OR);
tor_assert(!memcmp(conn->identity_digest, digest, DIGEST_LEN)); tor_assert(!memcmp(conn->identity_digest, digest, DIGEST_LEN));
if (conn->marked_for_close) if (conn->_base.marked_for_close)
continue; continue;
if (!best) { if (!best) {
best = conn; /* whatever it is, it's better than nothing. */ best = conn; /* whatever it is, it's better than nothing. */
continue; continue;
} }
if (best->state == OR_CONN_STATE_OPEN && if (best->_base.state == OR_CONN_STATE_OPEN &&
conn->state != OR_CONN_STATE_OPEN) conn->_base.state != OR_CONN_STATE_OPEN)
continue; /* avoid non-open conns if we can */ continue; /* avoid non-open conns if we can */
newer = best->timestamp_created < conn->timestamp_created; newer = best->_base.timestamp_created < conn->_base.timestamp_created;
if (!best->is_obsolete && conn->is_obsolete) if (!best->_base.or_is_obsolete && conn->_base.or_is_obsolete)
continue; /* We never prefer obsolete over non-obsolete connections. */ continue; /* We never prefer obsolete over non-obsolete connections. */
if ( if (
/* We prefer non-obsolete connections: */ /* We prefer non-obsolete connections: */
(best->is_obsolete && !conn->is_obsolete) || (best->_base.or_is_obsolete && !conn->_base.or_is_obsolete) ||
/* If both have circuits we prefer the newer: */ /* If both have circuits we prefer the newer: */
(best->n_circuits && conn->n_circuits && newer) || (best->n_circuits && conn->n_circuits && newer) ||
/* If neither has circuits we prefer the newer: */ /* If neither has circuits we prefer the newer: */
@ -418,10 +416,10 @@ connection_or_get_by_identity_digest(const char *digest)
* *
* Return the launched conn, or NULL if it failed. * Return the launched conn, or NULL if it failed.
*/ */
connection_t * or_connection_t *
connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest) connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
{ {
connection_t *conn; or_connection_t *conn;
or_options_t *options = get_options(); or_options_t *options = get_options();
tor_assert(id_digest); tor_assert(id_digest);
@ -431,11 +429,11 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
return NULL; return NULL;
} }
conn = connection_new(CONN_TYPE_OR); conn = TO_OR_CONN(connection_new(CONN_TYPE_OR));
/* set up conn so it's got all the data we need to remember */ /* set up conn so it's got all the data we need to remember */
connection_or_init_conn_from_address(conn, addr, port, id_digest, 1); connection_or_init_conn_from_address(conn, addr, port, id_digest, 1);
conn->state = OR_CONN_STATE_CONNECTING; conn->_base.state = OR_CONN_STATE_CONNECTING;
control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED); control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED);
if (options->HttpsProxy) { if (options->HttpsProxy) {
@ -444,7 +442,7 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
port = options->HttpsProxyPort; port = options->HttpsProxyPort;
} }
switch (connection_connect(conn, conn->address, addr, port)) { switch (connection_connect(TO_CONN(conn), conn->_base.address, addr, port)) {
case -1: case -1:
/* If the connection failed immediately, and we're using /* If the connection failed immediately, and we're using
* an https proxy, our https proxy is down. Don't blame the * an https proxy, our https proxy is down. Don't blame the
@ -454,10 +452,10 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
router_set_status(conn->identity_digest, 0); router_set_status(conn->identity_digest, 0);
} }
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED); control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED);
connection_free(conn); connection_free(TO_CONN(conn));
return NULL; return NULL;
case 0: case 0:
connection_watch_events(conn, EV_READ | EV_WRITE); connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
/* writable indicates finish, readable indicates broken link, /* writable indicates finish, readable indicates broken link,
error indicates broken link on windows */ error indicates broken link on windows */
return conn; return conn;
@ -480,16 +478,16 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest)
* Return -1 if <b>conn</b> is broken, else return 0. * Return -1 if <b>conn</b> is broken, else return 0.
*/ */
int int
connection_tls_start_handshake(connection_t *conn, int receiving) connection_tls_start_handshake(or_connection_t *conn, int receiving)
{ {
conn->state = OR_CONN_STATE_HANDSHAKING; conn->_base.state = OR_CONN_STATE_HANDSHAKING;
conn->tls = tor_tls_new(conn->s, receiving); conn->tls = tor_tls_new(conn->_base.s, receiving);
if (!conn->tls) { if (!conn->tls) {
log_warn(LD_BUG,"tor_tls_new failed. Closing."); log_warn(LD_BUG,"tor_tls_new failed. Closing.");
return -1; return -1;
} }
connection_start_reading(conn); connection_start_reading(TO_CONN(conn));
log_debug(LD_OR,"starting TLS handshake on fd %d", conn->s); log_debug(LD_OR,"starting TLS handshake on fd %d", conn->_base.s);
if (connection_tls_continue_handshake(conn) < 0) { if (connection_tls_continue_handshake(conn) < 0) {
return -1; return -1;
} }
@ -502,7 +500,7 @@ connection_tls_start_handshake(connection_t *conn, int receiving)
* Return -1 if <b>conn</b> is broken, else return 0. * Return -1 if <b>conn</b> is broken, else return 0.
*/ */
int int
connection_tls_continue_handshake(connection_t *conn) connection_tls_continue_handshake(or_connection_t *conn)
{ {
check_no_tls_errors(); check_no_tls_errors();
switch (tor_tls_handshake(conn->tls)) { switch (tor_tls_handshake(conn->tls)) {
@ -513,7 +511,7 @@ connection_tls_continue_handshake(connection_t *conn)
case TOR_TLS_DONE: case TOR_TLS_DONE:
return connection_tls_finish_handshake(conn); return connection_tls_finish_handshake(conn);
case TOR_TLS_WANTWRITE: case TOR_TLS_WANTWRITE:
connection_start_writing(conn); connection_start_writing(TO_CONN(conn));
log_debug(LD_OR,"wanted write"); log_debug(LD_OR,"wanted write");
return 0; return 0;
case TOR_TLS_WANTREAD: /* handshaking conns are *always* reading */ case TOR_TLS_WANTREAD: /* handshaking conns are *always* reading */
@ -531,9 +529,9 @@ connection_tls_continue_handshake(connection_t *conn)
* one day so we're clearer. * one day so we're clearer.
*/ */
int int
connection_or_nonopen_was_started_here(connection_t *conn) connection_or_nonopen_was_started_here(or_connection_t *conn)
{ {
tor_assert(conn->type == CONN_TYPE_OR); tor_assert(conn->_base.type == CONN_TYPE_OR);
if (!conn->tls) if (!conn->tls)
return 1; /* it's still in proxy states or something */ return 1; /* it's still in proxy states or something */
return !tor_tls_is_server(conn->tls); return !tor_tls_is_server(conn->tls);
@ -557,7 +555,7 @@ connection_or_nonopen_was_started_here(connection_t *conn)
* this guy; and note that this guy is reachable. * this guy; and note that this guy is reachable.
*/ */
static int static int
connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd) connection_or_check_valid_handshake(or_connection_t *conn, char *digest_rcvd)
{ {
routerinfo_t *router; routerinfo_t *router;
crypto_pk_env_t *identity_rcvd=NULL; crypto_pk_env_t *identity_rcvd=NULL;
@ -568,7 +566,7 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd)
check_no_tls_errors(); check_no_tls_errors();
if (! tor_tls_peer_has_cert(conn->tls)) { if (! tor_tls_peer_has_cert(conn->tls)) {
log_info(LD_PROTOCOL,"Peer (%s:%d) didn't send a cert! Closing.", log_info(LD_PROTOCOL,"Peer (%s:%d) didn't send a cert! Closing.",
conn->address, conn->port); conn->_base.address, conn->_base.port);
return -1; return -1;
} }
check_no_tls_errors(); check_no_tls_errors();
@ -576,17 +574,17 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd)
sizeof(nickname))) { sizeof(nickname))) {
log_fn(severity,LD_PROTOCOL,"Other side (%s:%d) has a cert without a " log_fn(severity,LD_PROTOCOL,"Other side (%s:%d) has a cert without a "
"valid nickname. Closing.", "valid nickname. Closing.",
conn->address, conn->port); conn->_base.address, conn->_base.port);
return -1; return -1;
} }
check_no_tls_errors(); check_no_tls_errors();
log_debug(LD_OR, "Other side (%s:%d) claims to be router '%s'", log_debug(LD_OR, "Other side (%s:%d) claims to be router '%s'",
conn->address, conn->port, nickname); conn->_base.address, conn->_base.port, nickname);
if (tor_tls_verify(severity, conn->tls, &identity_rcvd) < 0) { if (tor_tls_verify(severity, conn->tls, &identity_rcvd) < 0) {
log_fn(severity,LD_OR,"Other side, which claims to be router '%s' (%s:%d)," log_fn(severity,LD_OR,"Other side, which claims to be router '%s' (%s:%d),"
" has a cert but it's invalid. Closing.", " has a cert but it's invalid. Closing.",
nickname, conn->address, conn->port); nickname, conn->_base.address, conn->_base.port);
return -1; return -1;
} }
check_no_tls_errors(); check_no_tls_errors();
@ -607,7 +605,7 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd)
log_fn(severity, LD_OR, log_fn(severity, LD_OR,
"Identity key not as expected for router claiming to be " "Identity key not as expected for router claiming to be "
"'%s' (%s:%d)", "'%s' (%s:%d)",
nickname, conn->address, conn->port); nickname, conn->_base.address, conn->_base.port);
return -1; return -1;
} }
@ -623,7 +621,7 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd)
log_fn(severity, LD_OR, log_fn(severity, LD_OR,
"Identity key not as expected for router at %s:%d: wanted %s " "Identity key not as expected for router at %s:%d: wanted %s "
"but got %s", "but got %s",
conn->address, conn->port, expected, seen); conn->_base.address, conn->_base.port, expected, seen);
entry_guard_set_status(conn->identity_digest, 0); entry_guard_set_status(conn->identity_digest, 0);
router_set_status(conn->identity_digest, 0); router_set_status(conn->identity_digest, 0);
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED); control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED);
@ -633,7 +631,7 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd)
/* We initiated this connection to address:port. Drop all routers /* We initiated this connection to address:port. Drop all routers
* with the same address:port and a different key or nickname. * with the same address:port and a different key or nickname.
*/ */
dirserv_orconn_tls_done(conn->address, conn->port, dirserv_orconn_tls_done(conn->_base.address, conn->_base.port,
digest_rcvd, nickname, as_advertised); digest_rcvd, nickname, as_advertised);
} }
if (!as_advertised) if (!as_advertised)
@ -654,7 +652,7 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd)
* directory to be dirty (only matters if I'm an authdirserver). * directory to be dirty (only matters if I'm an authdirserver).
*/ */
static int static int
connection_tls_finish_handshake(connection_t *conn) connection_tls_finish_handshake(or_connection_t *conn)
{ {
char digest_rcvd[DIGEST_LEN]; char digest_rcvd[DIGEST_LEN];
int started_here = connection_or_nonopen_was_started_here(conn); int started_here = connection_or_nonopen_was_started_here(conn);
@ -664,7 +662,7 @@ connection_tls_finish_handshake(connection_t *conn)
return -1; return -1;
if (!started_here) { if (!started_here) {
connection_or_init_conn_from_address(conn,conn->addr,conn->port, connection_or_init_conn_from_address(conn,conn->_base.addr,conn->_base.port,
digest_rcvd, 0); digest_rcvd, 0);
/* Annotate that we received a TLS connection. /* Annotate that we received a TLS connection.
@ -677,12 +675,12 @@ connection_tls_finish_handshake(connection_t *conn)
* The reason this bandaid is here is because there's a bug in * The reason this bandaid is here is because there's a bug in
* Tor 0.1.1.x where middle hops don't always send their create * Tor 0.1.1.x where middle hops don't always send their create
* cell; so some servers rarely find themselves reachable. */ * cell; so some servers rarely find themselves reachable. */
// if (!is_local_IP(conn->addr)) // if (!is_local_IP(conn->_base.addr))
// router_orport_found_reachable(); // router_orport_found_reachable();
} }
directory_set_dirty(); directory_set_dirty();
conn->state = OR_CONN_STATE_OPEN; conn->_base.state = OR_CONN_STATE_OPEN;
control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED); control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED);
if (started_here) { if (started_here) {
rep_hist_note_connect_succeeded(conn->identity_digest, time(NULL)); rep_hist_note_connect_succeeded(conn->identity_digest, time(NULL));
@ -692,7 +690,7 @@ connection_tls_finish_handshake(connection_t *conn)
} }
router_set_status(conn->identity_digest, 1); router_set_status(conn->identity_digest, 1);
} }
connection_watch_events(conn, EV_READ); connection_watch_events(TO_CONN(conn), EV_READ);
circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */ circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
return 0; return 0;
} }
@ -704,18 +702,17 @@ connection_tls_finish_handshake(connection_t *conn)
* ready, then try to flush the record now. * ready, then try to flush the record now.
*/ */
void void
connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn) connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn)
{ {
char networkcell[CELL_NETWORK_SIZE]; char networkcell[CELL_NETWORK_SIZE];
char *n = networkcell; char *n = networkcell;
tor_assert(cell); tor_assert(cell);
tor_assert(conn); tor_assert(conn);
tor_assert(connection_speaks_cells(conn));
cell_pack(n, cell); cell_pack(n, cell);
connection_write_to_buf(n, CELL_NETWORK_SIZE, conn); connection_write_to_buf(n, CELL_NETWORK_SIZE, TO_CONN(conn));
#define MIN_TLS_FLUSHLEN 15872 #define MIN_TLS_FLUSHLEN 15872
/* openssl tls record size is 16383, this is close. The goal here is to /* openssl tls record size is 16383, this is close. The goal here is to
@ -723,26 +720,28 @@ connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn)
* during periods of high load we won't read the entire megabyte from * during periods of high load we won't read the entire megabyte from
* input before pushing any data out. It also has the feature of not * input before pushing any data out. It also has the feature of not
* growing huge outbufs unless something is slow. */ * growing huge outbufs unless something is slow. */
if (conn->outbuf_flushlen-CELL_NETWORK_SIZE < MIN_TLS_FLUSHLEN && if (conn->_base.outbuf_flushlen-CELL_NETWORK_SIZE < MIN_TLS_FLUSHLEN &&
conn->outbuf_flushlen >= MIN_TLS_FLUSHLEN) { conn->_base.outbuf_flushlen >= MIN_TLS_FLUSHLEN) {
int extra = conn->outbuf_flushlen - MIN_TLS_FLUSHLEN; int extra = conn->_base.outbuf_flushlen - MIN_TLS_FLUSHLEN;
conn->outbuf_flushlen = MIN_TLS_FLUSHLEN; conn->_base.outbuf_flushlen = MIN_TLS_FLUSHLEN;
if (connection_handle_write(conn) < 0) { if (connection_handle_write(TO_CONN(conn)) < 0) {
if (!conn->marked_for_close) { if (!conn->_base.marked_for_close) {
/* this connection is broken. remove it. */ /* this connection is broken. remove it. */
log_warn(LD_BUG, log_warn(LD_BUG,
"Bug: unhandled error on write for OR conn (fd %d); removing", "Bug: unhandled error on write for OR conn (fd %d); removing",
conn->s); conn->_base.s);
tor_fragile_assert(); tor_fragile_assert();
conn->has_sent_end = 1; /* don't cry wolf about duplicate close */ // XXX This was supposed to be edge-only!
// conn->has_sent_end = 1; /* don't cry wolf about duplicate close */
/* XXX do we need a close-immediate here, so we don't try to flush? */ /* XXX do we need a close-immediate here, so we don't try to flush? */
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
} }
return; return;
} }
if (extra) { if (extra) {
conn->outbuf_flushlen += extra; conn->_base.outbuf_flushlen += extra;
connection_start_writing(conn); connection_start_writing(TO_CONN(conn));
} }
} }
} }
@ -755,7 +754,7 @@ connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn)
* Always return 0. * Always return 0.
*/ */
static int static int
connection_or_process_cells_from_inbuf(connection_t *conn) connection_or_process_cells_from_inbuf(or_connection_t *conn)
{ {
char buf[CELL_NETWORK_SIZE]; char buf[CELL_NETWORK_SIZE];
cell_t cell; cell_t cell;
@ -763,13 +762,13 @@ connection_or_process_cells_from_inbuf(connection_t *conn)
loop: loop:
log_debug(LD_OR, log_debug(LD_OR,
"%d: starting, inbuf_datalen %d (%d pending in tls object).", "%d: starting, inbuf_datalen %d (%d pending in tls object).",
conn->s,(int)buf_datalen(conn->inbuf), conn->_base.s,(int)buf_datalen(conn->_base.inbuf),
tor_tls_get_pending_bytes(conn->tls)); tor_tls_get_pending_bytes(conn->tls));
if (buf_datalen(conn->inbuf) < CELL_NETWORK_SIZE) /* whole response if (buf_datalen(conn->_base.inbuf) < CELL_NETWORK_SIZE) /* whole response
available? */ available? */
return 0; /* not yet */ return 0; /* not yet */
connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, conn); connection_fetch_from_buf(buf, CELL_NETWORK_SIZE, TO_CONN(conn));
/* retrieve cell info from buf (create the host-order struct from the /* retrieve cell info from buf (create the host-order struct from the
* network-order string) */ * network-order string) */
@ -787,12 +786,11 @@ loop:
* Return 0. * Return 0.
*/ */
int int
connection_or_send_destroy(uint16_t circ_id, connection_t *conn, int reason) connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn, int reason)
{ {
cell_t cell; cell_t cell;
tor_assert(conn); tor_assert(conn);
tor_assert(connection_speaks_cells(conn));
memset(&cell, 0, sizeof(cell_t)); memset(&cell, 0, sizeof(cell_t));
cell.circ_id = circ_id; cell.circ_id = circ_id;

View file

@ -131,57 +131,57 @@ static int disable_log_messages = 0;
static int authentication_cookie_is_set = 0; static int authentication_cookie_is_set = 0;
static char authentication_cookie[AUTHENTICATION_COOKIE_LEN]; static char authentication_cookie[AUTHENTICATION_COOKIE_LEN];
static void connection_printf_to_buf(connection_t *conn, static void connection_printf_to_buf(control_connection_t *conn,
const char *format, ...) const char *format, ...)
CHECK_PRINTF(2,3); CHECK_PRINTF(2,3);
/*static*/ size_t write_escaped_data(const char *data, size_t len, /*static*/ size_t write_escaped_data(const char *data, size_t len,
int translate_newlines, char **out); int translate_newlines, char **out);
/*static*/ size_t read_escaped_data(const char *data, size_t len, /*static*/ size_t read_escaped_data(const char *data, size_t len,
int translate_newlines, char **out); int translate_newlines, char **out);
static void send_control0_message(connection_t *conn, uint16_t type, static void send_control0_message(control_connection_t *conn, uint16_t type,
uint32_t len, const char *body); uint32_t len, const char *body);
static void send_control_done(connection_t *conn); static void send_control_done(control_connection_t *conn);
static void send_control_done2(connection_t *conn, const char *msg, static void send_control_done2(control_connection_t *conn, const char *msg,
size_t len); size_t len);
static void send_control0_error(connection_t *conn, uint16_t error, static void send_control0_error(control_connection_t *conn, uint16_t error,
const char *message); const char *message);
static void send_control0_event(uint16_t event, uint32_t len, static void send_control0_event(uint16_t event, uint32_t len,
const char *body); const char *body);
static void send_control1_event(uint16_t event, const char *format, ...) static void send_control1_event(uint16_t event, const char *format, ...)
CHECK_PRINTF(2,3); CHECK_PRINTF(2,3);
static int handle_control_setconf(connection_t *conn, uint32_t len, static int handle_control_setconf(control_connection_t *conn, uint32_t len,
char *body); char *body);
static int handle_control_resetconf(connection_t *conn, uint32_t len, static int handle_control_resetconf(control_connection_t *conn, uint32_t len,
char *body); char *body);
static int handle_control_getconf(connection_t *conn, uint32_t len, static int handle_control_getconf(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_setevents(connection_t *conn, uint32_t len, static int handle_control_setevents(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_authenticate(connection_t *conn, uint32_t len, static int handle_control_authenticate(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_saveconf(connection_t *conn, uint32_t len, static int handle_control_saveconf(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_signal(connection_t *conn, uint32_t len, static int handle_control_signal(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_mapaddress(connection_t *conn, uint32_t len, static int handle_control_mapaddress(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_getinfo(connection_t *conn, uint32_t len, static int handle_control_getinfo(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_extendcircuit(connection_t *conn, uint32_t len, static int handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_setpurpose(connection_t *conn, int for_circuits, static int handle_control_setpurpose(control_connection_t *conn, int for_circuits,
uint32_t len, const char *body); uint32_t len, const char *body);
static int handle_control_attachstream(connection_t *conn, uint32_t len, static int handle_control_attachstream(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_postdescriptor(connection_t *conn, uint32_t len, static int handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_redirectstream(connection_t *conn, uint32_t len, static int handle_control_redirectstream(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_closestream(connection_t *conn, uint32_t len, static int handle_control_closestream(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int handle_control_closecircuit(connection_t *conn, uint32_t len, static int handle_control_closecircuit(control_connection_t *conn, uint32_t len,
const char *body); const char *body);
static int write_stream_target_to_buf(connection_t *conn, char *buf, static int write_stream_target_to_buf(edge_connection_t *conn, char *buf,
size_t len); size_t len);
/** Given a possibly invalid message type code <b>cmd</b>, return a /** Given a possibly invalid message type code <b>cmd</b>, return a
@ -235,10 +235,11 @@ control_update_global_event_mask(void)
for (i = 0; i < n_conns; ++i) { for (i = 0; i < n_conns; ++i) {
if (conns[i]->type == CONN_TYPE_CONTROL && if (conns[i]->type == CONN_TYPE_CONTROL &&
STATE_IS_OPEN(conns[i]->state)) { STATE_IS_OPEN(conns[i]->state)) {
if (STATE_IS_V0(conns[i]->state)) control_connection_t *conn = TO_CONTROL_CONN(conns[i]);
global_event_mask0 |= conns[i]->event_mask; if (STATE_IS_V0(conn->_base.state))
global_event_mask0 |= conn->event_mask;
else else
global_event_mask1 |= conns[i]->event_mask; global_event_mask1 |= conn->event_mask;
} }
} }
@ -281,10 +282,10 @@ control_adjust_event_log_severity(void)
* <b>conn</b>-\>outbuf * <b>conn</b>-\>outbuf
*/ */
static INLINE void static INLINE void
connection_write_str_to_buf(const char *s, connection_t *conn) connection_write_str_to_buf(const char *s, control_connection_t *conn)
{ {
size_t len = strlen(s); size_t len = strlen(s);
connection_write_to_buf(s, len, conn); connection_write_to_buf(s, len, TO_CONN(conn));
} }
/** Given a <b>len</b>-character string in <b>data</b>, made of lines /** Given a <b>len</b>-character string in <b>data</b>, made of lines
@ -446,7 +447,7 @@ get_escaped_string(const char *start, size_t in_len_max,
* Currently the length of the message is limited to 1024 (including the * Currently the length of the message is limited to 1024 (including the
* ending \n\r\0. */ * ending \n\r\0. */
static void static void
connection_printf_to_buf(connection_t *conn, const char *format, ...) connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
{ {
#define CONNECTION_PRINTF_TO_BUF_BUFFERSIZE 1024 #define CONNECTION_PRINTF_TO_BUF_BUFFERSIZE 1024
va_list ap; va_list ap;
@ -462,41 +463,41 @@ connection_printf_to_buf(connection_t *conn, const char *format, ...)
buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-2] = '\n'; buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-2] = '\n';
buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-3] = '\r'; buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-3] = '\r';
} }
connection_write_to_buf(buf, len, conn); connection_write_to_buf(buf, len, TO_CONN(conn));
} }
/** Send a message of type <b>type</b> containing <b>len</b> bytes /** Send a message of type <b>type</b> containing <b>len</b> bytes
* from <b>body</b> along the control connection <b>conn</b> */ * from <b>body</b> along the control connection <b>conn</b> */
static void static void
send_control0_message(connection_t *conn, uint16_t type, uint32_t len, send_control0_message(control_connection_t *conn, uint16_t type, uint32_t len,
const char *body) const char *body)
{ {
char buf[10]; char buf[10];
tor_assert(conn); tor_assert(conn);
tor_assert(STATE_IS_V0(conn->state)); tor_assert(STATE_IS_V0(conn->_base.state));
tor_assert(len || !body); tor_assert(len || !body);
tor_assert(type <= _CONTROL0_CMD_MAX_RECOGNIZED); tor_assert(type <= _CONTROL0_CMD_MAX_RECOGNIZED);
if (len < 65536) { if (len < 65536) {
set_uint16(buf, htons(len)); set_uint16(buf, htons(len));
set_uint16(buf+2, htons(type)); set_uint16(buf+2, htons(type));
connection_write_to_buf(buf, 4, conn); connection_write_to_buf(buf, 4, TO_CONN(conn));
if (len) if (len)
connection_write_to_buf(body, len, conn); connection_write_to_buf(body, len, TO_CONN(conn));
} else { } else {
set_uint16(buf, htons(65535)); set_uint16(buf, htons(65535));
set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENTHEADER)); set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENTHEADER));
set_uint16(buf+4, htons(type)); set_uint16(buf+4, htons(type));
set_uint32(buf+6, htonl(len)); set_uint32(buf+6, htonl(len));
connection_write_to_buf(buf, 10, conn); connection_write_to_buf(buf, 10, TO_CONN(conn));
connection_write_to_buf(body, 65535-6, conn); connection_write_to_buf(body, 65535-6, TO_CONN(conn));
len -= (65535-6); len -= (65535-6);
body += (65535-6); body += (65535-6);
while (len) { while (len) {
size_t chunklen = (len<65535)?len:65535; size_t chunklen = (len<65535)?len:65535;
set_uint16(buf, htons((uint16_t)chunklen)); set_uint16(buf, htons((uint16_t)chunklen));
set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENT)); set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENT));
connection_write_to_buf(buf, 4, conn); connection_write_to_buf(buf, 4, TO_CONN(conn));
connection_write_to_buf(body, chunklen, conn); connection_write_to_buf(body, chunklen, TO_CONN(conn));
len -= chunklen; len -= chunklen;
body += chunklen; body += chunklen;
} }
@ -505,9 +506,9 @@ send_control0_message(connection_t *conn, uint16_t type, uint32_t len,
/** Send a "DONE" message down the control connection <b>conn</b> */ /** Send a "DONE" message down the control connection <b>conn</b> */
static void static void
send_control_done(connection_t *conn) send_control_done(control_connection_t *conn)
{ {
if (STATE_IS_V0(conn->state)) { if (STATE_IS_V0(conn->_base.state)) {
send_control0_message(conn, CONTROL0_CMD_DONE, 0, NULL); send_control0_message(conn, CONTROL0_CMD_DONE, 0, NULL);
} else { } else {
connection_write_str_to_buf("250 OK\r\n", conn); connection_write_str_to_buf("250 OK\r\n", conn);
@ -518,7 +519,7 @@ send_control_done(connection_t *conn)
* as provided in the <b>len</b> bytes at <b>msg</b>. * as provided in the <b>len</b> bytes at <b>msg</b>.
*/ */
static void static void
send_control_done2(connection_t *conn, const char *msg, size_t len) send_control_done2(control_connection_t *conn, const char *msg, size_t len)
{ {
if (len==0) if (len==0)
len = strlen(msg); len = strlen(msg);
@ -528,7 +529,7 @@ send_control_done2(connection_t *conn, const char *msg, size_t len)
/** Send an error message with error code <b>error</b> and body /** Send an error message with error code <b>error</b> and body
* <b>message</b> down the connection <b>conn</b> */ * <b>message</b> down the connection <b>conn</b> */
static void static void
send_control0_error(connection_t *conn, uint16_t error, const char *message) send_control0_error(control_connection_t *conn, uint16_t error, const char *message)
{ {
char buf[256]; char buf[256];
size_t len; size_t len;
@ -561,11 +562,13 @@ send_control0_event(uint16_t event, uint32_t len, const char *body)
for (i = 0; i < n_conns; ++i) { for (i = 0; i < n_conns; ++i) {
if (conns[i]->type == CONN_TYPE_CONTROL && if (conns[i]->type == CONN_TYPE_CONTROL &&
!conns[i]->marked_for_close && !conns[i]->marked_for_close &&
conns[i]->state == CONTROL_CONN_STATE_OPEN_V0 && conns[i]->state == CONTROL_CONN_STATE_OPEN_V0) {
conns[i]->event_mask & (1<<event)) { control_connection_t *control_conn = TO_CONTROL_CONN(conns[i]);
send_control0_message(conns[i], CONTROL0_CMD_EVENT, buflen, buf); if (control_conn->event_mask & (1<<event)) {
if (event == EVENT_ERR_MSG) send_control0_message(control_conn, CONTROL0_CMD_EVENT, buflen, buf);
_connection_controller_force_write(conns[i]); if (event == EVENT_ERR_MSG)
_connection_controller_force_write(control_conn);
}
} }
} }
@ -586,11 +589,13 @@ send_control1_event_string(uint16_t event, const char *msg)
for (i = 0; i < n_conns; ++i) { for (i = 0; i < n_conns; ++i) {
if (conns[i]->type == CONN_TYPE_CONTROL && if (conns[i]->type == CONN_TYPE_CONTROL &&
!conns[i]->marked_for_close && !conns[i]->marked_for_close &&
conns[i]->state == CONTROL_CONN_STATE_OPEN_V1 && conns[i]->state == CONTROL_CONN_STATE_OPEN_V1) {
conns[i]->event_mask & (1<<event)) { control_connection_t *control_conn = TO_CONTROL_CONN(conns[i]);
connection_write_to_buf(msg, strlen(msg), conns[i]); if (control_conn->event_mask & (1<<event)) {
if (event == EVENT_ERR_MSG) connection_write_to_buf(msg, strlen(msg), TO_CONN(control_conn));
_connection_controller_force_write(conns[i]); if (event == EVENT_ERR_MSG)
_connection_controller_force_write(control_conn);
}
} }
} }
} }
@ -657,14 +662,14 @@ get_stream(const char *id)
* it passes <b>use_defaults</b> on to options_trial_assign(). * it passes <b>use_defaults</b> on to options_trial_assign().
*/ */
static int static int
control_setconf_helper(connection_t *conn, uint32_t len, char *body, control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
int use_defaults, int clear_first) int use_defaults, int clear_first)
{ {
int r; int r;
config_line_t *lines=NULL; config_line_t *lines=NULL;
char *start = body; char *start = body;
char *errstring = NULL; char *errstring = NULL;
int v0 = STATE_IS_V0(conn->state); int v0 = STATE_IS_V0(conn->_base.state);
if (!v0) { if (!v0) {
char *config = tor_malloc(len+1); char *config = tor_malloc(len+1);
@ -761,7 +766,7 @@ control_setconf_helper(connection_t *conn, uint32_t len, char *body,
/** Called when we receive a SETCONF message: parse the body and try /** Called when we receive a SETCONF message: parse the body and try
* to update our configuration. Reply with a DONE or ERROR message. */ * to update our configuration. Reply with a DONE or ERROR message. */
static int static int
handle_control_setconf(connection_t *conn, uint32_t len, char *body) handle_control_setconf(control_connection_t *conn, uint32_t len, char *body)
{ {
return control_setconf_helper(conn, len, body, 0, 1); return control_setconf_helper(conn, len, body, 0, 1);
} }
@ -769,9 +774,9 @@ handle_control_setconf(connection_t *conn, uint32_t len, char *body)
/** Called when we receive a RESETCONF message: parse the body and try /** Called when we receive a RESETCONF message: parse the body and try
* to update our configuration. Reply with a DONE or ERROR message. */ * to update our configuration. Reply with a DONE or ERROR message. */
static int static int
handle_control_resetconf(connection_t *conn, uint32_t len, char *body) handle_control_resetconf(control_connection_t *conn, uint32_t len, char *body)
{ {
int v0 = STATE_IS_V0(conn->state); int v0 = STATE_IS_V0(conn->_base.state);
tor_assert(!v0); tor_assert(!v0);
return control_setconf_helper(conn, len, body, 1, 1); return control_setconf_helper(conn, len, body, 1, 1);
} }
@ -779,7 +784,7 @@ handle_control_resetconf(connection_t *conn, uint32_t len, char *body)
/** Called when we receive a GETCONF message. Parse the request, and /** Called when we receive a GETCONF message. Parse the request, and
* reply with a CONFVALUE or an ERROR message */ * reply with a CONFVALUE or an ERROR message */
static int static int
handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body) handle_control_getconf(control_connection_t *conn, uint32_t body_len, const char *body)
{ {
smartlist_t *questions = NULL; smartlist_t *questions = NULL;
smartlist_t *answers = NULL; smartlist_t *answers = NULL;
@ -787,7 +792,7 @@ handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body)
char *msg = NULL; char *msg = NULL;
size_t msg_len; size_t msg_len;
or_options_t *options = get_options(); or_options_t *options = get_options();
int v0 = STATE_IS_V0(conn->state); int v0 = STATE_IS_V0(conn->_base.state);
questions = smartlist_create(); questions = smartlist_create();
(void) body_len; /* body is nul-terminated; so we can ignore len. */ (void) body_len; /* body is nul-terminated; so we can ignore len. */
@ -858,7 +863,7 @@ handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body)
tor_assert(strlen(tmp)>4); tor_assert(strlen(tmp)>4);
tmp[3] = ' '; tmp[3] = ' ';
msg = smartlist_join_strings(answers, "", 0, &msg_len); msg = smartlist_join_strings(answers, "", 0, &msg_len);
connection_write_to_buf(msg, msg_len, conn); connection_write_to_buf(msg, msg_len, TO_CONN(conn));
} else { } else {
connection_write_str_to_buf("250 OK\r\n", conn); connection_write_str_to_buf("250 OK\r\n", conn);
} }
@ -882,13 +887,13 @@ handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body)
/** Called when we get a SETEVENTS message: update conn->event_mask, /** Called when we get a SETEVENTS message: update conn->event_mask,
* and reply with DONE or ERROR. */ * and reply with DONE or ERROR. */
static int static int
handle_control_setevents(connection_t *conn, uint32_t len, const char *body) handle_control_setevents(control_connection_t *conn, uint32_t len, const char *body)
{ {
uint16_t event_code; uint16_t event_code;
uint32_t event_mask = 0; uint32_t event_mask = 0;
unsigned int extended = 0; unsigned int extended = 0;
if (STATE_IS_V0(conn->state)) { if (STATE_IS_V0(conn->_base.state)) {
if (len % 2) { if (len % 2) {
send_control0_error(conn, ERR_SYNTAX, send_control0_error(conn, ERR_SYNTAX,
"Odd number of bytes in setevents message"); "Odd number of bytes in setevents message");
@ -950,7 +955,7 @@ handle_control_setevents(connection_t *conn, uint32_t len, const char *body)
smartlist_free(events); smartlist_free(events);
} }
conn->event_mask = event_mask; conn->event_mask = event_mask;
conn->control_events_are_extended = extended; conn->_base.control_events_are_extended = extended;
control_update_global_event_mask(); control_update_global_event_mask();
send_control_done(conn); send_control_done(conn);
@ -987,13 +992,13 @@ decode_hashed_password(char *buf, const char *hashed)
* OPEN. Reply with DONE or ERROR. * OPEN. Reply with DONE or ERROR.
*/ */
static int static int
handle_control_authenticate(connection_t *conn, uint32_t len, const char *body) handle_control_authenticate(control_connection_t *conn, uint32_t len, const char *body)
{ {
int used_quoted_string = 0; int used_quoted_string = 0;
or_options_t *options = get_options(); or_options_t *options = get_options();
char *password; char *password;
size_t password_len; size_t password_len;
if (STATE_IS_V0(conn->state)) { if (STATE_IS_V0(conn->_base.state)) {
password = (char*)body; password = (char*)body;
password_len = len; password_len = len;
} else { } else {
@ -1047,7 +1052,7 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
} }
err: err:
if (STATE_IS_V0(conn->state)) if (STATE_IS_V0(conn->_base.state))
send_control0_error(conn,ERR_REJECTED_AUTHENTICATION, send_control0_error(conn,ERR_REJECTED_AUTHENTICATION,
"Authentication failed"); "Authentication failed");
else { else {
@ -1061,12 +1066,12 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
} }
return 0; return 0;
ok: ok:
log_info(LD_CONTROL, "Authenticated control connection (%d)", conn->s); log_info(LD_CONTROL, "Authenticated control connection (%d)", conn->_base.s);
send_control_done(conn); send_control_done(conn);
if (STATE_IS_V0(conn->state)) if (STATE_IS_V0(conn->_base.state))
conn->state = CONTROL_CONN_STATE_OPEN_V0; conn->_base.state = CONTROL_CONN_STATE_OPEN_V0;
else { else {
conn->state = CONTROL_CONN_STATE_OPEN_V1; conn->_base.state = CONTROL_CONN_STATE_OPEN_V1;
tor_free(password); tor_free(password);
} }
return 0; return 0;
@ -1075,13 +1080,13 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
/** Called when we get a SAVECONF command. Try to flush the current options to /** Called when we get a SAVECONF command. Try to flush the current options to
* disk, and report success or failure. */ * disk, and report success or failure. */
static int static int
handle_control_saveconf(connection_t *conn, uint32_t len, handle_control_saveconf(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
(void) len; (void) len;
(void) body; (void) body;
if (options_save_current()<0) { if (options_save_current()<0) {
if (STATE_IS_V0(conn->state)) if (STATE_IS_V0(conn->_base.state))
send_control0_error(conn, ERR_INTERNAL, send_control0_error(conn, ERR_INTERNAL,
"Unable to write configuration to disk."); "Unable to write configuration to disk.");
else else
@ -1097,11 +1102,11 @@ handle_control_saveconf(connection_t *conn, uint32_t len,
* report success or failure. (If the signal results in a shutdown, success * report success or failure. (If the signal results in a shutdown, success
* may not be reported.) */ * may not be reported.) */
static int static int
handle_control_signal(connection_t *conn, uint32_t len, handle_control_signal(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
int sig; int sig;
if (STATE_IS_V0(conn->state)) { if (STATE_IS_V0(conn->_base.state)) {
if (len != 1) { if (len != 1) {
send_control0_error(conn, ERR_SYNTAX, send_control0_error(conn, ERR_SYNTAX,
"Body of SIGNAL command too long or too short."); "Body of SIGNAL command too long or too short.");
@ -1138,7 +1143,7 @@ handle_control_signal(connection_t *conn, uint32_t len,
} }
if (control_signal_act(sig) < 0) { if (control_signal_act(sig) < 0) {
if (STATE_IS_V0(conn->state)) if (STATE_IS_V0(conn->_base.state))
send_control0_error(conn, ERR_SYNTAX, "Unrecognized signal number."); send_control0_error(conn, ERR_SYNTAX, "Unrecognized signal number.");
else else
connection_write_str_to_buf("551 Internal error acting on signal\r\n", connection_write_str_to_buf("551 Internal error acting on signal\r\n",
@ -1152,14 +1157,14 @@ handle_control_signal(connection_t *conn, uint32_t len,
/** Called when we get a MAPADDRESS command; try to bind all listed addresses, /** Called when we get a MAPADDRESS command; try to bind all listed addresses,
* and report success or failrue. */ * and report success or failrue. */
static int static int
handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body) handle_control_mapaddress(control_connection_t *conn, uint32_t len, const char *body)
{ {
smartlist_t *elts; smartlist_t *elts;
smartlist_t *lines; smartlist_t *lines;
smartlist_t *reply; smartlist_t *reply;
char *r; char *r;
size_t sz; size_t sz;
int v0 = STATE_IS_V0(conn->state); int v0 = STATE_IS_V0(conn->_base.state);
(void) len; /* body is nul-terminated, so it's safe to ignore the length. */ (void) len; /* body is nul-terminated, so it's safe to ignore the length. */
lines = smartlist_create(); lines = smartlist_create();
@ -1257,12 +1262,12 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body)
if (smartlist_len(reply)) { if (smartlist_len(reply)) {
((char*)smartlist_get(reply,smartlist_len(reply)-1))[3] = ' '; ((char*)smartlist_get(reply,smartlist_len(reply)-1))[3] = ' ';
r = smartlist_join_strings(reply, "\r\n", 1, &sz); r = smartlist_join_strings(reply, "\r\n", 1, &sz);
connection_write_to_buf(r, sz, conn); connection_write_to_buf(r, sz, TO_CONN(conn));
tor_free(r); tor_free(r);
} else { } else {
const char *response = const char *response =
"512 syntax error: not enough arguments to mapaddress.\r\n"; "512 syntax error: not enough arguments to mapaddress.\r\n";
connection_write_to_buf(response, strlen(response), conn); connection_write_to_buf(response, strlen(response), TO_CONN(conn));
} }
} }
@ -1399,6 +1404,7 @@ handle_getinfo_helper(const char *question, char **answer)
get_connection_array(&conns, &n_conns); get_connection_array(&conns, &n_conns);
for (i=0; i < n_conns; ++i) { for (i=0; i < n_conns; ++i) {
const char *state; const char *state;
edge_connection_t *conn;
char *s; char *s;
size_t slen; size_t slen;
circuit_t *circ; circuit_t *circ;
@ -1406,12 +1412,13 @@ handle_getinfo_helper(const char *question, char **answer)
conns[i]->marked_for_close || conns[i]->marked_for_close ||
conns[i]->state == AP_CONN_STATE_SOCKS_WAIT) conns[i]->state == AP_CONN_STATE_SOCKS_WAIT)
continue; continue;
switch (conns[i]->state) conn = TO_EDGE_CONN(conns[i]);
switch (conn->_base.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:
if (conns[i]->socks_request && if (conn->socks_request &&
conns[i]->socks_request->command == SOCKS_COMMAND_RESOLVE) conn->socks_request->command == SOCKS_COMMAND_RESOLVE)
state = "NEWRESOLVE"; state = "NEWRESOLVE";
else else
state = "NEW"; state = "NEW";
@ -1425,15 +1432,15 @@ handle_getinfo_helper(const char *question, char **answer)
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",
conns[i]->state); conn->_base.state);
continue; continue;
} }
circ = circuit_get_by_edge_conn(conns[i]); circ = circuit_get_by_edge_conn(conn);
write_stream_target_to_buf(conns[i], 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) conns[i]->global_identifier,state, (unsigned long) conn->_base.global_identifier,state,
circ?(unsigned long)circ->global_identifier : 0ul, circ?(unsigned long)circ->global_identifier : 0ul,
buf); buf);
smartlist_add(status, s); smartlist_add(status, s);
@ -1451,10 +1458,11 @@ handle_getinfo_helper(const char *question, char **answer)
char *s; char *s;
char name[128]; char name[128];
size_t slen; size_t slen;
connection_t *conn = conns[i]; or_connection_t *conn;
if (conn->type != CONN_TYPE_OR || conn->marked_for_close) if (conns[i]->type != CONN_TYPE_OR || conns[i]->marked_for_close)
continue; continue;
if (conn->state == OR_CONN_STATE_OPEN) conn = TO_OR_CONN(conns[i]);
if (conn->_base.state == OR_CONN_STATE_OPEN)
state = "CONNECTED"; state = "CONNECTED";
else if (conn->nickname) else if (conn->nickname)
state = "LAUNCHED"; state = "LAUNCHED";
@ -1464,7 +1472,7 @@ handle_getinfo_helper(const char *question, char **answer)
strlcpy(name, conn->nickname, sizeof(name)); strlcpy(name, conn->nickname, sizeof(name));
else else
tor_snprintf(name, sizeof(name), "%s:%d", tor_snprintf(name, sizeof(name), "%s:%d",
conn->address, conn->port); conn->_base.address, conn->_base.port);
slen = strlen(name)+strlen(state)+2; slen = strlen(name)+strlen(state)+2;
s = tor_malloc(slen+1); s = tor_malloc(slen+1);
@ -1544,14 +1552,14 @@ handle_getinfo_helper(const char *question, char **answer)
/** Called when we receive a GETINFO command. Try to fetch all requested /** Called when we receive a GETINFO command. Try to fetch all requested
* information, and reply with information or error message. */ * information, and reply with information or error message. */
static int static int
handle_control_getinfo(connection_t *conn, uint32_t len, const char *body) handle_control_getinfo(control_connection_t *conn, uint32_t len, const char *body)
{ {
smartlist_t *questions = NULL; smartlist_t *questions = NULL;
smartlist_t *answers = NULL; smartlist_t *answers = NULL;
smartlist_t *unrecognized = NULL; smartlist_t *unrecognized = NULL;
char *msg = NULL, *ans = NULL; char *msg = NULL, *ans = NULL;
size_t msg_len; size_t msg_len;
int v0 = STATE_IS_V0(conn->state); int v0 = STATE_IS_V0(conn->_base.state);
(void) len; /* body is nul-terminated, so it's safe to ignore the length. */ (void) len; /* body is nul-terminated, so it's safe to ignore the length. */
questions = smartlist_create(); questions = smartlist_create();
@ -1615,7 +1623,7 @@ handle_control_getinfo(connection_t *conn, uint32_t len, const char *body)
size_t len; size_t len;
len = write_escaped_data(v, strlen(v), 1, &esc); len = write_escaped_data(v, strlen(v), 1, &esc);
connection_printf_to_buf(conn, "250+%s=\r\n", k); connection_printf_to_buf(conn, "250+%s=\r\n", k);
connection_write_to_buf(esc, len, conn); connection_write_to_buf(esc, len, TO_CONN(conn));
tor_free(esc); tor_free(esc);
} }
} }
@ -1662,7 +1670,7 @@ get_purpose(char *string, int for_circuits, uint8_t *purpose)
/** Called when we get an EXTENDCIRCUIT message. Try to extend the listed /** Called when we get an EXTENDCIRCUIT message. Try to extend the listed
* circuit, and report success or failure. */ * circuit, and report success or failure. */
static int static int
handle_control_extendcircuit(connection_t *conn, uint32_t len, handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
smartlist_t *router_nicknames=NULL, *routers=NULL; smartlist_t *router_nicknames=NULL, *routers=NULL;
@ -1672,7 +1680,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
char reply[4]; char reply[4];
uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL; uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
v0 = STATE_IS_V0(conn->state); v0 = STATE_IS_V0(conn->_base.state);
router_nicknames = smartlist_create(); router_nicknames = smartlist_create();
if (v0) { if (v0) {
@ -1816,7 +1824,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
* is 1) or SETROUTERPURPOSE message. If we can find * is 1) or SETROUTERPURPOSE message. If we can find
* the circuit/router and it's a valid purpose, change it. */ * the circuit/router and it's a valid purpose, change it. */
static int static int
handle_control_setpurpose(connection_t *conn, int for_circuits, handle_control_setpurpose(control_connection_t *conn, int for_circuits,
uint32_t len, const char *body) uint32_t len, const char *body)
{ {
circuit_t *circ = NULL; circuit_t *circ = NULL;
@ -1868,14 +1876,15 @@ done:
/** Called when we get an ATTACHSTREAM message. Try to attach the requested /** Called when we get an ATTACHSTREAM message. Try to attach the requested
* stream, and report success or failure. */ * stream, and report success or failure. */
static int static int
handle_control_attachstream(connection_t *conn, uint32_t len, handle_control_attachstream(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
connection_t *ap_conn = NULL; connection_t *ap_conn = NULL;
circuit_t *circ = NULL; circuit_t *circ = NULL;
int zero_circ; int zero_circ;
edge_connection_t *edge_conn;
if (STATE_IS_V0(conn->state)) { if (STATE_IS_V0(conn->_base.state)) {
uint32_t conn_id; uint32_t conn_id;
uint32_t circ_id; uint32_t circ_id;
if (len < 8) { if (len < 8) {
@ -1927,7 +1936,7 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT && if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT &&
ap_conn->state != AP_CONN_STATE_CONNECT_WAIT && ap_conn->state != AP_CONN_STATE_CONNECT_WAIT &&
ap_conn->state != AP_CONN_STATE_RESOLVE_WAIT) { ap_conn->state != AP_CONN_STATE_RESOLVE_WAIT) {
if (STATE_IS_V0(conn->state)) { if (STATE_IS_V0(conn->_base.state)) {
send_control0_error(conn, ERR_NO_STREAM, send_control0_error(conn, ERR_NO_STREAM,
"Connection is not managed by controller."); "Connection is not managed by controller.");
} else { } else {
@ -1938,20 +1947,23 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
return 0; return 0;
} }
edge_conn = TO_EDGE_CONN(ap_conn);
/* Do we need to detach it first? */ /* Do we need to detach it first? */
if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT) { if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT) {
circuit_t *tmpcirc = circuit_get_by_edge_conn(ap_conn); circuit_t *tmpcirc = circuit_get_by_edge_conn(edge_conn);
connection_edge_end(ap_conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer); connection_edge_end(edge_conn, END_STREAM_REASON_TIMEOUT,
edge_conn->cpath_layer);
/* 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->has_sent_end = 0; ap_conn->edge_has_sent_end = 0;
if (tmpcirc) if (tmpcirc)
circuit_detach_stream(tmpcirc,ap_conn); circuit_detach_stream(tmpcirc,edge_conn);
ap_conn->state = AP_CONN_STATE_CONTROLLER_WAIT; ap_conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
} }
if (circ && if (circ &&
(circ->state != CIRCUIT_STATE_OPEN || ! CIRCUIT_IS_ORIGIN(circ))) { (circ->state != CIRCUIT_STATE_OPEN || ! CIRCUIT_IS_ORIGIN(circ))) {
if (STATE_IS_V0(conn->state)) if (STATE_IS_V0(conn->_base.state))
send_control0_error(conn, ERR_INTERNAL, send_control0_error(conn, ERR_INTERNAL,
"Refuse to attach stream to non-open, origin circ."); "Refuse to attach stream to non-open, origin circ.");
else else
@ -1960,9 +1972,9 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
conn); conn);
return 0; return 0;
} }
if (connection_ap_handshake_rewrite_and_attach(ap_conn, if (connection_ap_handshake_rewrite_and_attach(edge_conn,
circ ? TO_ORIGIN_CIRCUIT(circ) : NULL) < 0) { circ ? TO_ORIGIN_CIRCUIT(circ) : NULL) < 0) {
if (STATE_IS_V0(conn->state)) if (STATE_IS_V0(conn->_base.state))
send_control0_error(conn, ERR_INTERNAL, "Unable to attach stream."); send_control0_error(conn, ERR_INTERNAL, "Unable to attach stream.");
else else
connection_write_str_to_buf("551 Unable to attach stream\r\n", conn); connection_write_str_to_buf("551 Unable to attach stream\r\n", conn);
@ -1975,11 +1987,11 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
/** Called when we get a POSTDESCRIPTOR message. Try to learn the provided /** Called when we get a POSTDESCRIPTOR message. Try to learn the provided
* descriptor, and report success or failure. */ * descriptor, and report success or failure. */
static int static int
handle_control_postdescriptor(connection_t *conn, uint32_t len, handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
char *desc; char *desc;
int v0 = STATE_IS_V0(conn->state); int v0 = STATE_IS_V0(conn->_base.state);
const char *msg=NULL; const char *msg=NULL;
uint8_t purpose = ROUTER_PURPOSE_GENERAL; uint8_t purpose = ROUTER_PURPOSE_GENERAL;
@ -2034,14 +2046,14 @@ handle_control_postdescriptor(connection_t *conn, uint32_t len,
/** Called when we receive a REDIRECTSTERAM command. Try to change the target /** Called when we receive a REDIRECTSTERAM command. Try to change the target
* address of the named AP stream, and report success or failure. */ * address of the named AP stream, and report success or failure. */
static int static int
handle_control_redirectstream(connection_t *conn, uint32_t len, handle_control_redirectstream(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
connection_t *ap_conn = NULL; connection_t *ap_conn = NULL;
uint32_t conn_id; uint32_t conn_id;
char *new_addr = NULL; char *new_addr = NULL;
uint16_t new_port = 0; uint16_t new_port = 0;
if (STATE_IS_V0(conn->state)) { if (STATE_IS_V0(conn->_base.state)) {
if (len < 6) { if (len < 6) {
send_control0_error(conn, ERR_SYNTAX, send_control0_error(conn, ERR_SYNTAX,
"redirectstream message too short"); "redirectstream message too short");
@ -2051,7 +2063,7 @@ handle_control_redirectstream(connection_t *conn, uint32_t len,
if (!(ap_conn = connection_get_by_global_id(conn_id)) if (!(ap_conn = connection_get_by_global_id(conn_id))
|| ap_conn->state != CONN_TYPE_AP || ap_conn->state != CONN_TYPE_AP
|| !ap_conn->socks_request) { || !TO_EDGE_CONN(ap_conn)->socks_request) {
send_control0_error(conn, ERR_NO_STREAM, send_control0_error(conn, ERR_NO_STREAM,
"No AP connection found with given ID"); "No AP connection found with given ID");
return 0; return 0;
@ -2066,7 +2078,7 @@ handle_control_redirectstream(connection_t *conn, uint32_t len,
connection_printf_to_buf(conn, connection_printf_to_buf(conn,
"512 Missing argument to REDIRECTSTREAM\r\n"); "512 Missing argument to REDIRECTSTREAM\r\n");
else if (!(ap_conn = get_stream(smartlist_get(args, 0))) else if (!(ap_conn = get_stream(smartlist_get(args, 0)))
|| !ap_conn->socks_request) { || !TO_EDGE_CONN(ap_conn)->socks_request) {
connection_printf_to_buf(conn, "552 Unknown stream \"%s\"\r\n", connection_printf_to_buf(conn, "552 Unknown stream \"%s\"\r\n",
(char*)smartlist_get(args, 0)); (char*)smartlist_get(args, 0));
} else { } else {
@ -2089,25 +2101,28 @@ handle_control_redirectstream(connection_t *conn, uint32_t len,
return 0; return 0;
} }
strlcpy(ap_conn->socks_request->address, new_addr, {
sizeof(ap_conn->socks_request->address)); edge_connection_t *ap = TO_EDGE_CONN(ap_conn);
if (new_port) strlcpy(ap->socks_request->address, new_addr,
ap_conn->socks_request->port = new_port; sizeof(ap->socks_request->address));
tor_free(new_addr); if (new_port)
send_control_done(conn); ap->socks_request->port = new_port;
return 0; tor_free(new_addr);
send_control_done(conn);
return 0;
}
} }
/** Called when we get a CLOSESTREAM command; try to close the named stream /** Called when we get a CLOSESTREAM command; try to close the named stream
* and report success or failure. */ * and report success or failure. */
static int static int
handle_control_closestream(connection_t *conn, uint32_t len, handle_control_closestream(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
connection_t *ap_conn=NULL; connection_t *ap_conn=NULL;
uint8_t reason=0; uint8_t reason=0;
if (STATE_IS_V0(conn->state)) { if (STATE_IS_V0(conn->_base.state)) {
uint32_t conn_id; uint32_t conn_id;
if (len < 6) { if (len < 6) {
send_control0_error(conn, ERR_SYNTAX, "closestream message too short"); send_control0_error(conn, ERR_SYNTAX, "closestream message too short");
@ -2119,7 +2134,7 @@ handle_control_closestream(connection_t *conn, uint32_t len,
if (!(ap_conn = connection_get_by_global_id(conn_id)) if (!(ap_conn = connection_get_by_global_id(conn_id))
|| ap_conn->state != CONN_TYPE_AP || ap_conn->state != CONN_TYPE_AP
|| !ap_conn->socks_request) { || !TO_EDGE_CONN(ap_conn)->socks_request) {
send_control0_error(conn, ERR_NO_STREAM, send_control0_error(conn, ERR_NO_STREAM,
"No AP connection found with given ID"); "No AP connection found with given ID");
return 0; return 0;
@ -2151,7 +2166,7 @@ handle_control_closestream(connection_t *conn, uint32_t len,
return 0; return 0;
} }
connection_mark_unattached_ap(ap_conn, reason); connection_mark_unattached_ap(TO_EDGE_CONN(ap_conn), reason);
send_control_done(conn); send_control_done(conn);
return 0; return 0;
} }
@ -2159,13 +2174,13 @@ handle_control_closestream(connection_t *conn, uint32_t len,
/** Called when we get a CLOSECIRCUIT command; try to close the named circuit /** Called when we get a CLOSECIRCUIT command; try to close the named circuit
* and report success or failure. */ * and report success or failure. */
static int static int
handle_control_closecircuit(connection_t *conn, uint32_t len, handle_control_closecircuit(control_connection_t *conn, uint32_t len,
const char *body) const char *body)
{ {
circuit_t *circ = NULL; circuit_t *circ = NULL;
int safe = 0; int safe = 0;
if (STATE_IS_V0(conn->state)) { if (STATE_IS_V0(conn->_base.state)) {
uint32_t circ_id; uint32_t circ_id;
if (len < 5) { if (len < 5) {
send_control0_error(conn, ERR_SYNTAX, "closecircuit message too short"); send_control0_error(conn, ERR_SYNTAX, "closecircuit message too short");
@ -2221,7 +2236,7 @@ handle_control_closecircuit(connection_t *conn, uint32_t len,
* fragments and report failure. * fragments and report failure.
*/ */
static int static int
handle_control_fragments(connection_t *conn, uint16_t command_type, handle_control_fragments(control_connection_t *conn, uint16_t command_type,
uint32_t body_len, char *body) uint32_t body_len, char *body)
{ {
if (command_type == CONTROL0_CMD_FRAGMENTHEADER) { if (command_type == CONTROL0_CMD_FRAGMENTHEADER) {
@ -2262,24 +2277,22 @@ handle_control_fragments(connection_t *conn, uint16_t command_type,
/** Called when <b>conn</b> has no more bytes left on its outbuf. */ /** Called when <b>conn</b> has no more bytes left on its outbuf. */
int int
connection_control_finished_flushing(connection_t *conn) connection_control_finished_flushing(control_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CONTROL);
connection_stop_writing(conn); connection_stop_writing(TO_CONN(conn));
return 0; return 0;
} }
/** Called when <b>conn</b> has gotten its socket closed. */ /** Called when <b>conn</b> has gotten its socket closed. */
int int
connection_control_reached_eof(connection_t *conn) connection_control_reached_eof(control_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CONTROL);
log_info(LD_CONTROL,"Control connection reached EOF. Closing."); log_info(LD_CONTROL,"Control connection reached EOF. Closing.");
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return 0; return 0;
} }
@ -2287,16 +2300,15 @@ connection_control_reached_eof(connection_t *conn)
* commands from conn->inbuf, and execute them. * commands from conn->inbuf, and execute them.
*/ */
static int static int
connection_control_process_inbuf_v1(connection_t *conn) connection_control_process_inbuf_v1(control_connection_t *conn)
{ {
size_t data_len; size_t data_len;
int cmd_len; int cmd_len;
char *args; char *args;
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CONTROL); tor_assert(conn->_base.state == CONTROL_CONN_STATE_OPEN_V1 ||
tor_assert(conn->state == CONTROL_CONN_STATE_OPEN_V1 || conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1);
conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1);
if (!conn->incoming_cmd) { if (!conn->incoming_cmd) {
conn->incoming_cmd = tor_malloc(1024); conn->incoming_cmd = tor_malloc(1024);
@ -2311,7 +2323,7 @@ connection_control_process_inbuf_v1(connection_t *conn)
/* First, fetch a line. */ /* First, fetch a line. */
do { do {
data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len; data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
r = fetch_from_buf_line(conn->inbuf, r = fetch_from_buf_line(conn->_base.inbuf,
conn->incoming_cmd+conn->incoming_cmd_cur_len, conn->incoming_cmd+conn->incoming_cmd_cur_len,
&data_len); &data_len);
if (r == 0) if (r == 0)
@ -2361,11 +2373,11 @@ connection_control_process_inbuf_v1(connection_t *conn)
if (!strcasecmp(conn->incoming_cmd, "QUIT")) { if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
connection_write_str_to_buf("250 closing connection\r\n", conn); connection_write_str_to_buf("250 closing connection\r\n", conn);
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return 0; return 0;
} }
if (conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1 && if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1 &&
strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) { strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) {
connection_write_str_to_buf("514 Authentication required.\r\n", conn); connection_write_str_to_buf("514 Authentication required.\r\n", conn);
conn->incoming_cmd_cur_len = 0; conn->incoming_cmd_cur_len = 0;
@ -2436,7 +2448,7 @@ connection_control_process_inbuf_v1(connection_t *conn)
* commands from conn->inbuf, and execute them. * commands from conn->inbuf, and execute them.
*/ */
static int static int
connection_control_process_inbuf_v0(connection_t *conn) connection_control_process_inbuf_v0(control_connection_t *conn)
{ {
uint32_t body_len; uint32_t body_len;
uint16_t command_type; uint16_t command_type;
@ -2444,15 +2456,15 @@ connection_control_process_inbuf_v0(connection_t *conn)
again: again:
/* Try to suck a control message from the buffer. */ /* Try to suck a control message from the buffer. */
switch (fetch_from_buf_control0(conn->inbuf, &body_len, &command_type, &body, switch (fetch_from_buf_control0(conn->_base.inbuf, &body_len, &command_type, &body,
conn->state == CONTROL_CONN_STATE_NEEDAUTH_V0)) conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V0))
{ {
case -2: case -2:
tor_free(body); tor_free(body);
log_info(LD_CONTROL, log_info(LD_CONTROL,
"Detected v1 control protocol on connection (fd %d)", "Detected v1 control protocol on connection (fd %d)",
conn->s); conn->_base.s);
conn->state = CONTROL_CONN_STATE_NEEDAUTH_V1; conn->_base.state = CONTROL_CONN_STATE_NEEDAUTH_V1;
return connection_control_process_inbuf_v1(conn); return connection_control_process_inbuf_v1(conn);
case -1: case -1:
tor_free(body); tor_free(body);
@ -2470,7 +2482,7 @@ connection_control_process_inbuf_v0(connection_t *conn)
/* We got a command. If we need authentication, only authentication /* We got a command. If we need authentication, only authentication
* commands will be considered. */ * commands will be considered. */
if (conn->state == CONTROL_CONN_STATE_NEEDAUTH_V0 && if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V0 &&
command_type != CONTROL0_CMD_AUTHENTICATE) { command_type != CONTROL0_CMD_AUTHENTICATE) {
log_info(LD_CONTROL, "Rejecting '%s' command; authentication needed.", log_info(LD_CONTROL, "Rejecting '%s' command; authentication needed.",
control_cmd_to_string(command_type)); control_cmd_to_string(command_type));
@ -2584,12 +2596,11 @@ connection_control_process_inbuf_v0(connection_t *conn)
/** Called when <b>conn</b> has received more bytes on its inbuf. /** Called when <b>conn</b> has received more bytes on its inbuf.
*/ */
int int
connection_control_process_inbuf(connection_t *conn) connection_control_process_inbuf(control_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CONTROL);
if (STATE_IS_V0(conn->state)) if (STATE_IS_V0(conn->_base.state))
return connection_control_process_inbuf_v0(conn); return connection_control_process_inbuf_v0(conn);
else else
return connection_control_process_inbuf_v1(conn); return connection_control_process_inbuf_v1(conn);
@ -2644,7 +2655,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(connection_t *conn, char *buf, size_t len) write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
{ {
char buf2[256]; char buf2[256];
if (conn->chosen_exit_name) if (conn->chosen_exit_name)
@ -2663,12 +2674,11 @@ write_stream_target_to_buf(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(connection_t *conn, stream_status_event_t tp) control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp)
{ {
char *msg; char *msg;
size_t len; size_t len;
char buf[256]; char buf[256];
tor_assert(conn->type == CONN_TYPE_AP);
tor_assert(conn->socks_request); tor_assert(conn->socks_request);
if (!EVENT_IS_INTERESTING(EVENT_STREAM_STATUS)) if (!EVENT_IS_INTERESTING(EVENT_STREAM_STATUS))
@ -2679,7 +2689,7 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp)
len = strlen(buf); len = strlen(buf);
msg = tor_malloc(5+len+1); msg = tor_malloc(5+len+1);
msg[0] = (uint8_t) tp; msg[0] = (uint8_t) tp;
set_uint32(msg+1, htonl(conn->global_identifier)); set_uint32(msg+1, htonl(conn->_base.global_identifier));
strlcpy(msg+5, buf, len+1); strlcpy(msg+5, buf, len+1);
send_control0_event(EVENT_STREAM_STATUS, (uint32_t)(5+len+1), msg); send_control0_event(EVENT_STREAM_STATUS, (uint32_t)(5+len+1), msg);
@ -2705,7 +2715,7 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp)
circ = circuit_get_by_edge_conn(conn); circ = circuit_get_by_edge_conn(conn);
send_control1_event(EVENT_STREAM_STATUS, send_control1_event(EVENT_STREAM_STATUS,
"650 STREAM %lu %s %lu %s\r\n", "650 STREAM %lu %s %lu %s\r\n",
(unsigned long)conn->global_identifier, status, (unsigned long)conn->_base.global_identifier, status,
circ?(unsigned long)circ->global_identifier : 0ul, circ?(unsigned long)circ->global_identifier : 0ul,
buf); buf);
/* XXX need to specify its intended exit, etc? */ /* XXX need to specify its intended exit, etc? */
@ -2716,13 +2726,11 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp)
/** Something has happened to the OR connection <b>conn</b>: tell any /** Something has happened to the OR connection <b>conn</b>: tell any
* interested control connections. */ * interested control connections. */
int int
control_event_or_conn_status(connection_t *conn,or_conn_status_event_t tp) control_event_or_conn_status(or_connection_t *conn,or_conn_status_event_t tp)
{ {
char buf[HEX_DIGEST_LEN+3]; /* status, dollar, identity, NUL */ char buf[HEX_DIGEST_LEN+3]; /* status, dollar, identity, NUL */
size_t len; size_t len;
tor_assert(conn->type == CONN_TYPE_OR);
if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS)) if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS))
return 0; return 0;
@ -2739,7 +2747,7 @@ control_event_or_conn_status(connection_t *conn,or_conn_status_event_t tp)
strlcpy(name, conn->nickname, sizeof(name)); strlcpy(name, conn->nickname, sizeof(name));
else else
tor_snprintf(name, sizeof(name), "%s:%d", tor_snprintf(name, sizeof(name), "%s:%d",
conn->address, conn->port); conn->_base.address, conn->_base.port);
switch (tp) switch (tp)
{ {
case OR_CONN_EVENT_LAUNCHED: status = "LAUNCHED"; break; case OR_CONN_EVENT_LAUNCHED: status = "LAUNCHED"; break;

View file

@ -137,7 +137,7 @@ connection_cpu_process_inbuf(connection_t *conn)
uint32_t addr; uint32_t addr;
uint16_t port; uint16_t port;
uint16_t circ_id; uint16_t circ_id;
connection_t *p_conn; or_connection_t *p_conn;
circuit_t *circ; circuit_t *circ;
tor_assert(conn); tor_assert(conn);
@ -473,7 +473,8 @@ assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
log_info(LD_OR,"circ->p_conn gone. Failing circ."); log_info(LD_OR,"circ->p_conn gone. Failing circ.");
return -1; return -1;
} }
tag_pack(tag, circ->p_conn->addr, circ->p_conn->port, circ->p_circ_id); tag_pack(tag, circ->p_conn->_base.addr, circ->p_conn->_base.port,
circ->p_circ_id);
cpuworker->state = CPUWORKER_STATE_BUSY_ONION; cpuworker->state = CPUWORKER_STATE_BUSY_ONION;
/* touch the lastwritten timestamp, since that's how we check to /* touch the lastwritten timestamp, since that's how we check to

View file

@ -38,16 +38,16 @@ directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
const char *payload, size_t payload_len); const char *payload, size_t payload_len);
static void static void
directory_send_command(connection_t *conn, const char *platform, directory_send_command(dir_connection_t *conn, const char *platform,
int purpose, const char *resource, int purpose, const char *resource,
const char *payload, size_t payload_len); const char *payload, size_t payload_len);
static int directory_handle_command(connection_t *conn); static int directory_handle_command(dir_connection_t *conn);
static int body_is_plausible(const char *body, size_t body_len, int purpose); static int body_is_plausible(const char *body, size_t body_len, int purpose);
static int purpose_is_private(uint8_t purpose); static int purpose_is_private(uint8_t purpose);
static char *http_get_header(const char *headers, const char *which); static char *http_get_header(const char *headers, const char *which);
static void http_set_address_origin(const char *headers, connection_t *conn); static void http_set_address_origin(const char *headers, connection_t *conn);
static void connection_dir_download_networkstatus_failed(connection_t *conn); static void connection_dir_download_networkstatus_failed(dir_connection_t *conn);
static void connection_dir_download_routerdesc_failed(connection_t *conn); static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
static void dir_networkstatus_download_failed(smartlist_t *failed); static void dir_networkstatus_download_failed(smartlist_t *failed);
static void dir_routerdesc_download_failed(smartlist_t *failed); static void dir_routerdesc_download_failed(smartlist_t *failed);
static void note_request(const char *key, size_t bytes); static void note_request(const char *key, size_t bytes);
@ -261,24 +261,24 @@ directory_initiate_command_routerstatus(routerstatus_t *status,
* directory server: Mark the router as down and try again if possible. * directory server: Mark the router as down and try again if possible.
*/ */
void void
connection_dir_request_failed(connection_t *conn) connection_dir_request_failed(dir_connection_t *conn)
{ {
if (router_digest_is_me(conn->identity_digest)) if (router_digest_is_me(conn->identity_digest))
return; /* this was a test fetch. don't retry. */ return; /* this was a test fetch. don't retry. */
router_set_status(conn->identity_digest, 0); /* don't try him again */ router_set_status(conn->identity_digest, 0); /* don't try him again */
if (conn->purpose == DIR_PURPOSE_FETCH_DIR || if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR ||
conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) { conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying", log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying",
conn->address, conn->port); conn->_base.address, conn->_base.port);
directory_get_from_dirserver(conn->purpose, NULL, directory_get_from_dirserver(conn->_base.purpose, NULL,
0 /* don't retry_if_no_servers */); 0 /* don't retry_if_no_servers */);
} else if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) { } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying", log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
conn->address); conn->_base.address);
connection_dir_download_networkstatus_failed(conn); connection_dir_download_networkstatus_failed(conn);
} else if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) { } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying", log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
conn->address); conn->_base.address);
connection_dir_download_routerdesc_failed(conn); connection_dir_download_routerdesc_failed(conn);
} }
} }
@ -288,7 +288,7 @@ connection_dir_request_failed(connection_t *conn)
* retry the fetch now, later, or never. * retry the fetch now, later, or never.
*/ */
static void static void
connection_dir_download_networkstatus_failed(connection_t *conn) connection_dir_download_networkstatus_failed(dir_connection_t *conn)
{ {
if (!conn->requested_resource) { if (!conn->requested_resource) {
/* We never reached directory_send_command, which means that we never /* We never reached directory_send_command, which means that we never
@ -301,7 +301,7 @@ connection_dir_download_networkstatus_failed(connection_t *conn)
smartlist_t *trusted_dirs = router_get_trusted_dir_servers(); smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds, SMARTLIST_FOREACH(trusted_dirs, trusted_dir_server_t *, ds,
++ds->n_networkstatus_failures); ++ds->n_networkstatus_failures);
directory_get_from_dirserver(conn->purpose, "all.z", directory_get_from_dirserver(conn->_base.purpose, "all.z",
0 /* don't retry_if_no_servers */); 0 /* don't retry_if_no_servers */);
} else if (!strcmpstart(conn->requested_resource, "fp/")) { } else if (!strcmpstart(conn->requested_resource, "fp/")) {
/* We were trying to download by fingerprint; mark them all as having /* We were trying to download by fingerprint; mark them all as having
@ -321,7 +321,7 @@ connection_dir_download_networkstatus_failed(connection_t *conn)
* on connection <b>conn</b> failed. * on connection <b>conn</b> failed.
*/ */
static void static void
connection_dir_download_routerdesc_failed(connection_t *conn) connection_dir_download_routerdesc_failed(dir_connection_t *conn)
{ {
/* Try again. No need to increment the failure count for routerdescs, since /* Try again. No need to increment the failure count for routerdescs, since
* it's not their fault.*/ * it's not their fault.*/
@ -342,7 +342,7 @@ directory_initiate_command(const char *address, uint32_t addr,
int private_connection, const char *resource, int private_connection, const char *resource,
const char *payload, size_t payload_len) const char *payload, size_t payload_len)
{ {
connection_t *conn; dir_connection_t *conn;
tor_assert(address); tor_assert(address);
tor_assert(addr); tor_assert(addr);
@ -376,18 +376,18 @@ directory_initiate_command(const char *address, uint32_t addr,
tor_assert(0); tor_assert(0);
} }
conn = connection_new(CONN_TYPE_DIR); conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR));
/* set up conn so it's got all the data we need to remember */ /* set up conn so it's got all the data we need to remember */
conn->addr = addr; conn->_base.addr = addr;
conn->port = dir_port; conn->_base.port = dir_port;
conn->address = tor_strdup(address); conn->_base.address = tor_strdup(address);
memcpy(conn->identity_digest, digest, DIGEST_LEN); memcpy(conn->identity_digest, digest, DIGEST_LEN);
conn->purpose = purpose; conn->_base.purpose = purpose;
/* give it an initial state */ /* give it an initial state */
conn->state = DIR_CONN_STATE_CONNECTING; conn->_base.state = DIR_CONN_STATE_CONNECTING;
conn->dirconn_direct = (private_connection == 0); conn->dirconn_direct = (private_connection == 0);
if (!private_connection) { if (!private_connection) {
@ -398,19 +398,19 @@ directory_initiate_command(const char *address, uint32_t addr,
dir_port = get_options()->HttpProxyPort; dir_port = get_options()->HttpProxyPort;
} }
switch (connection_connect(conn, conn->address, addr, dir_port)) { switch (connection_connect(TO_CONN(conn), conn->_base.address, addr, dir_port)) {
case -1: case -1:
connection_dir_request_failed(conn); /* retry if we want */ connection_dir_request_failed(conn); /* retry if we want */
connection_free(conn); connection_free(TO_CONN(conn));
return; return;
case 1: case 1:
conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */ conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
/* fall through */ /* fall through */
case 0: case 0:
/* queue the command on the outbuf */ /* queue the command on the outbuf */
directory_send_command(conn, platform, purpose, resource, directory_send_command(conn, platform, purpose, resource,
payload, payload_len); payload, payload_len);
connection_watch_events(conn, EV_READ | EV_WRITE); connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
/* writable indicates finish, readable indicates broken link, /* writable indicates finish, readable indicates broken link,
error indicates broken link in windowsland. */ error indicates broken link in windowsland. */
} }
@ -419,23 +419,24 @@ directory_initiate_command(const char *address, uint32_t addr,
* populate it and add it at the right state * populate it and add it at the right state
* socketpair and hook up both sides * socketpair and hook up both sides
*/ */
conn->s = connection_ap_make_bridge(conn->address, conn->port); conn->_base.s = connection_ap_make_bridge(conn->_base.address,
if (conn->s < 0) { conn->_base.port);
if (conn->_base.s < 0) {
log_warn(LD_NET,"Making AP bridge to dirserver failed."); log_warn(LD_NET,"Making AP bridge to dirserver failed.");
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return; return;
} }
if (connection_add(conn) < 0) { if (connection_add(TO_CONN(conn)) < 0) {
log_warn(LD_NET,"Unable to add AP bridge to dirserver."); log_warn(LD_NET,"Unable to add AP bridge to dirserver.");
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return; return;
} }
conn->state = DIR_CONN_STATE_CLIENT_SENDING; conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
/* queue the command on the outbuf */ /* queue the command on the outbuf */
directory_send_command(conn, platform, purpose, resource, directory_send_command(conn, platform, purpose, resource,
payload, payload_len); payload, payload_len);
connection_watch_events(conn, EV_READ | EV_WRITE); connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
} }
} }
@ -443,7 +444,7 @@ directory_initiate_command(const char *address, uint32_t addr,
* are as in directory_initiate_command. * are as in directory_initiate_command.
*/ */
static void static void
directory_send_command(connection_t *conn, const char *platform, directory_send_command(dir_connection_t *conn, const char *platform,
int purpose, const char *resource, int purpose, const char *resource,
const char *payload, size_t payload_len) const char *payload, size_t payload_len)
{ {
@ -456,18 +457,18 @@ directory_send_command(connection_t *conn, const char *platform,
size_t len; size_t len;
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_DIR); tor_assert(conn->_base.type == CONN_TYPE_DIR);
tor_free(conn->requested_resource); tor_free(conn->requested_resource);
if (resource) if (resource)
conn->requested_resource = tor_strdup(resource); conn->requested_resource = tor_strdup(resource);
/* come up with a string for which Host: we want */ /* come up with a string for which Host: we want */
if (conn->port == 80) { if (conn->_base.port == 80) {
strlcpy(hoststring, conn->address, sizeof(hoststring)); strlcpy(hoststring, conn->_base.address, sizeof(hoststring));
} else { } else {
tor_snprintf(hoststring, sizeof(hoststring),"%s:%d", tor_snprintf(hoststring, sizeof(hoststring),"%s:%d",
conn->address, conn->port); conn->_base.address, conn->_base.port);
} }
/* come up with some proxy lines, if we're using one. */ /* come up with some proxy lines, if we're using one. */
@ -564,8 +565,8 @@ directory_send_command(connection_t *conn, const char *platform,
} }
tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring); tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring);
connection_write_to_buf(request, strlen(request), conn); connection_write_to_buf(request, strlen(request), TO_CONN(conn));
connection_write_to_buf(url, strlen(url), conn); connection_write_to_buf(url, strlen(url), TO_CONN(conn));
tor_free(url); tor_free(url);
if (!strcmp(httpcommand, "GET") && !payload) { if (!strcmp(httpcommand, "GET") && !payload) {
@ -580,11 +581,11 @@ directory_send_command(connection_t *conn, const char *platform,
hoststring, hoststring,
proxyauthstring); proxyauthstring);
} }
connection_write_to_buf(request, strlen(request), conn); connection_write_to_buf(request, strlen(request), TO_CONN(conn));
if (payload) { if (payload) {
/* then send the payload afterwards too */ /* then send the payload afterwards too */
connection_write_to_buf(payload, payload_len, conn); connection_write_to_buf(payload, payload_len, TO_CONN(conn));
} }
} }
@ -804,7 +805,7 @@ body_is_plausible(const char *body, size_t len, int purpose)
* The caller will take care of marking the connection for close. * The caller will take care of marking the connection for close.
*/ */
static int static int
connection_dir_client_reached_eof(connection_t *conn) connection_dir_client_reached_eof(dir_connection_t *conn)
{ {
char *body; char *body;
char *headers; char *headers;
@ -816,17 +817,17 @@ connection_dir_client_reached_eof(connection_t *conn)
int compression; int compression;
int plausible; int plausible;
int skewed=0; int skewed=0;
int allow_partial = conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC; int allow_partial = conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC;
int was_compressed=0; int was_compressed=0;
switch (fetch_from_buf_http(conn->inbuf, switch (fetch_from_buf_http(conn->_base.inbuf,
&headers, MAX_HEADERS_SIZE, &headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_DIR_SIZE, &body, &body_len, MAX_DIR_SIZE,
allow_partial)) { allow_partial)) {
case -1: /* overflow */ case -1: /* overflow */
log_warn(LD_PROTOCOL, log_warn(LD_PROTOCOL,
"'fetch' response too large (server '%s:%d'). Closing.", "'fetch' response too large (server '%s:%d'). Closing.",
conn->address, conn->port); conn->_base.address, conn->_base.port);
return -1; return -1;
case 0: case 0:
log_info(LD_HTTP, log_info(LD_HTTP,
@ -839,7 +840,7 @@ connection_dir_client_reached_eof(connection_t *conn)
if (parse_http_response(headers, &status_code, &date_header, if (parse_http_response(headers, &status_code, &date_header,
&compression, &reason) < 0) { &compression, &reason) < 0) {
log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.", log_warn(LD_HTTP,"Unparseable headers (server '%s:%d'). Closing.",
conn->address, conn->port); conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(body); tor_free(headers);
return -1; return -1;
} }
@ -847,7 +848,7 @@ connection_dir_client_reached_eof(connection_t *conn)
log_debug(LD_DIR, log_debug(LD_DIR,
"Received response from directory server '%s:%d': %d %s", "Received response from directory server '%s:%d': %d %s",
conn->address, conn->port, status_code, escaped(reason)); conn->_base.address, conn->_base.port, status_code, escaped(reason));
/* now check if it's got any hints for us about our IP address. */ /* now check if it's got any hints for us about our IP address. */
if (server_mode(get_options())) { if (server_mode(get_options())) {
@ -867,7 +868,7 @@ connection_dir_client_reached_eof(connection_t *conn)
LD_HTTP, LD_HTTP,
"Received directory with skewed time (server '%s:%d'): " "Received directory with skewed time (server '%s:%d'): "
"we are %d minutes %s, or the directory is %d minutes %s.", "we are %d minutes %s, or the directory is %d minutes %s.",
conn->address, conn->port, conn->_base.address, conn->_base.port,
abs(delta)/60, delta>0 ? "ahead" : "behind", abs(delta)/60, delta>0 ? "ahead" : "behind",
abs(delta)/60, delta>0 ? "behind" : "ahead"); abs(delta)/60, delta>0 ? "behind" : "ahead");
skewed = 1; /* don't check the recommended-versions line */ skewed = 1; /* don't check the recommended-versions line */
@ -880,12 +881,12 @@ connection_dir_client_reached_eof(connection_t *conn)
if (status_code == 503) { if (status_code == 503) {
log_info(LD_DIR,"Received http status code %d (%s) from server " log_info(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.", "'%s:%d'. I'll try again soon.",
status_code, escaped(reason), conn->address, conn->port); status_code, escaped(reason), conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason); tor_free(body); tor_free(headers); tor_free(reason);
return -1; return -1;
} }
plausible = body_is_plausible(body, body_len, conn->purpose); plausible = body_is_plausible(body, body_len, conn->_base.purpose);
if (compression || !plausible) { if (compression || !plausible) {
char *new_body = NULL; char *new_body = NULL;
size_t new_len = 0; size_t new_len = 0;
@ -912,7 +913,7 @@ connection_dir_client_reached_eof(connection_t *conn)
log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, " log_info(LD_HTTP, "HTTP body from server '%s:%d' was labeled %s, "
"but it seems to be %s.%s", "but it seems to be %s.%s",
conn->address, conn->port, description1, description2, conn->_base.address, conn->_base.port, description1, description2,
(compression>0 && guessed>0)?" Trying both.":""); (compression>0 && guessed>0)?" Trying both.":"");
} }
/* Try declared compression first if we can. */ /* Try declared compression first if we can. */
@ -929,7 +930,7 @@ connection_dir_client_reached_eof(connection_t *conn)
if (!plausible && !new_body) { if (!plausible && !new_body) {
log_fn(LOG_PROTOCOL_WARN, LD_HTTP, log_fn(LOG_PROTOCOL_WARN, LD_HTTP,
"Unable to decompress HTTP body (server '%s:%d').", "Unable to decompress HTTP body (server '%s:%d').",
conn->address, conn->port); conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason); tor_free(body); tor_free(headers); tor_free(reason);
return -1; return -1;
} }
@ -941,38 +942,38 @@ connection_dir_client_reached_eof(connection_t *conn)
} }
} }
if (conn->purpose == DIR_PURPOSE_FETCH_DIR) { if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR) {
/* fetch/process the directory to cache it. */ /* fetch/process the directory to cache it. */
log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'", log_info(LD_DIR,"Received directory (size %d) from server '%s:%d'",
(int)body_len, conn->address, conn->port); (int)body_len, conn->_base.address, conn->_base.port);
if (status_code != 200) { if (status_code != 200) {
log_warn(LD_DIR,"Received http status code %d (%s) from server " log_warn(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.", "'%s:%d'. I'll try again soon.",
status_code, escaped(reason), conn->address, conn->port); status_code, escaped(reason), conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason); tor_free(body); tor_free(headers); tor_free(reason);
return -1; return -1;
} }
if (router_parse_directory(body) < 0) { if (router_parse_directory(body) < 0) {
log_notice(LD_DIR,"I failed to parse the directory I fetched from " log_notice(LD_DIR,"I failed to parse the directory I fetched from "
"'%s:%d'. Ignoring.", conn->address, conn->port); "'%s:%d'. Ignoring.", conn->_base.address, conn->_base.port);
} }
note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len); note_request(was_compressed?"dl/dir.z":"dl/dir", orig_len);
} }
if (conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) { if (conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
/* just update our list of running routers, if this list is new info */ /* just update our list of running routers, if this list is new info */
log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len); log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len);
if (status_code != 200) { if (status_code != 200) {
log_warn(LD_DIR,"Received http status code %d (%s) from server " log_warn(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.", "'%s:%d'. I'll try again soon.",
status_code, escaped(reason), conn->address, conn->port); status_code, escaped(reason), conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason); tor_free(body); tor_free(headers); tor_free(reason);
return -1; return -1;
} }
if (router_parse_runningrouters(body)<0) { if (router_parse_runningrouters(body)<0) {
log_warn(LD_DIR, log_warn(LD_DIR,
"Bad running-routers from server '%s:%d'. I'll try again soon.", "Bad running-routers from server '%s:%d'. I'll try again soon.",
conn->address, conn->port); conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason); tor_free(body); tor_free(headers); tor_free(reason);
return -1; return -1;
} }
@ -980,16 +981,16 @@ connection_dir_client_reached_eof(connection_t *conn)
"dl/running-routers", orig_len); "dl/running-routers", orig_len);
} }
if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) { if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
smartlist_t *which = NULL; smartlist_t *which = NULL;
char *cp; char *cp;
log_info(LD_DIR,"Received networkstatus objects (size %d) from server " log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
"'%s:%d'",(int) body_len, conn->address, conn->port); "'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
if (status_code != 200) { if (status_code != 200) {
log_warn(LD_DIR, log_warn(LD_DIR,
"Received http status code %d (%s) from server " "Received http status code %d (%s) from server "
"'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.", "'%s:%d' while fetching \"/tor/status/%s\". I'll try again soon.",
status_code, escaped(reason), conn->address, conn->port, status_code, escaped(reason), conn->_base.address, conn->_base.port,
conn->requested_resource); conn->requested_resource);
tor_free(body); tor_free(headers); tor_free(reason); tor_free(body); tor_free(headers); tor_free(reason);
connection_dir_download_networkstatus_failed(conn); connection_dir_download_networkstatus_failed(conn);
@ -1038,11 +1039,11 @@ connection_dir_client_reached_eof(connection_t *conn)
} }
} }
if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC) { if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC) {
smartlist_t *which = NULL; smartlist_t *which = NULL;
int n_asked_for = 0; int n_asked_for = 0;
log_info(LD_DIR,"Received server info (size %d) from server '%s:%d'", log_info(LD_DIR,"Received server info (size %d) from server '%s:%d'",
(int)body_len, conn->address, conn->port); (int)body_len, conn->_base.address, conn->_base.port);
note_request(was_compressed?"dl/server.z":"dl/server", orig_len); note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
if (conn->requested_resource && if (conn->requested_resource &&
!strcmpstart(conn->requested_resource,"d/")) { !strcmpstart(conn->requested_resource,"d/")) {
@ -1059,7 +1060,7 @@ connection_dir_client_reached_eof(connection_t *conn)
log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR, log_fn(dir_okay ? LOG_INFO : LOG_WARN, LD_DIR,
"Received http status code %d (%s) from server '%s:%d' " "Received http status code %d (%s) from server '%s:%d' "
"while fetching \"/tor/server/%s\". I'll try again soon.", "while fetching \"/tor/server/%s\". I'll try again soon.",
status_code, escaped(reason), conn->address, conn->port, status_code, escaped(reason), conn->_base.address, conn->_base.port,
conn->requested_resource); conn->requested_resource);
if (!which) { if (!which) {
connection_dir_download_routerdesc_failed(conn); connection_dir_download_routerdesc_failed(conn);
@ -1085,7 +1086,7 @@ connection_dir_client_reached_eof(connection_t *conn)
if (which) { /* mark remaining ones as failed */ if (which) { /* mark remaining ones as failed */
log_info(LD_DIR, "Received %d/%d routers requested from %s:%d", log_info(LD_DIR, "Received %d/%d routers requested from %s:%d",
n_asked_for-smartlist_len(which), n_asked_for, n_asked_for-smartlist_len(which), n_asked_for,
conn->address, (int)conn->port); conn->_base.address, (int)conn->_base.port);
if (smartlist_len(which)) { if (smartlist_len(which)) {
dir_routerdesc_download_failed(which); dir_routerdesc_download_failed(which);
} }
@ -1098,13 +1099,13 @@ connection_dir_client_reached_eof(connection_t *conn)
routerinfo_t *me = router_get_my_routerinfo(); routerinfo_t *me = router_get_my_routerinfo();
if (me && if (me &&
router_digest_is_me(conn->identity_digest) && router_digest_is_me(conn->identity_digest) &&
me->addr == conn->addr && me->addr == conn->_base.addr &&
me->dir_port == conn->port) me->dir_port == conn->_base.port)
router_dirport_found_reachable(); router_dirport_found_reachable();
} }
} }
if (conn->purpose == DIR_PURPOSE_UPLOAD_DIR) { if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
switch (status_code) { switch (status_code) {
case 200: case 200:
log_info(LD_GENERAL,"eof (status 200) after uploading server " log_info(LD_GENERAL,"eof (status 200) after uploading server "
@ -1113,7 +1114,7 @@ connection_dir_client_reached_eof(connection_t *conn)
case 400: case 400:
log_warn(LD_GENERAL,"http status 400 (%s) response from " log_warn(LD_GENERAL,"http status 400 (%s) response from "
"dirserver '%s:%d'. Please correct.", "dirserver '%s:%d'. Please correct.",
escaped(reason), conn->address, conn->port); escaped(reason), conn->_base.address, conn->_base.port);
break; break;
case 403: case 403:
log_warn(LD_GENERAL, log_warn(LD_GENERAL,
@ -1121,19 +1122,19 @@ connection_dir_client_reached_eof(connection_t *conn)
"'%s:%d'. Is your clock skewed? Have you mailed us your key " "'%s:%d'. Is your clock skewed? Have you mailed us your key "
"fingerprint? Are you using the right key? Are you using a " "fingerprint? Are you using the right key? Are you using a "
"private IP address? See http://tor.eff.org/doc/" "private IP address? See http://tor.eff.org/doc/"
"tor-doc-server.html",escaped(reason), conn->address, conn->port); "tor-doc-server.html",escaped(reason), conn->_base.address, conn->_base.port);
break; break;
default: default:
log_warn(LD_GENERAL, log_warn(LD_GENERAL,
"http status %d (%s) reason unexpected (server '%s:%d').", "http status %d (%s) reason unexpected (server '%s:%d').",
status_code, escaped(reason), conn->address, conn->port); status_code, escaped(reason), conn->_base.address, conn->_base.port);
break; break;
} }
/* return 0 in all cases, since we don't want to mark any /* return 0 in all cases, since we don't want to mark any
* dirservers down just because they don't like us. */ * dirservers down just because they don't like us. */
} }
if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC) { if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d " log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
"(%s))", "(%s))",
(int)body_len, status_code, escaped(reason)); (int)body_len, status_code, escaped(reason));
@ -1145,7 +1146,7 @@ connection_dir_client_reached_eof(connection_t *conn)
* cleans it up */ * cleans it up */
} else { } else {
/* success. notify pending connections about this. */ /* success. notify pending connections about this. */
conn->purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
rend_client_desc_here(conn->rend_query); rend_client_desc_here(conn->rend_query);
} }
break; break;
@ -1161,12 +1162,12 @@ connection_dir_client_reached_eof(connection_t *conn)
default: default:
log_warn(LD_REND,"http status %d (%s) response unexpected (server " log_warn(LD_REND,"http status %d (%s) response unexpected (server "
"'%s:%d').", "'%s:%d').",
status_code, escaped(reason), conn->address, conn->port); status_code, escaped(reason), conn->_base.address, conn->_base.port);
break; break;
} }
} }
if (conn->purpose == DIR_PURPOSE_UPLOAD_RENDDESC) { if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) {
switch (status_code) { switch (status_code) {
case 200: case 200:
log_info(LD_REND, log_info(LD_REND,
@ -1176,12 +1177,12 @@ connection_dir_client_reached_eof(connection_t *conn)
case 400: case 400:
log_warn(LD_REND,"http status 400 (%s) response from dirserver " log_warn(LD_REND,"http status 400 (%s) response from dirserver "
"'%s:%d'. Malformed rendezvous descriptor?", "'%s:%d'. Malformed rendezvous descriptor?",
escaped(reason), conn->address, conn->port); escaped(reason), conn->_base.address, conn->_base.port);
break; break;
default: default:
log_warn(LD_REND,"http status %d (%s) response unexpected (server " log_warn(LD_REND,"http status %d (%s) response unexpected (server "
"'%s:%d').", "'%s:%d').",
status_code, escaped(reason), conn->address, conn->port); status_code, escaped(reason), conn->_base.address, conn->_base.port);
break; break;
} }
} }
@ -1191,20 +1192,20 @@ connection_dir_client_reached_eof(connection_t *conn)
/** Called when a directory connection reaches EOF */ /** Called when a directory connection reaches EOF */
int int
connection_dir_reached_eof(connection_t *conn) connection_dir_reached_eof(dir_connection_t *conn)
{ {
int retval; int retval;
if (conn->state != DIR_CONN_STATE_CLIENT_READING) { if (conn->_base.state != DIR_CONN_STATE_CLIENT_READING) {
log_info(LD_HTTP,"conn reached eof, not reading. Closing."); log_info(LD_HTTP,"conn reached eof, not reading. Closing.");
connection_close_immediate(conn); /* error: give up on flushing */ connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return -1; return -1;
} }
retval = connection_dir_client_reached_eof(conn); retval = connection_dir_client_reached_eof(conn);
if (retval == 0) /* success */ if (retval == 0) /* success */
conn->state = DIR_CONN_STATE_CLIENT_FINISHED; conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED;
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return retval; return retval;
} }
@ -1212,10 +1213,10 @@ connection_dir_reached_eof(connection_t *conn)
* directory servers and connections <em>at</em> directory servers.) * directory servers and connections <em>at</em> directory servers.)
*/ */
int int
connection_dir_process_inbuf(connection_t *conn) connection_dir_process_inbuf(dir_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_DIR); tor_assert(conn->_base.type == CONN_TYPE_DIR);
/* Directory clients write, then read data until they receive EOF; /* Directory clients write, then read data until they receive EOF;
* directory servers read data until they get an HTTP command, then * directory servers read data until they get an HTTP command, then
@ -1224,9 +1225,9 @@ connection_dir_process_inbuf(connection_t *conn)
*/ */
/* If we're on the dirserver side, look for a command. */ /* If we're on the dirserver side, look for a command. */
if (conn->state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) { if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
if (directory_handle_command(conn) < 0) { if (directory_handle_command(conn) < 0) {
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return -1; return -1;
} }
return 0; return 0;
@ -1234,7 +1235,7 @@ connection_dir_process_inbuf(connection_t *conn)
/* XXX for READ states, might want to make sure inbuf isn't too big */ /* XXX for READ states, might want to make sure inbuf isn't too big */
if (!conn->inbuf_reached_eof) if (!conn->_base.inbuf_reached_eof)
log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf."); log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
return 0; return 0;
} }
@ -1243,7 +1244,7 @@ connection_dir_process_inbuf(connection_t *conn)
* <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>. * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
*/ */
static void static void
write_http_status_line(connection_t *conn, int status, write_http_status_line(dir_connection_t *conn, int status,
const char *reason_phrase) const char *reason_phrase)
{ {
char buf[256]; char buf[256];
@ -1252,12 +1253,12 @@ write_http_status_line(connection_t *conn, int status,
log_warn(LD_BUG,"Bug: status line too long."); log_warn(LD_BUG,"Bug: status line too long.");
return; return;
} }
connection_write_to_buf(buf, strlen(buf), conn); connection_write_to_buf(buf, strlen(buf), TO_CONN(conn));
} }
/** DOCDOC */ /** DOCDOC */
static void static void
write_http_response_header(connection_t *conn, ssize_t length, write_http_response_header(dir_connection_t *conn, ssize_t length,
const char *type, const char *encoding) const char *type, const char *encoding)
{ {
char date[RFC1123_TIME_LEN+1]; char date[RFC1123_TIME_LEN+1];
@ -1272,7 +1273,7 @@ write_http_response_header(connection_t *conn, ssize_t length,
tor_snprintf(cp, sizeof(tmp), tor_snprintf(cp, sizeof(tmp),
"HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n" "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n"
X_ADDRESS_HEADER "%s\r\n", X_ADDRESS_HEADER "%s\r\n",
date, type, conn->address); date, type, conn->_base.address);
cp += strlen(tmp); cp += strlen(tmp);
if (encoding) { if (encoding) {
tor_snprintf(cp, sizeof(tmp)-(cp-tmp), tor_snprintf(cp, sizeof(tmp)-(cp-tmp),
@ -1288,7 +1289,7 @@ write_http_response_header(connection_t *conn, ssize_t length,
memcpy(cp, "\r\n", 3); memcpy(cp, "\r\n", 3);
else else
tor_assert(0); tor_assert(0);
connection_write_to_buf(tmp, strlen(tmp), conn); connection_write_to_buf(tmp, strlen(tmp), TO_CONN(conn));
} }
/** Helper function: return 1 if there are any dir conns of purpose /** Helper function: return 1 if there are any dir conns of purpose
@ -1308,7 +1309,7 @@ already_fetching_directory(int purpose)
if (conn->type == CONN_TYPE_DIR && if (conn->type == CONN_TYPE_DIR &&
conn->purpose == purpose && conn->purpose == purpose &&
!conn->marked_for_close && !conn->marked_for_close &&
!router_digest_is_me(conn->identity_digest)) !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest))
return 1; return 1;
} }
return 0; return 0;
@ -1389,7 +1390,7 @@ directory_dump_request_log(void)
* conn-\>outbuf. If the request is unrecognized, send a 400. * conn-\>outbuf. If the request is unrecognized, send a 400.
* Always return 0. */ * Always return 0. */
static int static int
directory_handle_command_get(connection_t *conn, char *headers, directory_handle_command_get(dir_connection_t *conn, char *headers,
char *body, size_t body_len) char *body, size_t body_len)
{ {
size_t dlen; size_t dlen;
@ -1401,7 +1402,7 @@ directory_handle_command_get(connection_t *conn, char *headers,
log_debug(LD_DIRSERV,"Received GET command."); log_debug(LD_DIRSERV,"Received GET command.");
conn->state = DIR_CONN_STATE_SERVER_WRITING; conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
if (parse_http_url(headers, &url) < 0) { if (parse_http_url(headers, &url) < 0) {
write_http_status_line(conn, 400, "Bad request"); write_http_status_line(conn, 400, "Bad request");
@ -1471,7 +1472,7 @@ directory_handle_command_get(connection_t *conn, char *headers,
write_http_response_header(conn, dlen, write_http_response_header(conn, dlen,
deflated?"application/octet-stream":"text/plain", deflated?"application/octet-stream":"text/plain",
deflated?"deflate":"identity"); deflated?"deflate":"identity");
connection_write_to_buf(cp, strlen(cp), conn); connection_write_to_buf(cp, strlen(cp), TO_CONN(conn));
return 0; return 0;
} }
@ -1583,7 +1584,7 @@ directory_handle_command_get(connection_t *conn, char *headers,
NULL); NULL);
note_request("/tor/rendezvous?/", desc_len); note_request("/tor/rendezvous?/", desc_len);
/* need to send descp separately, because it may include nuls */ /* need to send descp separately, because it may include nuls */
connection_write_to_buf(descp, desc_len, conn); connection_write_to_buf(descp, desc_len, TO_CONN(conn));
break; break;
case 0: /* well-formed but not present */ case 0: /* well-formed but not present */
write_http_status_line(conn, 404, "Not found"); write_http_status_line(conn, 404, "Not found");
@ -1600,7 +1601,7 @@ directory_handle_command_get(connection_t *conn, char *headers,
char *bytes = directory_dump_request_log(); char *bytes = directory_dump_request_log();
size_t len = strlen(bytes); size_t len = strlen(bytes);
write_http_response_header(conn, len, "text/plain", NULL); write_http_response_header(conn, len, "text/plain", NULL);
connection_write_to_buf(bytes, len, conn); connection_write_to_buf(bytes, len, TO_CONN(conn));
tor_free(bytes); tor_free(bytes);
tor_free(url); tor_free(url);
return 0; return 0;
@ -1611,12 +1612,12 @@ directory_handle_command_get(connection_t *conn, char *headers,
char robots[] = "User-agent: *\r\nDisallow: /\r\n"; char robots[] = "User-agent: *\r\nDisallow: /\r\n";
size_t len = strlen(robots); size_t len = strlen(robots);
write_http_response_header(conn, len, "text/plain", NULL); write_http_response_header(conn, len, "text/plain", NULL);
connection_write_to_buf(robots, len, conn); connection_write_to_buf(robots, len, TO_CONN(conn));
tor_free(url); tor_free(url);
return 0; return 0;
} }
if (!strcmp(url,"/tor/dir-all-weaselhack") && (conn->addr == 0x7f000001ul) && if (!strcmp(url,"/tor/dir-all-weaselhack") && (conn->_base.addr == 0x7f000001ul) &&
authdir_mode(get_options())) { authdir_mode(get_options())) {
/* XXX until weasel rewrites his scripts XXXX012 */ /* XXX until weasel rewrites his scripts XXXX012 */
char *new_directory=NULL; char *new_directory=NULL;
@ -1633,7 +1634,7 @@ directory_handle_command_get(connection_t *conn, char *headers,
write_http_response_header(conn, dlen, "text/plain", "identity"); write_http_response_header(conn, dlen, "text/plain", "identity");
connection_write_to_buf(new_directory, dlen, conn); connection_write_to_buf(new_directory, dlen, TO_CONN(conn));
tor_free(new_directory); tor_free(new_directory);
tor_free(url); tor_free(url);
return 0; return 0;
@ -1651,14 +1652,14 @@ directory_handle_command_get(connection_t *conn, char *headers,
* response into conn-\>outbuf. If the request is unrecognized, send a * response into conn-\>outbuf. If the request is unrecognized, send a
* 400. Always return 0. */ * 400. Always return 0. */
static int static int
directory_handle_command_post(connection_t *conn, char *headers, directory_handle_command_post(dir_connection_t *conn, char *headers,
char *body, size_t body_len) char *body, size_t body_len)
{ {
char *url = NULL; char *url = NULL;
log_debug(LD_DIRSERV,"Received POST command."); log_debug(LD_DIRSERV,"Received POST command.");
conn->state = DIR_CONN_STATE_SERVER_WRITING; conn->_base.state = DIR_CONN_STATE_SERVER_WRITING;
if (!authdir_mode(get_options())) { if (!authdir_mode(get_options())) {
/* we just provide cached directories; we don't want to /* we just provide cached directories; we don't want to
@ -1685,7 +1686,7 @@ directory_handle_command_post(connection_t *conn, char *headers,
case -1: case -1:
case 1: case 1:
log_notice(LD_DIRSERV,"Rejected router descriptor from %s.", log_notice(LD_DIRSERV,"Rejected router descriptor from %s.",
conn->address); conn->_base.address);
/* malformed descriptor, or something wrong */ /* malformed descriptor, or something wrong */
write_http_status_line(conn, 400, msg); write_http_status_line(conn, 400, msg);
break; break;
@ -1703,7 +1704,7 @@ directory_handle_command_post(connection_t *conn, char *headers,
// char tmp[1024*2+1]; // char tmp[1024*2+1];
log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV, log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
"Rejected rend descriptor (length %d) from %s.", "Rejected rend descriptor (length %d) from %s.",
(int)body_len, conn->address); (int)body_len, conn->_base.address);
#if 0 #if 0
if (body_len <= 1024) { if (body_len <= 1024) {
base16_encode(tmp, sizeof(tmp), body, body_len); base16_encode(tmp, sizeof(tmp), body, body_len);
@ -1731,21 +1732,21 @@ directory_handle_command_post(connection_t *conn, char *headers,
* buffer. Return a 0 on success, or -1 on error. * buffer. Return a 0 on success, or -1 on error.
*/ */
static int static int
directory_handle_command(connection_t *conn) directory_handle_command(dir_connection_t *conn)
{ {
char *headers=NULL, *body=NULL; char *headers=NULL, *body=NULL;
size_t body_len=0; size_t body_len=0;
int r; int r;
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_DIR); tor_assert(conn->_base.type == CONN_TYPE_DIR);
switch (fetch_from_buf_http(conn->inbuf, switch (fetch_from_buf_http(conn->_base.inbuf,
&headers, MAX_HEADERS_SIZE, &headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_BODY_SIZE, 0)) { &body, &body_len, MAX_BODY_SIZE, 0)) {
case -1: /* overflow */ case -1: /* overflow */
log_warn(LD_DIRSERV, log_warn(LD_DIRSERV,
"Invalid input from address '%s'. Closing.", conn->address); "Invalid input from address '%s'. Closing.", conn->_base.address);
return -1; return -1;
case 0: case 0:
log_debug(LD_DIRSERV,"command not all here yet."); log_debug(LD_DIRSERV,"command not all here yet.");
@ -1753,7 +1754,7 @@ directory_handle_command(connection_t *conn)
/* case 1, fall through */ /* case 1, fall through */
} }
http_set_address_origin(headers, conn); http_set_address_origin(headers, TO_CONN(conn));
//log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body); //log_debug(LD_DIRSERV,"headers %s, body %s.", headers, body);
if (!strncasecmp(headers,"GET",3)) if (!strncasecmp(headers,"GET",3))
@ -1776,23 +1777,23 @@ directory_handle_command(connection_t *conn)
* appropriate. * appropriate.
*/ */
int int
connection_dir_finished_flushing(connection_t *conn) connection_dir_finished_flushing(dir_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_DIR); tor_assert(conn->_base.type == CONN_TYPE_DIR);
switch (conn->state) { switch (conn->_base.state) {
case DIR_CONN_STATE_CLIENT_SENDING: case DIR_CONN_STATE_CLIENT_SENDING:
log_debug(LD_DIR,"client finished sending command."); log_debug(LD_DIR,"client finished sending command.");
conn->state = DIR_CONN_STATE_CLIENT_READING; conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
connection_stop_writing(conn); connection_stop_writing(TO_CONN(conn));
return 0; return 0;
case DIR_CONN_STATE_SERVER_WRITING: case DIR_CONN_STATE_SERVER_WRITING:
log_debug(LD_DIRSERV,"Finished writing server response. Closing."); log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return 0; return 0;
default: default:
log_warn(LD_BUG,"Bug: called in unexpected state %d.", conn->state); log_warn(LD_BUG,"Bug: called in unexpected state %d.", conn->_base.state);
tor_fragile_assert(); tor_fragile_assert();
return -1; return -1;
} }
@ -1802,16 +1803,16 @@ connection_dir_finished_flushing(connection_t *conn)
/** Connected handler for directory connections: begin sending data to the /** Connected handler for directory connections: begin sending data to the
* server */ * server */
int int
connection_dir_finished_connecting(connection_t *conn) connection_dir_finished_connecting(dir_connection_t *conn)
{ {
tor_assert(conn); tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_DIR); tor_assert(conn->_base.type == CONN_TYPE_DIR);
tor_assert(conn->state == DIR_CONN_STATE_CONNECTING); tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING);
log_debug(LD_HTTP,"Dir connection to router %s:%u established.", log_debug(LD_HTTP,"Dir connection to router %s:%u established.",
conn->address,conn->port); conn->_base.address,conn->_base.port);
conn->state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */ conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* start flushing conn */
return 0; return 0;
} }

View file

@ -1825,7 +1825,7 @@ dirserv_test_reachability(int try_all)
#define DIRSERV_BUFFER_MIN 16384 #define DIRSERV_BUFFER_MIN 16384
static int static int
connection_dirserv_finish_spooling(connection_t *conn) connection_dirserv_finish_spooling(dir_connection_t *conn)
{ {
if (conn->zlib_state) { if (conn->zlib_state) {
connection_write_to_buf_zlib(conn, conn->zlib_state, "", 0, 1); connection_write_to_buf_zlib(conn, conn->zlib_state, "", 0, 1);
@ -1838,12 +1838,12 @@ connection_dirserv_finish_spooling(connection_t *conn)
/** DOCDOC */ /** DOCDOC */
static int static int
connection_dirserv_add_servers_to_outbuf(connection_t *conn) connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
{ {
int by_fp = conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP; int by_fp = conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP;
while (smartlist_len(conn->fingerprint_stack) && while (smartlist_len(conn->fingerprint_stack) &&
buf_datalen(conn->outbuf) < DIRSERV_BUFFER_MIN) { buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
const char *body; const char *body;
char *fp = smartlist_pop_last(conn->fingerprint_stack); char *fp = smartlist_pop_last(conn->fingerprint_stack);
signed_descriptor_t *sd = NULL; signed_descriptor_t *sd = NULL;
@ -1875,7 +1875,7 @@ connection_dirserv_add_servers_to_outbuf(connection_t *conn)
} else { } else {
connection_write_to_buf(body, connection_write_to_buf(body,
sd->signed_descriptor_len, sd->signed_descriptor_len,
conn); TO_CONN(conn));
} }
} }
@ -1890,11 +1890,11 @@ connection_dirserv_add_servers_to_outbuf(connection_t *conn)
/** DOCDOC */ /** DOCDOC */
static int static int
connection_dirserv_add_dir_bytes_to_outbuf(connection_t *conn) connection_dirserv_add_dir_bytes_to_outbuf(dir_connection_t *conn)
{ {
int bytes, remaining; int bytes, remaining;
bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->outbuf); bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->_base.outbuf);
tor_assert(bytes > 0); tor_assert(bytes > 0);
tor_assert(conn->cached_dir); tor_assert(conn->cached_dir);
if (bytes < 8192) if (bytes < 8192)
@ -1909,7 +1909,7 @@ connection_dirserv_add_dir_bytes_to_outbuf(connection_t *conn)
bytes, bytes == remaining); bytes, bytes == remaining);
} else { } else {
connection_write_to_buf(conn->cached_dir->dir_z + conn->cached_dir_offset, connection_write_to_buf(conn->cached_dir->dir_z + conn->cached_dir_offset,
bytes, conn); bytes, TO_CONN(conn));
} }
conn->cached_dir_offset += bytes; conn->cached_dir_offset += bytes;
if (conn->cached_dir_offset == (int)conn->cached_dir->dir_z_len) { if (conn->cached_dir_offset == (int)conn->cached_dir->dir_z_len) {
@ -1923,10 +1923,10 @@ connection_dirserv_add_dir_bytes_to_outbuf(connection_t *conn)
/* DOCDOC */ /* DOCDOC */
static int static int
connection_dirserv_add_networkstatus_bytes_to_outbuf(connection_t *conn) connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn)
{ {
while (buf_datalen(conn->outbuf) < DIRSERV_BUFFER_MIN) { while (buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
if (conn->cached_dir) { if (conn->cached_dir) {
int uncompressing = (conn->zlib_state != NULL); int uncompressing = (conn->zlib_state != NULL);
int r = connection_dirserv_add_dir_bytes_to_outbuf(conn); int r = connection_dirserv_add_dir_bytes_to_outbuf(conn);
@ -1973,13 +1973,12 @@ connection_dirserv_add_networkstatus_bytes_to_outbuf(connection_t *conn)
/** Called whenever we have flushed some directory data in state /** Called whenever we have flushed some directory data in state
* SERVER_WRITING. */ * SERVER_WRITING. */
int int
connection_dirserv_flushed_some(connection_t *conn) connection_dirserv_flushed_some(dir_connection_t *conn)
{ {
tor_assert(conn->type == CONN_TYPE_DIR); tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING);
tor_assert(conn->state == DIR_CONN_STATE_SERVER_WRITING);
if (conn->dir_spool_src == DIR_SPOOL_NONE if (conn->dir_spool_src == DIR_SPOOL_NONE
|| buf_datalen(conn->outbuf) >= DIRSERV_BUFFER_MIN) || buf_datalen(conn->_base.outbuf) >= DIRSERV_BUFFER_MIN)
return 0; return 0;
switch (conn->dir_spool_src) { switch (conn->dir_spool_src) {

View file

@ -53,7 +53,7 @@ static time_t last_rotation_time=0;
/** Linked list of connections waiting for a DNS answer. */ /** Linked list of connections waiting for a DNS answer. */
typedef struct pending_connection_t { typedef struct pending_connection_t {
connection_t *conn; edge_connection_t *conn;
struct pending_connection_t *next; struct pending_connection_t *next;
} pending_connection_t; } pending_connection_t;
@ -83,8 +83,8 @@ static void purge_expired_resolves(uint32_t now);
static void dns_purge_resolve(cached_resolve_t *resolve); static void dns_purge_resolve(cached_resolve_t *resolve);
static void dns_found_answer(const char *address, uint32_t addr, char outcome, static void dns_found_answer(const char *address, uint32_t addr, char outcome,
uint32_t ttl); uint32_t ttl);
static void send_resolved_cell(connection_t *conn, uint8_t answer_type); static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type);
static int assign_to_dnsworker(connection_t *exitconn); static int assign_to_dnsworker(edge_connection_t *exitconn);
#ifndef USE_EVENTDNS #ifndef USE_EVENTDNS
static int dnsworker_main(void *data); static int dnsworker_main(void *data);
static int spawn_dnsworker(void); static int spawn_dnsworker(void);
@ -226,7 +226,7 @@ purge_expired_resolves(uint32_t now)
{ {
cached_resolve_t *resolve; cached_resolve_t *resolve;
pending_connection_t *pend; pending_connection_t *pend;
connection_t *pendconn; edge_connection_t *pendconn;
/* this is fast because the linked list /* this is fast because the linked list
* oldest_cached_resolve is ordered by when they came in. * oldest_cached_resolve is ordered by when they came in.
@ -251,12 +251,12 @@ purge_expired_resolves(uint32_t now)
pend = resolve->pending_connections; pend = resolve->pending_connections;
resolve->pending_connections = pend->next; resolve->pending_connections = pend->next;
/* Connections should only be pending if they have no socket. */ /* Connections should only be pending if they have no socket. */
tor_assert(pend->conn->s == -1); tor_assert(pend->conn->_base.s == -1);
pendconn = pend->conn; pendconn = pend->conn;
connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT, connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT,
pendconn->cpath_layer); pendconn->cpath_layer);
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
connection_free(pendconn); connection_free(TO_CONN(pendconn));
tor_free(pend); tor_free(pend);
} }
} }
@ -273,7 +273,7 @@ purge_expired_resolves(uint32_t now)
/** Send a response to the RESOVLE request of a connection. answer_type must /** Send a response to the RESOVLE request of a connection. answer_type must
* be one of RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT) */ * be one of RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT) */
static void static void
send_resolved_cell(connection_t *conn, uint8_t answer_type) send_resolved_cell(edge_connection_t *conn, uint8_t answer_type)
{ {
char buf[RELAY_PAYLOAD_SIZE]; char buf[RELAY_PAYLOAD_SIZE];
size_t buflen; size_t buflen;
@ -286,7 +286,7 @@ send_resolved_cell(connection_t *conn, uint8_t answer_type)
{ {
case RESOLVED_TYPE_IPV4: case RESOLVED_TYPE_IPV4:
buf[1] = 4; buf[1] = 4;
set_uint32(buf+2, htonl(conn->addr)); set_uint32(buf+2, htonl(conn->_base.addr));
set_uint32(buf+6, htonl(ttl)); set_uint32(buf+6, htonl(ttl));
buflen = 10; buflen = 10;
break; break;
@ -337,7 +337,7 @@ insert_resolve(cached_resolve_t *r)
* dns farm, and return 0. * dns farm, and return 0.
*/ */
int int
dns_resolve(connection_t *exitconn) dns_resolve(edge_connection_t *exitconn)
{ {
cached_resolve_t *resolve; cached_resolve_t *resolve;
cached_resolve_t search; cached_resolve_t search;
@ -345,17 +345,17 @@ dns_resolve(connection_t *exitconn)
struct in_addr in; struct in_addr in;
circuit_t *circ; circuit_t *circ;
uint32_t now = time(NULL); uint32_t now = time(NULL);
assert_connection_ok(exitconn, 0); assert_connection_ok(TO_CONN(exitconn), 0);
tor_assert(exitconn->s == -1); tor_assert(exitconn->_base.s == -1);
assert_cache_ok(); assert_cache_ok();
/* first check if exitconn->address is an IP. If so, we already /* first check if exitconn->_base.address is an IP. If so, we already
* know the answer. */ * know the answer. */
if (tor_inet_aton(exitconn->address, &in) != 0) { if (tor_inet_aton(exitconn->_base.address, &in) != 0) {
exitconn->addr = ntohl(in.s_addr); exitconn->_base.addr = ntohl(in.s_addr);
exitconn->address_ttl = DEFAULT_DNS_TTL; exitconn->address_ttl = DEFAULT_DNS_TTL;
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
return 1; return 1;
} }
@ -364,11 +364,11 @@ dns_resolve(connection_t *exitconn)
* resolves in the hash table. */ * resolves in the hash table. */
purge_expired_resolves(now); purge_expired_resolves(now);
/* lower-case exitconn->address, so it's in canonical form */ /* lower-case exitconn->_base.address, so it's in canonical form */
tor_strlower(exitconn->address); tor_strlower(exitconn->_base.address);
/* now check the hash table to see if 'address' is already there. */ /* now check the hash table to see if 'address' is already there. */
strlcpy(search.address, exitconn->address, sizeof(search.address)); strlcpy(search.address, exitconn->_base.address, sizeof(search.address));
resolve = HT_FIND(cache_map, &cache_root, &search); resolve = HT_FIND(cache_map, &cache_root, &search);
if (resolve && resolve->expire > now) { /* already there */ if (resolve && resolve->expire > now) { /* already there */
switch (resolve->state) { switch (resolve->state) {
@ -381,27 +381,27 @@ dns_resolve(connection_t *exitconn)
resolve->pending_connections = pending_connection; resolve->pending_connections = pending_connection;
log_debug(LD_EXIT,"Connection (fd %d) waiting for pending DNS " log_debug(LD_EXIT,"Connection (fd %d) waiting for pending DNS "
"resolve of %s", "resolve of %s",
exitconn->s, escaped_safe_str(exitconn->address)); exitconn->_base.s, escaped_safe_str(exitconn->_base.address));
exitconn->state = EXIT_CONN_STATE_RESOLVING; exitconn->_base.state = EXIT_CONN_STATE_RESOLVING;
return 0; return 0;
case CACHE_STATE_VALID: case CACHE_STATE_VALID:
exitconn->addr = resolve->addr; exitconn->_base.addr = resolve->addr;
exitconn->address_ttl = resolve->ttl; exitconn->address_ttl = resolve->ttl;
log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s", log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s",
exitconn->s, escaped_safe_str(exitconn->address)); exitconn->_base.s, escaped_safe_str(exitconn->_base.address));
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
return 1; return 1;
case CACHE_STATE_FAILED: case CACHE_STATE_FAILED:
log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s", log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s",
exitconn->s, escaped_safe_str(exitconn->address)); exitconn->_base.s, escaped_safe_str(exitconn->_base.address));
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
circ = circuit_get_by_edge_conn(exitconn); circ = circuit_get_by_edge_conn(exitconn);
if (circ) if (circ)
circuit_detach_stream(circ, exitconn); circuit_detach_stream(circ, exitconn);
if (!exitconn->marked_for_close) if (!exitconn->_base.marked_for_close)
connection_free(exitconn); connection_free(TO_CONN(exitconn));
return -1; return -1;
} }
tor_assert(0); tor_assert(0);
@ -411,17 +411,17 @@ dns_resolve(connection_t *exitconn)
resolve->magic = CACHED_RESOLVE_MAGIC; resolve->magic = CACHED_RESOLVE_MAGIC;
resolve->state = CACHE_STATE_PENDING; resolve->state = CACHE_STATE_PENDING;
resolve->expire = now + DEFAULT_DNS_TTL; /* this will get replaced. */ resolve->expire = now + DEFAULT_DNS_TTL; /* this will get replaced. */
strlcpy(resolve->address, exitconn->address, sizeof(resolve->address)); strlcpy(resolve->address, exitconn->_base.address, sizeof(resolve->address));
/* add us to the pending list */ /* add us to the pending list */
pending_connection = tor_malloc_zero(sizeof(pending_connection_t)); pending_connection = tor_malloc_zero(sizeof(pending_connection_t));
pending_connection->conn = exitconn; pending_connection->conn = exitconn;
resolve->pending_connections = pending_connection; resolve->pending_connections = pending_connection;
exitconn->state = EXIT_CONN_STATE_RESOLVING; exitconn->_base.state = EXIT_CONN_STATE_RESOLVING;
insert_resolve(resolve); insert_resolve(resolve);
log_debug(LD_EXIT,"Assigning question %s to dnsworker.", log_debug(LD_EXIT,"Assigning question %s to dnsworker.",
escaped_safe_str(exitconn->address)); escaped_safe_str(exitconn->_base.address));
assert_cache_ok(); assert_cache_ok();
return assign_to_dnsworker(exitconn); return assign_to_dnsworker(exitconn);
} }
@ -429,7 +429,7 @@ dns_resolve(connection_t *exitconn)
/** Log an error and abort if conn is waiting for a DNS resolve. /** Log an error and abort if conn is waiting for a DNS resolve.
*/ */
void void
assert_connection_edge_not_dns_pending(connection_t *conn) assert_connection_edge_not_dns_pending(edge_connection_t *conn)
{ {
pending_connection_t *pend; pending_connection_t *pend;
cached_resolve_t **resolve; cached_resolve_t **resolve;
@ -455,9 +455,9 @@ assert_all_pending_dns_resolves_ok(void)
for (pend = (*resolve)->pending_connections; for (pend = (*resolve)->pending_connections;
pend; pend;
pend = pend->next) { pend = pend->next) {
assert_connection_ok(pend->conn, 0); assert_connection_ok(TO_CONN(pend->conn), 0);
tor_assert(pend->conn->s == -1); tor_assert(pend->conn->_base.s == -1);
tor_assert(!connection_in_array(pend->conn)); tor_assert(!connection_in_array(TO_CONN(pend->conn)));
} }
} }
} }
@ -465,26 +465,26 @@ assert_all_pending_dns_resolves_ok(void)
/** Remove <b>conn</b> from the list of connections waiting for conn-\>address. /** Remove <b>conn</b> from the list of connections waiting for conn-\>address.
*/ */
void void
connection_dns_remove(connection_t *conn) connection_dns_remove(edge_connection_t *conn)
{ {
pending_connection_t *pend, *victim; pending_connection_t *pend, *victim;
cached_resolve_t search; cached_resolve_t search;
cached_resolve_t *resolve; cached_resolve_t *resolve;
tor_assert(conn->type == CONN_TYPE_EXIT); tor_assert(conn->_base.type == CONN_TYPE_EXIT);
tor_assert(conn->state == EXIT_CONN_STATE_RESOLVING); tor_assert(conn->_base.state == EXIT_CONN_STATE_RESOLVING);
strlcpy(search.address, conn->address, sizeof(search.address)); strlcpy(search.address, conn->_base.address, sizeof(search.address));
resolve = HT_FIND(cache_map, &cache_root, &search); resolve = HT_FIND(cache_map, &cache_root, &search);
if (!resolve) { if (!resolve) {
log_notice(LD_BUG, "Address %s is not pending. Dropping.", log_notice(LD_BUG, "Address %s is not pending. Dropping.",
escaped_safe_str(conn->address)); escaped_safe_str(conn->_base.address));
return; return;
} }
tor_assert(resolve->pending_connections); tor_assert(resolve->pending_connections);
assert_connection_ok(conn,0); assert_connection_ok(TO_CONN(conn),0);
pend = resolve->pending_connections; pend = resolve->pending_connections;
@ -493,7 +493,7 @@ connection_dns_remove(connection_t *conn)
tor_free(pend); tor_free(pend);
log_debug(LD_EXIT, "First connection (fd %d) no longer waiting " log_debug(LD_EXIT, "First connection (fd %d) no longer waiting "
"for resolve of %s", "for resolve of %s",
conn->s, escaped_safe_str(conn->address)); conn->_base.s, escaped_safe_str(conn->_base.address));
return; return;
} else { } else {
for ( ; pend->next; pend = pend->next) { for ( ; pend->next; pend = pend->next) {
@ -503,7 +503,7 @@ connection_dns_remove(connection_t *conn)
tor_free(victim); tor_free(victim);
log_debug(LD_EXIT, log_debug(LD_EXIT,
"Connection (fd %d) no longer waiting for resolve of %s", "Connection (fd %d) no longer waiting for resolve of %s",
conn->s, escaped_safe_str(conn->address)); conn->_base.s, escaped_safe_str(conn->_base.address));
return; /* more are pending */ return; /* more are pending */
} }
} }
@ -521,7 +521,7 @@ dns_cancel_pending_resolve(char *address)
pending_connection_t *pend; pending_connection_t *pend;
cached_resolve_t search; cached_resolve_t search;
cached_resolve_t *resolve; cached_resolve_t *resolve;
connection_t *pendconn; edge_connection_t *pendconn;
circuit_t *circ; circuit_t *circ;
strlcpy(search.address, address, sizeof(search.address)); strlcpy(search.address, address, sizeof(search.address));
@ -549,18 +549,18 @@ dns_cancel_pending_resolve(char *address)
escaped_safe_str(address)); escaped_safe_str(address));
while (resolve->pending_connections) { while (resolve->pending_connections) {
pend = resolve->pending_connections; pend = resolve->pending_connections;
pend->conn->state = EXIT_CONN_STATE_RESOLVEFAILED; pend->conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
pendconn = pend->conn; pendconn = pend->conn;
assert_connection_ok(pendconn, 0); assert_connection_ok(TO_CONN(pendconn), 0);
tor_assert(pendconn->s == -1); tor_assert(pendconn->_base.s == -1);
if (!pendconn->marked_for_close) { if (!pendconn->_base.marked_for_close) {
connection_edge_end(pendconn, END_STREAM_REASON_RESOURCELIMIT, connection_edge_end(pendconn, END_STREAM_REASON_RESOURCELIMIT,
pendconn->cpath_layer); pendconn->cpath_layer);
} }
circ = circuit_get_by_edge_conn(pendconn); circ = circuit_get_by_edge_conn(pendconn);
if (circ) if (circ)
circuit_detach_stream(circ, pendconn); circuit_detach_stream(circ, pendconn);
connection_free(pendconn); connection_free(TO_CONN(pendconn));
resolve->pending_connections = pend->next; resolve->pending_connections = pend->next;
tor_free(pend); tor_free(pend);
} }
@ -612,7 +612,7 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
pending_connection_t *pend; pending_connection_t *pend;
cached_resolve_t search; cached_resolve_t search;
cached_resolve_t *resolve; cached_resolve_t *resolve;
connection_t *pendconn; edge_connection_t *pendconn;
circuit_t *circ; circuit_t *circ;
assert_cache_ok(); assert_cache_ok();
@ -659,16 +659,16 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
while (resolve->pending_connections) { while (resolve->pending_connections) {
pend = resolve->pending_connections; pend = resolve->pending_connections;
assert_connection_ok(pend->conn,time(NULL)); assert_connection_ok(TO_CONN(pend->conn),time(NULL));
pend->conn->addr = resolve->addr; pend->conn->_base.addr = resolve->addr;
pend->conn->address_ttl = resolve->ttl; pend->conn->address_ttl = resolve->ttl;
pendconn = pend->conn; /* don't pass complex things to the pendconn = pend->conn; /* don't pass complex things to the
connection_mark_for_close macro */ connection_mark_for_close macro */
if (resolve->state == CACHE_STATE_FAILED) { if (resolve->state == CACHE_STATE_FAILED) {
/* prevent double-remove. */ /* prevent double-remove. */
pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED; pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
if (pendconn->purpose == EXIT_PURPOSE_CONNECT) { if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) {
connection_edge_end(pendconn, END_STREAM_REASON_RESOLVEFAILED, connection_edge_end(pendconn, END_STREAM_REASON_RESOLVEFAILED,
pendconn->cpath_layer); pendconn->cpath_layer);
/* This detach must happen after we send the end cell. */ /* This detach must happen after we send the end cell. */
@ -678,11 +678,11 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
/* This detach must happen after we send the resolved cell. */ /* This detach must happen after we send the resolved cell. */
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
} }
connection_free(pendconn); connection_free(TO_CONN(pendconn));
} else { } else {
if (pendconn->purpose == EXIT_PURPOSE_CONNECT) { if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) {
/* prevent double-remove. */ /* prevent double-remove. */
pend->conn->state = EXIT_CONN_STATE_CONNECTING; pend->conn->_base.state = EXIT_CONN_STATE_CONNECTING;
circ = circuit_get_by_edge_conn(pend->conn); circ = circuit_get_by_edge_conn(pend->conn);
tor_assert(circ); tor_assert(circ);
@ -698,12 +698,12 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
} else { } else {
/* prevent double-remove. This isn't really an accurate state, /* prevent double-remove. This isn't really an accurate state,
* but it does the right thing. */ * but it does the right thing. */
pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED; pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4); send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4);
circ = circuit_get_by_edge_conn(pendconn); circ = circuit_get_by_edge_conn(pendconn);
tor_assert(circ); tor_assert(circ);
circuit_detach_stream(circ, pendconn); circuit_detach_stream(circ, pendconn);
connection_free(pendconn); connection_free(TO_CONN(pendconn));
} }
} }
resolve->pending_connections = pend->next; resolve->pending_connections = pend->next;
@ -722,14 +722,14 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
* <b>exitconn</b>-\>address; tell that dns worker to begin resolving. * <b>exitconn</b>-\>address; tell that dns worker to begin resolving.
*/ */
static int static int
assign_to_dnsworker(connection_t *exitconn) assign_to_dnsworker(edge_connection_t *exitconn)
{ {
connection_t *dnsconn; connection_t *dnsconn;
unsigned char len; unsigned char len;
tor_assert(exitconn->state == EXIT_CONN_STATE_RESOLVING); tor_assert(exitconn->_base.state == EXIT_CONN_STATE_RESOLVING);
assert_connection_ok(exitconn, 0); assert_connection_ok(TO_CONN(exitconn), 0);
tor_assert(exitconn->s == -1); tor_assert(exitconn->_base.s == -1);
/* respawn here, to be sure there are enough */ /* respawn here, to be sure there are enough */
if (spawn_enough_dnsworkers() < 0) { if (spawn_enough_dnsworkers() < 0) {
@ -741,18 +741,18 @@ assign_to_dnsworker(connection_t *exitconn)
if (!dnsconn) { if (!dnsconn) {
log_warn(LD_EXIT,"no idle dns workers. Failing."); log_warn(LD_EXIT,"no idle dns workers. Failing.");
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT); send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT);
goto err; goto err;
} }
log_debug(LD_EXIT, log_debug(LD_EXIT,
"Connection (fd %d) needs to resolve %s; assigning " "Connection (fd %d) needs to resolve %s; assigning "
"to DNSWorker (fd %d)", exitconn->s, "to DNSWorker (fd %d)", exitconn->_base.s,
escaped_safe_str(exitconn->address), dnsconn->s); escaped_safe_str(exitconn->_base.address), dnsconn->s);
tor_free(dnsconn->address); tor_free(dnsconn->address);
dnsconn->address = tor_strdup(exitconn->address); dnsconn->address = tor_strdup(exitconn->_base.address);
dnsconn->state = DNSWORKER_STATE_BUSY; dnsconn->state = DNSWORKER_STATE_BUSY;
/* touch the lastwritten timestamp, since that's how we check to /* touch the lastwritten timestamp, since that's how we check to
* see how long it's been since we asked the question, and sometimes * see how long it's been since we asked the question, and sometimes
@ -766,7 +766,7 @@ assign_to_dnsworker(connection_t *exitconn)
return 0; return 0;
err: err:
dns_cancel_pending_resolve(exitconn->address); /* also sends end and frees */ dns_cancel_pending_resolve(exitconn->_base.address); /* also sends end and frees */
return -1; return -1;
} }
@ -1172,11 +1172,11 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses,
static int static int
assign_to_dnsworker(connection_t *exitconn) assign_to_dnsworker(connection_t *exitconn)
{ {
char *addr = tor_strdup(exitconn->address); char *addr = tor_strdup(exitconn->_base.address);
int r; int r;
log_info(LD_EXIT, "Launching eventdns request for %s", log_info(LD_EXIT, "Launching eventdns request for %s",
escaped_safe_str(exitconn->address)); escaped_safe_str(exitconn->_base.address));
r = eventdns_resolve(exitconn->address, DNS_QUERY_NO_SEARCH, r = eventdns_resolve(exitconn->_base.address, DNS_QUERY_NO_SEARCH,
eventdns_callback, addr); eventdns_callback, addr);
if (r) { if (r) {
log_warn(LD_EXIT, "eventdns rejected address %s: error %d.", log_warn(LD_EXIT, "eventdns rejected address %s: error %d.",

View file

@ -786,11 +786,12 @@ hibernate_go_dormant(time_t now)
(conn = connection_get_by_type(CONN_TYPE_AP)) || (conn = connection_get_by_type(CONN_TYPE_AP)) ||
(conn = connection_get_by_type(CONN_TYPE_EXIT))) { (conn = connection_get_by_type(CONN_TYPE_EXIT))) {
if (CONN_IS_EDGE(conn)) if (CONN_IS_EDGE(conn))
connection_edge_end(conn, END_STREAM_REASON_HIBERNATING, connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING,
conn->cpath_layer); TO_EDGE_CONN(conn)->cpath_layer);
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(conn, END_STREAM_REASON_HIBERNATING); connection_mark_unattached_ap(TO_EDGE_CONN(conn),
END_STREAM_REASON_HIBERNATING);
else else
connection_mark_for_close(conn); connection_mark_for_close(conn);
} }

View file

@ -212,11 +212,11 @@ connection_unlink(connection_t *conn, int remove)
} }
smartlist_remove(closeable_connection_lst, conn); smartlist_remove(closeable_connection_lst, conn);
if (conn->type == CONN_TYPE_EXIT) { if (conn->type == CONN_TYPE_EXIT) {
assert_connection_edge_not_dns_pending(conn); assert_connection_edge_not_dns_pending(TO_EDGE_CONN(conn));
} }
if (conn->type == CONN_TYPE_OR && if (conn->type == CONN_TYPE_OR) {
!tor_digest_is_zero(conn->identity_digest)) { if (!tor_digest_is_zero(TO_OR_CONN(conn)->identity_digest))
connection_or_remove_from_identity_map(conn); connection_or_remove_from_identity_map(TO_OR_CONN(conn));
} }
connection_free(conn); connection_free(conn);
} }
@ -413,7 +413,8 @@ conn_read_callback(int fd, short event, void *_conn)
tor_fragile_assert(); tor_fragile_assert();
#endif #endif
if (CONN_IS_EDGE(conn)) if (CONN_IS_EDGE(conn))
connection_edge_end_errno(conn, conn->cpath_layer); connection_edge_end_errno(TO_EDGE_CONN(conn),
TO_EDGE_CONN(conn)->cpath_layer);
connection_mark_for_close(conn); connection_mark_for_close(conn);
} }
} }
@ -443,7 +444,8 @@ conn_write_callback(int fd, short events, void *_conn)
"Bug: unhandled error on write for %s connection (fd %d); removing", "Bug: unhandled error on write for %s connection (fd %d); removing",
conn_type_to_string(conn->type), conn->s); conn_type_to_string(conn->type), conn->s);
tor_fragile_assert(); tor_fragile_assert();
conn->has_sent_end = 1; /* otherwise we cry wolf about duplicate close */ if (CONN_IS_EDGE(conn))
conn->edge_has_sent_end = 1; /* otherwise we cry wolf about duplicate close */
/* XXX do we need a close-immediate here, so we don't try to flush? */ /* XXX do we need a close-immediate here, so we don't try to flush? */
connection_mark_for_close(conn); connection_mark_for_close(conn);
} }
@ -489,7 +491,7 @@ conn_close_if_marked(int i)
conn->marked_for_close_file, conn->marked_for_close); conn->marked_for_close_file, conn->marked_for_close);
if (connection_speaks_cells(conn)) { if (connection_speaks_cells(conn)) {
if (conn->state == OR_CONN_STATE_OPEN) { if (conn->state == OR_CONN_STATE_OPEN) {
retval = flush_buf_tls(conn->tls, conn->outbuf, sz, retval = flush_buf_tls(TO_OR_CONN(conn)->tls, conn->outbuf, sz,
&conn->outbuf_flushlen); &conn->outbuf_flushlen);
} else } else
retval = -1; /* never flush non-open broken tls connections */ retval = -1; /* never flush non-open broken tls connections */
@ -544,12 +546,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);
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(conn->socks_request->address), safe_str(edge_conn->socks_request->address),
conn->socks_request->port); edge_conn->socks_request->port);
connection_mark_unattached_ap(conn, END_STREAM_REASON_NET_UNREACHABLE); connection_mark_unattached_ap(edge_conn, END_STREAM_REASON_NET_UNREACHABLE);
} }
} }
@ -582,6 +585,7 @@ run_connection_housekeeping(int i, time_t now)
cell_t cell; cell_t cell;
connection_t *conn = connection_array[i]; connection_t *conn = connection_array[i];
or_options_t *options = get_options(); or_options_t *options = get_options();
or_connection_t *or_conn;
if (conn->outbuf && !buf_datalen(conn->outbuf)) if (conn->outbuf && !buf_datalen(conn->outbuf))
conn->timestamp_lastempty = now; conn->timestamp_lastempty = now;
@ -602,7 +606,7 @@ run_connection_housekeeping(int i, time_t now)
buf_datalen(conn->inbuf)>=1024) { buf_datalen(conn->inbuf)>=1024) {
log_info(LD_DIR,"Trying to extract information from wedged server desc " log_info(LD_DIR,"Trying to extract information from wedged server desc "
"download."); "download.");
connection_dir_reached_eof(conn); connection_dir_reached_eof(TO_DIR_CONN(conn));
} else { } else {
connection_mark_for_close(conn); connection_mark_for_close(conn);
} }
@ -612,17 +616,19 @@ run_connection_housekeeping(int i, time_t now)
if (!connection_speaks_cells(conn)) if (!connection_speaks_cells(conn))
return; /* we're all done here, the rest is just for OR conns */ return; /* we're all done here, the rest is just for OR conns */
if (!conn->is_obsolete) { or_conn = TO_OR_CONN(conn);
if (!conn->or_is_obsolete) {
if (conn->timestamp_created + TIME_BEFORE_OR_CONN_IS_OBSOLETE < now) { if (conn->timestamp_created + TIME_BEFORE_OR_CONN_IS_OBSOLETE < now) {
log_info(LD_OR, log_info(LD_OR,
"Marking OR conn to %s:%d obsolete (fd %d, %d secs old).", "Marking OR conn to %s:%d obsolete (fd %d, %d secs old).",
conn->address, conn->port, conn->s, conn->address, conn->port, conn->s,
(int)(now - conn->timestamp_created)); (int)(now - conn->timestamp_created));
conn->is_obsolete = 1; conn->or_is_obsolete = 1;
} else { } else {
connection_t *best = or_connection_t *best =
connection_or_get_by_identity_digest(conn->identity_digest); connection_or_get_by_identity_digest(or_conn->identity_digest);
if (best && best != conn && if (best && best != or_conn &&
(conn->state == OR_CONN_STATE_OPEN || (conn->state == OR_CONN_STATE_OPEN ||
now > conn->timestamp_created + TLS_HANDSHAKE_TIMEOUT)) { now > conn->timestamp_created + TLS_HANDSHAKE_TIMEOUT)) {
/* We only mark as obsolete connections that already are in /* We only mark as obsolete connections that already are in
@ -637,16 +643,16 @@ run_connection_housekeeping(int i, time_t now)
"(fd %d, %d secs old).", "(fd %d, %d secs old).",
conn->address, conn->port, conn->s, conn->address, conn->port, conn->s,
(int)(now - conn->timestamp_created)); (int)(now - conn->timestamp_created));
conn->is_obsolete = 1; conn->or_is_obsolete = 1;
} }
} }
} }
if (conn->is_obsolete && !conn->n_circuits) { if (conn->or_is_obsolete && !or_conn->n_circuits) {
/* no unmarked circs -- mark it now */ /* no unmarked circs -- mark it now */
log_info(LD_OR, log_info(LD_OR,
"Expiring non-used OR connection to fd %d (%s:%d) [Obsolete].", "Expiring non-used OR connection to fd %d (%s:%d) [Obsolete].",
conn->s,conn->address, conn->port); conn->s, conn->address, conn->port);
connection_mark_for_close(conn); connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1; conn->hold_open_until_flushed = 1;
return; return;
@ -655,20 +661,20 @@ run_connection_housekeeping(int i, time_t now)
/* If we haven't written to an OR connection for a while, then either nuke /* If we haven't written to an OR connection for a while, then either nuke
the connection or send a keepalive, depending. */ the connection or send a keepalive, depending. */
if (now >= conn->timestamp_lastwritten + options->KeepalivePeriod) { if (now >= conn->timestamp_lastwritten + options->KeepalivePeriod) {
routerinfo_t *router = router_get_by_digest(conn->identity_digest); routerinfo_t *router = router_get_by_digest(or_conn->identity_digest);
if (!connection_state_is_open(conn)) { if (!connection_state_is_open(conn)) {
log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).", log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).",
conn->s,conn->address, conn->port); conn->s,conn->address, conn->port);
connection_mark_for_close(conn); connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1; conn->hold_open_until_flushed = 1;
} else if (we_are_hibernating() && !conn->n_circuits && } else if (we_are_hibernating() && !or_conn->n_circuits &&
!buf_datalen(conn->outbuf)) { !buf_datalen(conn->outbuf)) {
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
"[Hibernating or exiting].", "[Hibernating or exiting].",
conn->s,conn->address, conn->port); conn->s,conn->address, conn->port);
connection_mark_for_close(conn); connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1; conn->hold_open_until_flushed = 1;
} else if (!clique_mode(options) && !conn->n_circuits && } else if (!clique_mode(options) && !or_conn->n_circuits &&
(!router || !server_mode(options) || (!router || !server_mode(options) ||
!router_is_clique_mode(router))) { !router_is_clique_mode(router))) {
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
@ -692,7 +698,7 @@ run_connection_housekeeping(int i, time_t now)
conn->address, conn->port); conn->address, conn->port);
memset(&cell,0,sizeof(cell_t)); memset(&cell,0,sizeof(cell_t));
cell.command = CELL_PADDING; cell.command = CELL_PADDING;
connection_or_write_cell_to_buf(&cell, conn); connection_or_write_cell_to_buf(&cell, or_conn);
} }
} }
} }

View file

@ -576,7 +576,11 @@ typedef struct {
typedef struct buf_t buf_t; typedef struct buf_t buf_t;
typedef struct socks_request_t socks_request_t; typedef struct socks_request_t socks_request_t;
#define CONNECTION_MAGIC 0x7C3C304Eu #define BASE_CONNECTION_MAGIC 0x7C3C304Eu
#define OR_CONNECTION_MAGIC 0x7D31FF03u
#define EDGE_CONNECTION_MAGIC 0xF0374013u
#define DIR_CONNECTION_MAGIC 0x9988ffeeu
#define CONTROL_CONNECTION_MAGIC 0x8abc765du
/** Description of a connection to another host or process, and associated /** Description of a connection to another host or process, and associated
* data. * data.
@ -609,14 +613,15 @@ struct connection_t {
unsigned hold_open_until_flushed:1; /**< Despite this connection's being unsigned hold_open_until_flushed:1; /**< Despite this connection's being
* marked for close, do we flush it * marked for close, do we flush it
* before closing it? */ * before closing it? */
unsigned has_sent_end:1; /**< For debugging; only used on edge connections.
* Set once we've set the stream end, unsigned edge_has_sent_end:1; /**< For debugging; only used on edge
* connections. Set once we've set the stream end,
* and check in circuit_about_to_close_connection(). */ * and check in circuit_about_to_close_connection(). */
/** For control connections only. If set, we send extended info with control /** For control connections only. If set, we send extended info with control
* events as appropriate. */ * events as appropriate. */
unsigned int control_events_are_extended:1; unsigned int control_events_are_extended:1;
/** Used for OR conns that shouldn't get any new circs attached to them. */ /** Used for OR conns that shouldn't get any new circs attached to them. */
unsigned int is_obsolete:1; unsigned int or_is_obsolete:1;
int s; /**< Our socket; -1 if this connection is closed. */ int s; /**< Our socket; -1 if this connection is closed. */
int poll_index; /* XXXX rename. */ int poll_index; /* XXXX rename. */
@ -648,22 +653,23 @@ struct connection_t {
* we marked for close? */ * we marked for close? */
char *address; /**< FQDN (or IP) of the guy on the other end. char *address; /**< FQDN (or IP) of the guy on the other end.
* strdup into this, because free_connection frees it. */ * strdup into this, because free_connection frees it. */
uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
* connection. Exit connections only. */ /** Quasi-global identifier for this connection; used for control.c */
/* XXXX NM This can get re-used after 2**32 circuits. */
uint32_t global_identifier;
};
typedef struct connection_t connection_t;
/** DOCDOC */
typedef struct or_connection_t {
connection_t _base;
char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for
* the other side's signing key. */ * the other side's signing key. */
char *nickname; /**< Nickname of OR on other side (if any). */ char *nickname; /**< Nickname of OR on other side (if any). */
/** Nickname of planned exit node -- used with .exit support. */
char *chosen_exit_name;
/** If 1, and we fail to reach the chosen exit, stop requiring it. */
unsigned int chosen_exit_optional:1;
/** Number of times we've reassigned this application connection to
* a new circuit. We keep track because the timeout is longer if we've
* already retried several times. */
int num_socks_retries;
/* Used only by OR connections: */
tor_tls_t *tls; /**< TLS connection state (OR only.) */ tor_tls_t *tls; /**< TLS connection state (OR only.) */
/* bandwidth* and receiver_bucket only used by ORs in OPEN state: */ /* bandwidth* and receiver_bucket only used by ORs in OPEN state: */
@ -677,16 +683,19 @@ struct connection_t {
* we use? */ * we use? */
int n_circuits; /**< How many circuits use this connection as p_conn or int n_circuits; /**< How many circuits use this connection as p_conn or
* n_conn ? */ * n_conn ? */
struct connection_t *next_with_same_id; /**< Next connection with same struct or_connection_t *next_with_same_id; /**< Next connection with same
* identity digest as this one. */ * identity digest as this one. */
uint16_t next_circ_id; /**< Which circ_id do we try to use next on uint16_t next_circ_id; /**< Which circ_id do we try to use next on
* this connection? This is always in the * this connection? This is always in the
* range 0..1<<15-1. (OR only.)*/ * range 0..1<<15-1. (OR only.)*/
} or_connection_t;
typedef struct edge_connection_t {
connection_t _base;
/* Used only by edge connections: */
uint16_t stream_id; uint16_t stream_id;
struct 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 only). */ * edge, if any (Edge only). */
struct crypt_path_t *cpath_layer; /**< A pointer to which node in the circ struct crypt_path_t *cpath_layer; /**< A pointer to which node in the circ
* this conn exits at. (Edge only.) */ * this conn exits at. (Edge only.) */
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
@ -694,6 +703,36 @@ struct connection_t {
int deliver_window; /**< How many more relay cells can end at me? (Edge int deliver_window; /**< How many more relay cells can end at me? (Edge
* only.) */ * only.) */
/** Number of times we've reassigned this application connection to
* a new circuit. We keep track because the timeout is longer if we've
* already retried several times. */
int num_socks_retries;
/** Nickname of planned exit node -- used with .exit support. */
char *chosen_exit_name;
/** If 1, and we fail to reach the chosen exit, stop requiring it. */
unsigned int chosen_exit_optional:1;
/* Used only by AP connections */
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
* only.) */
struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
* connection is using. */
uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
* connection. Exit connections only. */
/* Used only by DIR and AP connections: */
char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we
* querying for? (DIR/AP only) */
} edge_connection_t;
typedef struct dir_connection_t {
connection_t _base;
/* Used only by Dir connections */ /* Used only by Dir connections */
char *requested_resource; /**< Which 'resource' did we ask the directory char *requested_resource; /**< Which 'resource' did we ask the directory
* for? */ * for? */
@ -708,31 +747,55 @@ struct connection_t {
off_t cached_dir_offset; off_t cached_dir_offset;
tor_zlib_state_t *zlib_state; tor_zlib_state_t *zlib_state;
/* Used only by AP connections */ /* Used only by DIR and AP connections: */
socks_request_t *socks_request; /**< SOCKS structure describing request (AP char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we
* only.) */ * querying for? (DIR/AP only) */
/** Quasi-global identifier for this connection; used for control.c */ char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for
/* XXXX NM This can get re-used after 2**32 circuits. */ * the directory server's signing key. */
uint32_t global_identifier; } dir_connection_t;
typedef struct control_connection_t {
connection_t _base;
/* Used only by control connections */ /* Used only by control connections */
uint32_t event_mask; uint32_t event_mask;
uint32_t incoming_cmd_len; uint32_t incoming_cmd_len;
uint32_t incoming_cmd_cur_len; uint32_t incoming_cmd_cur_len;
char *incoming_cmd; char *incoming_cmd;
/* Used only by DIR and AP connections: */
struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
* connection is using. */
char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we
* querying for? (DIR/AP only) */
/* Used only by control v0 connections */ /* Used only by control v0 connections */
uint16_t incoming_cmd_type; uint16_t incoming_cmd_type;
}; } control_connection_t;
typedef struct connection_t connection_t; #define TO_CONN(c) &(((c)->_base))
#define DOWNCAST(from, to, ptr) \
(to*) (((from*)(ptr)) - STRUCT_OFFSET(to, _base))
or_connection_t *TO_OR_CONN(connection_t *);
dir_connection_t *TO_DIR_CONN(connection_t *);
edge_connection_t *TO_EDGE_CONN(connection_t *);
control_connection_t *TO_CONTROL_CONN(connection_t *);
extern INLINE or_connection_t *TO_OR_CONN(connection_t *c)
{
tor_assert(c->magic == OR_CONNECTION_MAGIC);
return DOWNCAST(connection_t, or_connection_t, c);
}
extern INLINE dir_connection_t *TO_DIR_CONN(connection_t *c)
{
tor_assert(c->magic == DIR_CONNECTION_MAGIC);
return DOWNCAST(connection_t, dir_connection_t, c);
}
extern INLINE edge_connection_t *TO_EDGE_CONN(connection_t *c)
{
tor_assert(c->magic == EDGE_CONNECTION_MAGIC);
return DOWNCAST(connection_t, edge_connection_t, c);
}
extern INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c)
{
tor_assert(c->magic == CONTROL_CONNECTION_MAGIC);
return DOWNCAST(connection_t, control_connection_t, c);
}
typedef enum { typedef enum {
ADDR_POLICY_ACCEPT=1, ADDR_POLICY_ACCEPT=1,
@ -1072,7 +1135,7 @@ typedef struct circuit_t {
* ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */ * ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
/** The OR connection that is next in this circuit. */ /** The OR connection that is next in this circuit. */
connection_t *n_conn; or_connection_t *n_conn;
/** The identity hash of n_conn. */ /** The identity hash of n_conn. */
char n_conn_id_digest[DIGEST_LEN]; char n_conn_id_digest[DIGEST_LEN];
/** The circuit_id used in the next (forward) hop of this circuit. */ /** The circuit_id used in the next (forward) hop of this circuit. */
@ -1121,7 +1184,7 @@ typedef struct origin_circuit_t {
circuit_t _base; circuit_t _base;
/** Linked list of AP streams associated with this circuit. */ /** Linked list of AP streams associated with this circuit. */
connection_t *p_streams; edge_connection_t *p_streams;
/** Build state for this circuit. It includes the intended path /** Build state for this circuit. It includes the intended path
* length, the chosen exit router, rendezvous information, etc. * length, the chosen exit router, rendezvous information, etc.
*/ */
@ -1164,12 +1227,12 @@ typedef struct or_circuit_t {
/** The circuit_id used in the previous (backward) hop of this circuit. */ /** The circuit_id used in the previous (backward) hop of this circuit. */
circid_t p_circ_id; circid_t p_circ_id;
/** The OR connection that is previous in this circuit. */ /** The OR connection that is previous in this circuit. */
connection_t *p_conn; or_connection_t *p_conn;
/** Linked list of Exit streams associated with this circuit. */ /** Linked list of Exit streams associated with this circuit. */
connection_t *n_streams; edge_connection_t *n_streams;
/** Linked list of Exit streams associated with this circuit that are /** Linked list of Exit streams associated with this circuit that are
* still being resolved. */ * still being resolved. */
connection_t *resolving_streams; edge_connection_t *resolving_streams;
/** The cipher used by intermediate hops for cells heading toward the /** The cipher used by intermediate hops for cells heading toward the
* OP. */ * OP. */
crypto_cipher_env_t *p_crypto; crypto_cipher_env_t *p_crypto;
@ -1210,14 +1273,16 @@ or_circuit_t *TO_OR_CIRCUIT(circuit_t *x);
extern INLINE or_circuit_t *TO_OR_CIRCUIT(circuit_t *x) extern INLINE or_circuit_t *TO_OR_CIRCUIT(circuit_t *x)
{ {
tor_assert(x->magic == OR_CIRCUIT_MAGIC); tor_assert(x->magic == OR_CIRCUIT_MAGIC);
return (or_circuit_t*) (((char*)x) - STRUCT_OFFSET(or_circuit_t, _base)); //return (or_circuit_t*) (((char*)x) - STRUCT_OFFSET(or_circuit_t, _base));
return DOWNCAST(circuit_t, or_circuit_t, x);
} }
origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x); origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x);
extern INLINE origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x) extern INLINE origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x)
{ {
tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC); tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
return (origin_circuit_t*) //return (origin_circuit_t*)
(((char*)x) - STRUCT_OFFSET(origin_circuit_t, _base)); // (((char*)x) - STRUCT_OFFSET(origin_circuit_t, _base));
return DOWNCAST(circuit_t, origin_circuit_t, x);
} }
#define ALLOW_INVALID_ENTRY 1 #define ALLOW_INVALID_ENTRY 1
@ -1554,7 +1619,7 @@ origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
int need_uptime, int need_capacity, int need_uptime, int need_capacity,
int internal); int internal);
int circuit_handle_first_hop(origin_circuit_t *circ); int circuit_handle_first_hop(origin_circuit_t *circ);
void circuit_n_conn_done(connection_t *or_conn, int status); void circuit_n_conn_done(or_connection_t *or_conn, int status);
int inform_testing_reachability(void); int inform_testing_reachability(void);
int circuit_send_next_onion_skin(origin_circuit_t *circ); int circuit_send_next_onion_skin(origin_circuit_t *circ);
void circuit_note_clock_jumped(int seconds_elapsed); void circuit_note_clock_jumped(int seconds_elapsed);
@ -1593,17 +1658,18 @@ circuit_t * _circuit_get_global_list(void);
const char *circuit_state_to_string(int state); const char *circuit_state_to_string(int state);
void circuit_dump_by_conn(connection_t *conn, int severity); void circuit_dump_by_conn(connection_t *conn, int severity);
void circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id, void circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
connection_t *conn); or_connection_t *conn);
void circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id, void circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
connection_t *conn); or_connection_t *conn);
void circuit_set_state(circuit_t *circ, int state); void circuit_set_state(circuit_t *circ, int state);
void circuit_close_all_marked(void); void circuit_close_all_marked(void);
origin_circuit_t *origin_circuit_new(void); origin_circuit_t *origin_circuit_new(void);
or_circuit_t *or_circuit_new(uint16_t p_circ_id, connection_t *p_conn); or_circuit_t *or_circuit_new(uint16_t p_circ_id, or_connection_t *p_conn);
circuit_t *circuit_get_by_circid_orconn(uint16_t circ_id, connection_t *conn); circuit_t *circuit_get_by_circid_orconn(uint16_t circ_id,
int circuit_id_used_on_conn(uint16_t circ_id, connection_t *conn); or_connection_t *conn);
circuit_t *circuit_get_by_edge_conn(connection_t *conn); int circuit_id_used_on_conn(uint16_t circ_id, or_connection_t *conn);
void circuit_unlink_all_from_or_conn(connection_t *conn, int reason); circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn);
void circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason);
circuit_t *circuit_get_by_global_id(uint32_t id); circuit_t *circuit_get_by_global_id(uint32_t id);
origin_circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, origin_circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query,
uint8_t purpose); uint8_t purpose);
@ -1631,10 +1697,10 @@ void circuit_free_all(void);
void circuit_expire_building(time_t now); void circuit_expire_building(time_t now);
void circuit_remove_handled_ports(smartlist_t *needed_ports); void circuit_remove_handled_ports(smartlist_t *needed_ports);
int circuit_stream_is_being_handled(connection_t *conn, uint16_t port, int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port,
int min); int min);
void circuit_build_needed_circs(time_t now); void circuit_build_needed_circs(time_t now);
void circuit_detach_stream(circuit_t *circ, connection_t *conn); void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn);
void circuit_about_to_close_connection(connection_t *conn); void circuit_about_to_close_connection(connection_t *conn);
void circuit_has_opened(origin_circuit_t *circ); void circuit_has_opened(origin_circuit_t *circ);
void circuit_build_failed(origin_circuit_t *circ); void circuit_build_failed(origin_circuit_t *circ);
@ -1650,13 +1716,13 @@ origin_circuit_t *circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
int need_uptime, int need_capacity, int need_uptime, int need_capacity,
int is_internal); int is_internal);
void circuit_reset_failure_count(int timeout); void circuit_reset_failure_count(int timeout);
int connection_ap_handshake_attach_chosen_circuit(connection_t *conn, int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
origin_circuit_t *circ); origin_circuit_t *circ);
int connection_ap_handshake_attach_circuit(connection_t *conn); int connection_ap_handshake_attach_circuit(edge_connection_t *conn);
/********************************* command.c ***************************/ /********************************* command.c ***************************/
void command_process_cell(cell_t *cell, connection_t *conn); void command_process_cell(cell_t *cell, or_connection_t *conn);
extern uint64_t stats_n_padding_cells_processed; extern uint64_t stats_n_padding_cells_processed;
extern uint64_t stats_n_create_cells_processed; extern uint64_t stats_n_create_cells_processed;
@ -1730,15 +1796,15 @@ int connection_fetch_from_buf(char *string, size_t len, connection_t *conn);
int connection_wants_to_flush(connection_t *conn); int connection_wants_to_flush(connection_t *conn);
int connection_outbuf_too_full(connection_t *conn); int connection_outbuf_too_full(connection_t *conn);
int connection_handle_write(connection_t *conn); int connection_handle_write(connection_t *conn);
void _connection_controller_force_write(connection_t *conn); void _connection_controller_force_write(control_connection_t *conn);
void connection_write_to_buf(const char *string, size_t len, void connection_write_to_buf(const char *string, size_t len,
connection_t *conn); connection_t *conn);
void connection_write_to_buf_zlib(connection_t *conn, void connection_write_to_buf_zlib(dir_connection_t *conn,
tor_zlib_state_t *state, tor_zlib_state_t *state,
const char *data, size_t data_len, const char *data, size_t data_len,
int done); int done);
connection_t *connection_or_exact_get_by_addr_port(uint32_t addr, or_connection_t *connection_or_exact_get_by_addr_port(uint32_t addr,
uint16_t port); uint16_t port);
connection_t *connection_get_by_global_id(uint32_t id); connection_t *connection_get_by_global_id(uint32_t id);
@ -1759,34 +1825,34 @@ int connection_state_is_connecting(connection_t *conn);
char *alloc_http_authenticator(const char *authenticator); char *alloc_http_authenticator(const char *authenticator);
void assert_connection_ok(connection_t *conn, time_t now); void assert_connection_ok(connection_t *conn, time_t now);
int connection_or_nonopen_was_started_here(connection_t *conn); int connection_or_nonopen_was_started_here(or_connection_t *conn);
/********************************* connection_edge.c *************************/ /********************************* connection_edge.c *************************/
#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(connection_t *conn, int endreason, void _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
int line, const char *file); int line, const char *file);
int connection_edge_reached_eof(connection_t *conn); int connection_edge_reached_eof(edge_connection_t *conn);
int connection_edge_process_inbuf(connection_t *conn, int package_partial); int connection_edge_process_inbuf(edge_connection_t *conn, int package_partial);
int connection_edge_destroy(uint16_t circ_id, connection_t *conn); int connection_edge_destroy(uint16_t circ_id, edge_connection_t *conn);
int connection_edge_end(connection_t *conn, char reason, int connection_edge_end(edge_connection_t *conn, char reason,
crypt_path_t *cpath_layer); crypt_path_t *cpath_layer);
int connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer); int connection_edge_end_errno(edge_connection_t *conn, crypt_path_t *cpath_layer);
int connection_edge_finished_flushing(connection_t *conn); int connection_edge_finished_flushing(edge_connection_t *conn);
int connection_edge_finished_connecting(connection_t *conn); int connection_edge_finished_connecting(edge_connection_t *conn);
int connection_ap_handshake_send_begin(connection_t *ap_conn, int connection_ap_handshake_send_begin(edge_connection_t *ap_conn,
origin_circuit_t *circ); origin_circuit_t *circ);
int connection_ap_handshake_send_resolve(connection_t *ap_conn, int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn,
origin_circuit_t *circ); origin_circuit_t *circ);
int connection_ap_make_bridge(char *address, uint16_t port); int connection_ap_make_bridge(char *address, uint16_t port);
void connection_ap_handshake_socks_reply(connection_t *conn, char *reply, void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
size_t replylen, size_t replylen,
socks5_reply_status_t status); socks5_reply_status_t status);
void connection_ap_handshake_socks_resolved(connection_t *conn, void connection_ap_handshake_socks_resolved(edge_connection_t *conn,
int answer_type, int answer_type,
size_t answer_len, size_t answer_len,
const char *answer, const char *answer,
@ -1794,12 +1860,12 @@ void connection_ap_handshake_socks_resolved(connection_t *conn,
int connection_exit_begin_conn(cell_t *cell, circuit_t *circ); 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(connection_t *conn); void connection_exit_connect(edge_connection_t *conn);
int connection_edge_is_rendezvous_stream(connection_t *conn); int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit); int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_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);
int connection_ap_detach_retriable(connection_t *conn, origin_circuit_t *circ); int connection_ap_detach_retriable(edge_connection_t *conn, origin_circuit_t *circ);
void addressmap_init(void); void addressmap_init(void);
void addressmap_clean(time_t now); void addressmap_clean(time_t now);
@ -1820,7 +1886,7 @@ int address_is_in_virtual_range(const char *addr);
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); time_t max_expires);
int connection_ap_handshake_rewrite_and_attach(connection_t *conn, int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
origin_circuit_t *circ); origin_circuit_t *circ);
void set_exit_redirects(smartlist_t *lst); void set_exit_redirects(smartlist_t *lst);
@ -1831,23 +1897,23 @@ hostname_type_t parse_extended_hostname(char *address);
/********************************* connection_or.c ***************************/ /********************************* connection_or.c ***************************/
void connection_or_remove_from_identity_map(connection_t *conn); void connection_or_remove_from_identity_map(or_connection_t *conn);
void connection_or_clear_identity_map(void); void connection_or_clear_identity_map(void);
connection_t *connection_or_get_by_identity_digest(const char *digest); or_connection_t *connection_or_get_by_identity_digest(const char *digest);
int connection_or_reached_eof(connection_t *conn); int connection_or_reached_eof(or_connection_t *conn);
int connection_or_process_inbuf(connection_t *conn); int connection_or_process_inbuf(or_connection_t *conn);
int connection_or_finished_flushing(connection_t *conn); int connection_or_finished_flushing(or_connection_t *conn);
int connection_or_finished_connecting(connection_t *conn); int connection_or_finished_connecting(or_connection_t *conn);
connection_t *connection_or_connect(uint32_t addr, uint16_t port, or_connection_t *connection_or_connect(uint32_t addr, uint16_t port,
const char *id_digest); const char *id_digest);
int connection_tls_start_handshake(connection_t *conn, int receiving); int connection_tls_start_handshake(or_connection_t *conn, int receiving);
int connection_tls_continue_handshake(connection_t *conn); int connection_tls_continue_handshake(or_connection_t *conn);
void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn); void connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn);
int connection_or_send_destroy(uint16_t circ_id, connection_t *conn, int connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn,
int reason); int reason);
/********************************* control.c ***************************/ /********************************* control.c ***************************/
@ -1906,14 +1972,14 @@ void control_adjust_event_log_severity(void);
#define LOG_FN_CONN(conn, args) \ #define LOG_FN_CONN(conn, args) \
CONN_LOG_PROTECT(conn, log_fn args) CONN_LOG_PROTECT(conn, log_fn args)
int connection_control_finished_flushing(connection_t *conn); int connection_control_finished_flushing(control_connection_t *conn);
int connection_control_reached_eof(connection_t *conn); int connection_control_reached_eof(control_connection_t *conn);
int connection_control_process_inbuf(connection_t *conn); int connection_control_process_inbuf(control_connection_t *conn);
int control_event_circuit_status(origin_circuit_t *circ, int control_event_circuit_status(origin_circuit_t *circ,
circuit_status_event_t e); circuit_status_event_t e);
int control_event_stream_status(connection_t *conn, stream_status_event_t e); int control_event_stream_status(edge_connection_t *conn, stream_status_event_t e);
int control_event_or_conn_status(connection_t *conn, or_conn_status_event_t e); int control_event_or_conn_status(or_connection_t *conn, or_conn_status_event_t e);
int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written); int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written);
void control_event_logmsg(int severity, unsigned int domain, const char *msg); void control_event_logmsg(int severity, unsigned int domain, const char *msg);
int control_event_descriptors_changed(smartlist_t *routers); int control_event_descriptors_changed(smartlist_t *routers);
@ -1959,11 +2025,11 @@ void directory_initiate_command_routerstatus(routerstatus_t *status,
int parse_http_response(const char *headers, int *code, time_t *date, int parse_http_response(const char *headers, int *code, time_t *date,
int *compression, char **response); int *compression, char **response);
int connection_dir_reached_eof(connection_t *conn); int connection_dir_reached_eof(dir_connection_t *conn);
int connection_dir_process_inbuf(connection_t *conn); int connection_dir_process_inbuf(dir_connection_t *conn);
int connection_dir_finished_flushing(connection_t *conn); int connection_dir_finished_flushing(dir_connection_t *conn);
int connection_dir_finished_connecting(connection_t *conn); int connection_dir_finished_connecting(dir_connection_t *conn);
void connection_dir_request_failed(connection_t *conn); void connection_dir_request_failed(dir_connection_t *conn);
int dir_split_resource_into_fingerprints(const char *resource, int dir_split_resource_into_fingerprints(const char *resource,
smartlist_t *fp_out, int *compresseed_out, smartlist_t *fp_out, int *compresseed_out,
int decode_hex, int sort_uniq); int decode_hex, int sort_uniq);
@ -1971,7 +2037,7 @@ char *directory_dump_request_log(void);
/********************************* dirserv.c ***************************/ /********************************* dirserv.c ***************************/
int connection_dirserv_flushed_some(connection_t *conn); int connection_dirserv_flushed_some(dir_connection_t *conn);
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk); int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
int dirserv_parse_fingerprint_file(const char *fname); int dirserv_parse_fingerprint_file(const char *fname);
void dirserv_free_fingerprint_list(void); void dirserv_free_fingerprint_list(void);
@ -2021,11 +2087,11 @@ int connection_dns_finished_flushing(connection_t *conn);
int connection_dns_reached_eof(connection_t *conn); int connection_dns_reached_eof(connection_t *conn);
int connection_dns_process_inbuf(connection_t *conn); int connection_dns_process_inbuf(connection_t *conn);
void dnsworkers_rotate(void); void dnsworkers_rotate(void);
void connection_dns_remove(connection_t *conn); void connection_dns_remove(edge_connection_t *conn);
void assert_connection_edge_not_dns_pending(connection_t *conn); void assert_connection_edge_not_dns_pending(edge_connection_t *conn);
void assert_all_pending_dns_resolves_ok(void); void assert_all_pending_dns_resolves_ok(void);
void dns_cancel_pending_resolve(char *question); void dns_cancel_pending_resolve(char *question);
int dns_resolve(connection_t *exitconn); int dns_resolve(edge_connection_t *exitconn);
/********************************* hibernate.c **********************/ /********************************* hibernate.c **********************/
@ -2146,12 +2212,12 @@ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
void relay_header_pack(char *dest, const relay_header_t *src); void relay_header_pack(char *dest, const relay_header_t *src);
void relay_header_unpack(relay_header_t *dest, const char *src); void relay_header_unpack(relay_header_t *dest, const char *src);
int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int connection_edge_send_command(edge_connection_t *fromconn, circuit_t *circ,
int relay_command, const char *payload, int relay_command, const char *payload,
size_t payload_len, size_t payload_len,
crypt_path_t *cpath_layer); crypt_path_t *cpath_layer);
int connection_edge_package_raw_inbuf(connection_t *conn, int package_partial); int connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial);
void connection_edge_consider_sending_sendme(connection_t *conn); void connection_edge_consider_sending_sendme(edge_connection_t *conn);
socks5_reply_status_t connection_edge_end_reason_socks5_response(int reason); socks5_reply_status_t connection_edge_end_reason_socks5_response(int reason);
int errno_to_end_reason(int e); int errno_to_end_reason(int e);
@ -2283,7 +2349,7 @@ void rend_service_rendezvous_has_opened(origin_circuit_t *circuit);
int rend_service_introduce(origin_circuit_t *circuit, const char *request, int rend_service_introduce(origin_circuit_t *circuit, const char *request,
size_t request_len); size_t request_len);
void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc); void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc);
int rend_service_set_connection_addr_port(connection_t *conn, int rend_service_set_connection_addr_port(edge_connection_t *conn,
origin_circuit_t *circ); origin_circuit_t *circ);
void rend_service_dump_stats(int severity); void rend_service_dump_stats(int severity);
void rend_service_free_all(void); void rend_service_free_all(void);
@ -2332,7 +2398,7 @@ void mark_my_descriptor_dirty(void);
void check_descriptor_bandwidth_changed(time_t now); void check_descriptor_bandwidth_changed(time_t now);
void check_descriptor_ipaddress_changed(time_t now); void check_descriptor_ipaddress_changed(time_t now);
void router_new_address_suggestion(const char *suggestion); void router_new_address_suggestion(const char *suggestion);
int router_compare_to_my_exit_policy(connection_t *conn); int router_compare_to_my_exit_policy(edge_connection_t *conn);
routerinfo_t *router_get_my_routerinfo(void); routerinfo_t *router_get_my_routerinfo(void);
const char *router_get_my_descriptor(void); const char *router_get_my_descriptor(void);
int router_digest_is_me(const char *digest); int router_digest_is_me(const char *digest);

View file

@ -16,19 +16,19 @@ const char relay_c_id[] =
static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction, static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
crypt_path_t **layer_hint, char *recognized); crypt_path_t **layer_hint, char *recognized);
static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
int cell_direction); int cell_direction);
static int static int
connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
connection_t *conn, edge_connection_t *conn,
crypt_path_t *layer_hint); crypt_path_t *layer_hint);
static void static void
circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint); circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint);
static void static void
circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint); circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint);
static int static int
circuit_resume_edge_reading_helper(connection_t *conn, circuit_resume_edge_reading_helper(edge_connection_t *conn,
circuit_t *circ, circuit_t *circ,
crypt_path_t *layer_hint); crypt_path_t *layer_hint);
static int static int
@ -144,7 +144,7 @@ relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
int int
circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
{ {
connection_t *conn=NULL; or_connection_t *or_conn=NULL;
crypt_path_t *layer_hint=NULL; crypt_path_t *layer_hint=NULL;
char recognized=0; char recognized=0;
int reason; int reason;
@ -162,7 +162,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
} }
if (recognized) { if (recognized) {
conn = relay_lookup_conn(circ, cell, cell_direction); edge_connection_t *conn = relay_lookup_conn(circ, cell, cell_direction);
if (cell_direction == CELL_DIRECTION_OUT) { if (cell_direction == CELL_DIRECTION_OUT) {
++stats_n_relay_cells_delivered; ++stats_n_relay_cells_delivered;
log_debug(LD_OR,"Sending away from origin."); log_debug(LD_OR,"Sending away from origin.");
@ -190,16 +190,16 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
/* not recognized. pass it on. */ /* not recognized. pass it on. */
if (cell_direction == CELL_DIRECTION_OUT) { if (cell_direction == CELL_DIRECTION_OUT) {
cell->circ_id = circ->n_circ_id; /* switch it */ cell->circ_id = circ->n_circ_id; /* switch it */
conn = circ->n_conn; or_conn = circ->n_conn;
} else if (! CIRCUIT_IS_ORIGIN(circ)) { } else if (! CIRCUIT_IS_ORIGIN(circ)) {
cell->circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; /* switch it */ cell->circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; /* switch it */
conn = TO_OR_CIRCUIT(circ)->p_conn; or_conn = TO_OR_CIRCUIT(circ)->p_conn;
} else { } else {
// XXXX NM WARN. // XXXX NM WARN.
return 0; return 0;
} }
if (!conn) { if (!or_conn) {
// XXXX Can this splice stuff be done more cleanly? // XXXX Can this splice stuff be done more cleanly?
if (! CIRCUIT_IS_ORIGIN(circ) && if (! CIRCUIT_IS_ORIGIN(circ) &&
TO_OR_CIRCUIT(circ)->rend_splice && TO_OR_CIRCUIT(circ)->rend_splice &&
@ -225,7 +225,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
log_debug(LD_OR,"Passing on unrecognized cell."); log_debug(LD_OR,"Passing on unrecognized cell.");
++stats_n_relay_cells_relayed; ++stats_n_relay_cells_relayed;
connection_or_write_cell_to_buf(cell, conn); connection_or_write_cell_to_buf(cell, or_conn);
return 0; return 0;
} }
@ -323,7 +323,7 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
int cell_direction, int cell_direction,
crypt_path_t *layer_hint) crypt_path_t *layer_hint)
{ {
connection_t *conn; /* where to send the cell */ or_connection_t *conn; /* where to send the cell */
if (cell_direction == CELL_DIRECTION_OUT) { if (cell_direction == CELL_DIRECTION_OUT) {
crypt_path_t *thishop; /* counter for repeated crypts */ crypt_path_t *thishop; /* counter for repeated crypts */
@ -369,10 +369,10 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
/** If cell's stream_id matches the stream_id of any conn that's /** If cell's stream_id matches the stream_id of any conn that's
* attached to circ, return that conn, else return NULL. * attached to circ, return that conn, else return NULL.
*/ */
static connection_t * static edge_connection_t *
relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction) relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
{ {
connection_t *tmpconn; edge_connection_t *tmpconn;
relay_header_t rh; relay_header_t rh;
relay_header_unpack(&rh, cell->payload); relay_header_unpack(&rh, cell->payload);
@ -387,7 +387,8 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
if (CIRCUIT_IS_ORIGIN(circ)) { if (CIRCUIT_IS_ORIGIN(circ)) {
for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn; for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
tmpconn=tmpconn->next_stream) { tmpconn=tmpconn->next_stream) {
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) { if (rh.stream_id == tmpconn->stream_id &&
!tmpconn->_base.marked_for_close) {
log_debug(LD_APP,"found conn for stream %d.", rh.stream_id); log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
return tmpconn; return tmpconn;
} }
@ -395,7 +396,7 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
} else { } else {
for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn; for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
tmpconn=tmpconn->next_stream) { tmpconn=tmpconn->next_stream) {
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) { if (rh.stream_id == tmpconn->stream_id && !tmpconn->_base.marked_for_close) {
log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id); log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
if (cell_direction == CELL_DIRECTION_OUT || if (cell_direction == CELL_DIRECTION_OUT ||
connection_edge_is_rendezvous_stream(tmpconn)) connection_edge_is_rendezvous_stream(tmpconn))
@ -404,7 +405,7 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
} }
for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn; for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn;
tmpconn=tmpconn->next_stream) { tmpconn=tmpconn->next_stream) {
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) { if (rh.stream_id == tmpconn->stream_id && !tmpconn->_base.marked_for_close) {
log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id); log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
return tmpconn; return tmpconn;
} }
@ -452,7 +453,7 @@ relay_header_unpack(relay_header_t *dest, const char *src)
* return -1. Else return 0. * return -1. Else return 0.
*/ */
int int
connection_edge_send_command(connection_t *fromconn, circuit_t *circ, connection_edge_send_command(edge_connection_t *fromconn, circuit_t *circ,
int relay_command, const char *payload, int relay_command, const char *payload,
size_t payload_len, crypt_path_t *cpath_layer) size_t payload_len, crypt_path_t *cpath_layer)
{ {
@ -461,22 +462,22 @@ connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
int cell_direction; int cell_direction;
/* XXXX NM Split this function into a separate versions per circuit type? */ /* XXXX NM Split this function into a separate versions per circuit type? */
if (fromconn && fromconn->marked_for_close) { if (fromconn && fromconn->_base.marked_for_close) {
log_warn(LD_BUG, log_warn(LD_BUG,
"Bug: called on conn that's already marked for close at %s:%d.", "Bug: called on conn that's already marked for close at %s:%d.",
fromconn->marked_for_close_file, fromconn->marked_for_close); fromconn->_base.marked_for_close_file, fromconn->_base.marked_for_close);
return 0; return 0;
} }
if (!circ) { if (!circ) {
tor_assert(fromconn); tor_assert(fromconn);
if (fromconn->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(fromconn, END_STREAM_REASON_INTERNAL);
} else { } else {
log_info(LD_EXIT,"no circ. Closing conn."); log_info(LD_EXIT,"no circ. Closing conn.");
fromconn->has_sent_end = 1; /* no circ to send to */ fromconn->_base.edge_has_sent_end = 1; /* no circ to send to */
connection_mark_for_close(fromconn); connection_mark_for_close(TO_CONN(fromconn));
} }
return -1; return -1;
} }
@ -665,7 +666,7 @@ edge_reason_is_retriable(int reason)
static int static int
connection_edge_process_end_not_open( connection_edge_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,
connection_t *conn, crypt_path_t *layer_hint) edge_connection_t *conn, crypt_path_t *layer_hint)
{ {
struct in_addr in; struct in_addr in;
routerinfo_t *exitrouter; routerinfo_t *exitrouter;
@ -673,7 +674,7 @@ connection_edge_process_end_not_open(
(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) &&
conn->type == CONN_TYPE_AP) { conn->_base.type == CONN_TYPE_AP) {
log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.", log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
safe_str(conn->socks_request->address), safe_str(conn->socks_request->address),
connection_edge_end_reason_str(reason)); connection_edge_end_reason_str(reason));
@ -775,12 +776,12 @@ connection_edge_process_end_not_open(
log_info(LD_APP, log_info(LD_APP,
"Edge got end (%s) before we're connected. Marking for close.", "Edge got end (%s) before we're connected. Marking for close.",
connection_edge_end_reason_str(rh->length > 0 ? reason : -1)); connection_edge_end_reason_str(rh->length > 0 ? reason : -1));
if (conn->type == CONN_TYPE_AP) { if (conn->_base.type == CONN_TYPE_AP) {
circuit_log_path(LOG_INFO,LD_APP,circ); circuit_log_path(LOG_INFO,LD_APP,circ);
connection_mark_unattached_ap(conn, reason); connection_mark_unattached_ap(conn, reason);
} else { } else {
conn->has_sent_end = 1; /* we just got an 'end', don't need to send one */ conn->_base.edge_has_sent_end = 1; /* we just got an 'end', don't need to send one */
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
} }
return 0; return 0;
} }
@ -795,7 +796,7 @@ connection_edge_process_end_not_open(
static int static int
connection_edge_process_relay_cell_not_open( connection_edge_process_relay_cell_not_open(
relay_header_t *rh, cell_t *cell, circuit_t *circ, relay_header_t *rh, cell_t *cell, circuit_t *circ,
connection_t *conn, crypt_path_t *layer_hint) edge_connection_t *conn, crypt_path_t *layer_hint)
{ {
if (rh->command == RELAY_COMMAND_END) { if (rh->command == RELAY_COMMAND_END) {
if (CIRCUIT_IS_ORIGIN(circ)) if (CIRCUIT_IS_ORIGIN(circ))
@ -806,17 +807,17 @@ connection_edge_process_relay_cell_not_open(
return 0; return 0;
} }
if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) { if (conn->_base.type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) {
tor_assert(CIRCUIT_IS_ORIGIN(circ)); tor_assert(CIRCUIT_IS_ORIGIN(circ));
if (conn->state != AP_CONN_STATE_CONNECT_WAIT) { if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) {
log_warn(LD_APP,"Got 'connected' while not in state connect_wait. " log_warn(LD_APP,"Got 'connected' while not in state connect_wait. "
"Dropping."); "Dropping.");
return 0; return 0;
} }
// log_fn(LOG_INFO,"Connected! Notifying application."); // log_fn(LOG_INFO,"Connected! Notifying application.");
conn->state = AP_CONN_STATE_OPEN; conn->_base.state = AP_CONN_STATE_OPEN;
log_info(LD_APP,"'connected' received after %d seconds.", log_info(LD_APP,"'connected' received after %d seconds.",
(int)(time(NULL) - conn->timestamp_lastread)); (int)(time(NULL) - conn->_base.timestamp_lastread));
if (rh->length >= 4) { if (rh->length >= 4) {
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE)); uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
int ttl; int ttl;
@ -840,15 +841,15 @@ connection_edge_process_relay_cell_not_open(
/* handle anything that might have queued */ /* handle anything that might have queued */
if (connection_edge_package_raw_inbuf(conn, 1) < 0) { if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
/* (We already sent an end cell if possible) */ /* (We already sent an end cell if possible) */
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return 0; return 0;
} }
return 0; return 0;
} }
if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_RESOLVED) { if (conn->_base.type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_RESOLVED) {
int ttl; int ttl;
int answer_len; int answer_len;
if (conn->state != AP_CONN_STATE_RESOLVE_WAIT) { if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
log_warn(LD_APP,"Got a 'resolved' cell while not in state resolve_wait. " log_warn(LD_APP,"Got a 'resolved' cell while not in state resolve_wait. "
"Dropping."); "Dropping.");
return 0; return 0;
@ -877,8 +878,8 @@ connection_edge_process_relay_cell_not_open(
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Got an unexpected relay command %d, in state %d (%s). Dropping.", "Got an unexpected relay command %d, in state %d (%s). Dropping.",
rh->command, conn->state, rh->command, conn->_base.state,
conn_state_to_string(conn->type, conn->state)); conn_state_to_string(conn->_base.type, conn->_base.state));
return 0; /* for forward compatibility, don't kill the circuit */ return 0; /* for forward compatibility, don't kill the circuit */
// connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL, // connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL,
// conn->cpath_layer); // conn->cpath_layer);
@ -897,7 +898,7 @@ connection_edge_process_relay_cell_not_open(
*/ */
static int static int
connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
connection_t *conn, edge_connection_t *conn,
crypt_path_t *layer_hint) crypt_path_t *layer_hint)
{ {
static int num_seen=0; static int num_seen=0;
@ -922,7 +923,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
/* either conn is NULL, in which case we've got a control cell, or else /* either conn is NULL, in which case we've got a control cell, or else
* conn points to the recognized stream. */ * conn points to the recognized stream. */
if (conn && !connection_state_is_open(conn)) if (conn && !connection_state_is_open(TO_CONN(conn)))
return connection_edge_process_relay_cell_not_open( return connection_edge_process_relay_cell_not_open(
&rh, cell, circ, conn, layer_hint); &rh, cell, circ, conn, layer_hint);
@ -950,7 +951,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
"(relay data) circ deliver_window below 0. Killing."); "(relay data) circ deliver_window below 0. Killing.");
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL, connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL,
conn->cpath_layer); conn->cpath_layer);
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return -END_CIRC_REASON_TORPROTOCOL; return -END_CIRC_REASON_TORPROTOCOL;
} }
log_debug(domain,"circ deliver_window now %d.", layer_hint ? log_debug(domain,"circ deliver_window now %d.", layer_hint ?
@ -971,7 +972,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
stats_n_data_bytes_received += rh.length; stats_n_data_bytes_received += rh.length;
connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE, connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE,
rh.length, conn); rh.length, TO_CONN(conn));
connection_edge_consider_sending_sendme(conn); connection_edge_consider_sending_sendme(conn);
return 0; return 0;
case RELAY_COMMAND_END: case RELAY_COMMAND_END:
@ -983,7 +984,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
} }
/* XXX add to this log_fn the exit node's nickname? */ /* XXX add to this log_fn the exit node's nickname? */
log_info(domain,"%d: end cell (%s) for stream %d. Removing stream.", log_info(domain,"%d: end cell (%s) for stream %d. Removing stream.",
conn->s, conn->_base.s,
connection_edge_end_reason_str(rh.length > 0 ? connection_edge_end_reason_str(rh.length > 0 ?
*(char *)(cell->payload+RELAY_HEADER_SIZE) : -1), *(char *)(cell->payload+RELAY_HEADER_SIZE) : -1),
conn->stream_id); conn->stream_id);
@ -991,12 +992,12 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
log_warn(LD_BUG, log_warn(LD_BUG,
"Bug: open stream hasn't sent socks answer yet? Closing."); "Bug: 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->has_sent_end = 1; conn->_base.edge_has_sent_end = 1;
if (!conn->marked_for_close) { if (!conn->_base.marked_for_close) {
/* only mark it if not already marked. it's possible to /* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */ * get the 'end' right around when the client hangs up on us. */
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
conn->hold_open_until_flushed = 1; conn->_base.hold_open_until_flushed = 1;
} }
return 0; return 0;
case RELAY_COMMAND_EXTEND: case RELAY_COMMAND_EXTEND:
@ -1076,11 +1077,11 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
conn->package_window += STREAMWINDOW_INCREMENT; conn->package_window += STREAMWINDOW_INCREMENT;
log_debug(domain,"stream-level sendme, packagewindow now %d.", log_debug(domain,"stream-level sendme, packagewindow now %d.",
conn->package_window); conn->package_window);
connection_start_reading(conn); connection_start_reading(TO_CONN(conn));
/* handle whatever might still be on the inbuf */ /* handle whatever might still be on the inbuf */
if (connection_edge_package_raw_inbuf(conn, 1) < 0) { if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
/* (We already sent an end cell if possible) */ /* (We already sent an end cell if possible) */
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
return 0; return 0;
} }
return 0; return 0;
@ -1139,7 +1140,7 @@ uint64_t stats_n_data_bytes_received = 0;
* be marked for close, else return 0. * be marked for close, else return 0.
*/ */
int int
connection_edge_package_raw_inbuf(connection_t *conn, int package_partial) 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];
@ -1147,11 +1148,11 @@ connection_edge_package_raw_inbuf(connection_t *conn, int package_partial)
unsigned domain = conn->cpath_layer ? LD_APP : LD_EXIT; unsigned domain = conn->cpath_layer ? LD_APP : LD_EXIT;
tor_assert(conn); tor_assert(conn);
tor_assert(!connection_speaks_cells(conn));
if (conn->marked_for_close) { if (conn->_base.marked_for_close) {
log_warn(LD_BUG, log_warn(LD_BUG,
"Bug: called on conn that's already marked for close at %s:%d.", "Bug: called on conn that's already marked for close at %s:%d.",
conn->marked_for_close_file, conn->marked_for_close); conn->_base.marked_for_close_file, conn->_base.marked_for_close);
return 0; return 0;
} }
@ -1169,11 +1170,11 @@ repeat_connection_edge_package_raw_inbuf:
if (conn->package_window <= 0) { if (conn->package_window <= 0) {
log_info(domain,"called with package_window %d. Skipping.", log_info(domain,"called with package_window %d. Skipping.",
conn->package_window); conn->package_window);
connection_stop_reading(conn); connection_stop_reading(TO_CONN(conn));
return 0; return 0;
} }
amount_to_process = buf_datalen(conn->inbuf); amount_to_process = buf_datalen(conn->_base.inbuf);
if (!amount_to_process) if (!amount_to_process)
return 0; return 0;
@ -1189,10 +1190,10 @@ repeat_connection_edge_package_raw_inbuf:
stats_n_data_bytes_packaged += length; stats_n_data_bytes_packaged += length;
stats_n_data_cells_packaged += 1; stats_n_data_cells_packaged += 1;
connection_fetch_from_buf(payload, length, conn); connection_fetch_from_buf(payload, length, TO_CONN(conn));
log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->s, log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->_base.s,
(int)length, (int)buf_datalen(conn->inbuf)); (int)length, (int)buf_datalen(conn->_base.inbuf));
if (connection_edge_send_command(conn, circ, RELAY_COMMAND_DATA, if (connection_edge_send_command(conn, circ, RELAY_COMMAND_DATA,
payload, length, conn->cpath_layer) < 0) payload, length, conn->cpath_layer) < 0)
@ -1208,7 +1209,7 @@ repeat_connection_edge_package_raw_inbuf:
} }
if (--conn->package_window <= 0) { /* is it 0 after decrement? */ if (--conn->package_window <= 0) { /* is it 0 after decrement? */
connection_stop_reading(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, conn->cpath_layer);
return 0; /* don't process the inbuf any more */ return 0; /* don't process the inbuf any more */
@ -1226,11 +1227,11 @@ repeat_connection_edge_package_raw_inbuf:
* low, send back a suitable number of stream-level sendme cells. * low, send back a suitable number of stream-level sendme cells.
*/ */
void void
connection_edge_consider_sending_sendme(connection_t *conn) connection_edge_consider_sending_sendme(edge_connection_t *conn)
{ {
circuit_t *circ; circuit_t *circ;
if (connection_outbuf_too_full(conn)) if (connection_outbuf_too_full(TO_CONN(conn)))
return; return;
circ = circuit_get_by_edge_conn(conn); circ = circuit_get_by_edge_conn(conn);
@ -1244,7 +1245,7 @@ connection_edge_consider_sending_sendme(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->cpath_layer?LD_APP:LD_EXIT,
"Outbuf %d, Queueing stream sendme.", "Outbuf %d, Queueing stream sendme.",
(int)conn->outbuf_flushlen); (int)conn->_base.outbuf_flushlen);
conn->deliver_window += STREAMWINDOW_INCREMENT; conn->deliver_window += STREAMWINDOW_INCREMENT;
if (connection_edge_send_command(conn, circ, RELAY_COMMAND_SENDME, if (connection_edge_send_command(conn, circ, RELAY_COMMAND_SENDME,
NULL, 0, conn->cpath_layer) < 0) { NULL, 0, conn->cpath_layer) < 0) {
@ -1278,21 +1279,21 @@ circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
* of a linked list of edge streams that should each be considered. * of a linked list of edge streams that should each be considered.
*/ */
static int static int
circuit_resume_edge_reading_helper(connection_t *conn, circuit_resume_edge_reading_helper(edge_connection_t *conn,
circuit_t *circ, circuit_t *circ,
crypt_path_t *layer_hint) crypt_path_t *layer_hint)
{ {
for ( ; conn; conn=conn->next_stream) { for ( ; conn; conn=conn->next_stream) {
if (conn->marked_for_close) if (conn->_base.marked_for_close)
continue; continue;
if ((!layer_hint && conn->package_window > 0) || if ((!layer_hint && conn->package_window > 0) ||
(layer_hint && conn->package_window > 0 && (layer_hint && conn->package_window > 0 &&
conn->cpath_layer == layer_hint)) { conn->cpath_layer == layer_hint)) {
connection_start_reading(conn); connection_start_reading(TO_CONN(conn));
/* handle whatever might still be on the inbuf */ /* handle whatever might still be on the inbuf */
if (connection_edge_package_raw_inbuf(conn, 1)<0) { if (connection_edge_package_raw_inbuf(conn, 1)<0) {
/* (We already sent an end cell if possible) */ /* (We already sent an end cell if possible) */
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
continue; continue;
} }
@ -1315,7 +1316,7 @@ circuit_resume_edge_reading_helper(connection_t *conn,
static int static int
circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint) circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
{ {
connection_t *conn = NULL; edge_connection_t *conn = NULL;
unsigned domain = layer_hint ? LD_APP : LD_EXIT; unsigned domain = layer_hint ? LD_APP : LD_EXIT;
if (!layer_hint) { if (!layer_hint) {
@ -1325,7 +1326,7 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
if (circ->package_window <= 0) { if (circ->package_window <= 0) {
log_debug(domain,"yes, not-at-origin. stopped."); log_debug(domain,"yes, not-at-origin. stopped.");
for (conn = or_circ->n_streams; conn; conn=conn->next_stream) for (conn = or_circ->n_streams; conn; conn=conn->next_stream)
connection_stop_reading(conn); connection_stop_reading(TO_CONN(conn));
return 1; return 1;
} }
return 0; return 0;
@ -1344,7 +1345,7 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
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(conn); connection_stop_reading(TO_CONN(conn));
return 1; return 1;
} }
return 0; return 0;

View file

@ -430,7 +430,7 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
void void
rend_client_desc_here(const char *query) rend_client_desc_here(const char *query)
{ {
connection_t *conn; edge_connection_t *conn;
rend_cache_entry_t *entry; rend_cache_entry_t *entry;
time_t now = time(NULL); time_t now = time(NULL);
int i, n_conns; int i, n_conns;
@ -439,25 +439,26 @@ rend_client_desc_here(const char *query)
get_connection_array(&carray, &n_conns); get_connection_array(&carray, &n_conns);
for (i = 0; i < n_conns; ++i) { for (i = 0; i < n_conns; ++i) {
conn = carray[i]; if (carray[i]->type != CONN_TYPE_AP ||
if (conn->type != CONN_TYPE_AP || carray[i]->state != AP_CONN_STATE_RENDDESC_WAIT ||
conn->state != AP_CONN_STATE_RENDDESC_WAIT || carray[i]->marked_for_close)
conn->marked_for_close ||
rend_cmp_service_ids(query, conn->rend_query))
continue; continue;
assert_connection_ok(conn, now); conn = TO_EDGE_CONN(carray[i]);
if (rend_cmp_service_ids(query, conn->rend_query))
continue;
assert_connection_ok(TO_CONN(conn), now);
if (rend_cache_lookup_entry(conn->rend_query, -1, &entry) == 1 && if (rend_cache_lookup_entry(conn->rend_query, -1, &entry) == 1 &&
entry->parsed->n_intro_points > 0) { entry->parsed->n_intro_points > 0) {
/* 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->state = AP_CONN_STATE_CIRCUIT_WAIT; conn->_base.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->timestamp_created = now; conn->_base.timestamp_created = now;
conn->timestamp_lastread = now; conn->_base.timestamp_lastread = now;
conn->timestamp_lastwritten = now; conn->_base.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 */

View file

@ -1121,7 +1121,7 @@ rend_service_dump_stats(int severity)
* or 0 for success. * or 0 for success.
*/ */
int int
rend_service_set_connection_addr_port(connection_t *conn, rend_service_set_connection_addr_port(edge_connection_t *conn,
origin_circuit_t *circ) origin_circuit_t *circ)
{ {
rend_service_t *service; rend_service_t *service;
@ -1142,14 +1142,14 @@ rend_service_set_connection_addr_port(connection_t *conn,
} }
for (i = 0; i < smartlist_len(service->ports); ++i) { for (i = 0; i < smartlist_len(service->ports); ++i) {
p = smartlist_get(service->ports, i); p = smartlist_get(service->ports, i);
if (conn->port == p->virtual_port) { if (conn->_base.port == p->virtual_port) {
conn->addr = p->real_addr; conn->_base.addr = p->real_addr;
conn->port = p->real_port; conn->_base.port = p->real_port;
return 0; return 0;
} }
} }
log_info(LD_REND, "No virtual port mapping exists for port %d on service %s", log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
conn->port,serviceid); conn->_base.port,serviceid);
return -1; return -1;
} }

View file

@ -650,16 +650,16 @@ router_upload_dir_desc_to_dirservers(int force)
* conn. Return 0 if we accept; non-0 if we reject. * conn. Return 0 if we accept; non-0 if we reject.
*/ */
int int
router_compare_to_my_exit_policy(connection_t *conn) router_compare_to_my_exit_policy(edge_connection_t *conn)
{ {
tor_assert(desc_routerinfo); tor_assert(desc_routerinfo);
/* make sure it's resolved to something. this way we can't get a /* make sure it's resolved to something. this way we can't get a
'maybe' below. */ 'maybe' below. */
if (!conn->addr) if (!conn->_base.addr)
return -1; return -1;
return compare_addr_to_addr_policy(conn->addr, conn->port, return compare_addr_to_addr_policy(conn->_base.addr, conn->_base.port,
desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED; desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED;
} }

View file

@ -1705,13 +1705,13 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
/* mark-for-close connections using the old key, so we can /* mark-for-close connections using the old key, so we can
* make new ones with the new key. * make new ones with the new key.
*/ */
connection_t *conn; or_connection_t *conn;
while ((conn = connection_or_get_by_identity_digest( while ((conn = connection_or_get_by_identity_digest(
old_router->cache_info.identity_digest))) { old_router->cache_info.identity_digest))) {
log_info(LD_DIR,"Closing conn to router '%s'; there is now a named " log_info(LD_DIR,"Closing conn to router '%s'; there is now a named "
"router with that name.", "router with that name.",
old_router->nickname); old_router->nickname);
connection_mark_for_close(conn); connection_mark_for_close(TO_CONN(conn));
} }
routerlist_remove(routerlist, old_router, i--, 0); routerlist_remove(routerlist, old_router, i--, 0);
} else if (old_router->is_named) { } else if (old_router->is_named) {
@ -3317,8 +3317,9 @@ list_pending_descriptor_downloads(digestmap_t *result)
if (conn->type == CONN_TYPE_DIR && if (conn->type == CONN_TYPE_DIR &&
conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC && conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
!conn->marked_for_close) { !conn->marked_for_close) {
if (!strcmpstart(conn->requested_resource, prefix)) dir_connection_t *dir_conn = TO_DIR_CONN(conn);
dir_split_resource_into_fingerprints(conn->requested_resource+p_len, if (!strcmpstart(dir_conn->requested_resource, prefix))
dir_split_resource_into_fingerprints(dir_conn->requested_resource+p_len,
tmp, NULL, 1, 0); tmp, NULL, 1, 0);
} }
} }