diff options
author | Nick Mathewson <nickm@torproject.org> | 2006-07-26 19:07:26 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2006-07-26 19:07:26 +0000 |
commit | 4ff4577beb7b7aa286059a5070b23357fff48bf3 (patch) | |
tree | 87c11a323c91def209efc2d0eb79b768f8f2e804 /src | |
parent | 18771e851fab7ec12051636eda1dad7e13b11095 (diff) | |
download | tor-4ff4577beb7b7aa286059a5070b23357fff48bf3.tar.gz tor-4ff4577beb7b7aa286059a5070b23357fff48bf3.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/or/circuitbuild.c | 45 | ||||
-rw-r--r-- | src/or/circuitlist.c | 68 | ||||
-rw-r--r-- | src/or/circuituse.c | 57 | ||||
-rw-r--r-- | src/or/command.c | 28 | ||||
-rw-r--r-- | src/or/connection.c | 408 | ||||
-rw-r--r-- | src/or/connection_edge.c | 307 | ||||
-rw-r--r-- | src/or/connection_or.c | 196 | ||||
-rw-r--r-- | src/or/control.c | 322 | ||||
-rw-r--r-- | src/or/cpuworker.c | 5 | ||||
-rw-r--r-- | src/or/directory.c | 253 | ||||
-rw-r--r-- | src/or/dirserv.c | 25 | ||||
-rw-r--r-- | src/or/dns.c | 140 | ||||
-rw-r--r-- | src/or/hibernate.c | 7 | ||||
-rw-r--r-- | src/or/main.c | 52 | ||||
-rw-r--r-- | src/or/or.h | 280 | ||||
-rw-r--r-- | src/or/relay.c | 135 | ||||
-rw-r--r-- | src/or/rendclient.c | 23 | ||||
-rw-r--r-- | src/or/rendservice.c | 10 | ||||
-rw-r--r-- | src/or/router.c | 6 | ||||
-rw-r--r-- | src/or/routerlist.c | 9 |
20 files changed, 1275 insertions, 1101 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index e58e253f48..7a256371ba 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -60,14 +60,13 @@ static void entry_guards_changed(void); * Return it, or 0 if can't get a unique circ_id. */ 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 attempts=0; uint16_t high_bit; tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_OR); high_bit = (conn->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0; do { /* 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) { crypt_path_t *firsthop; - connection_t *n_conn; + or_connection_t *n_conn; char tmpbuf[INET_NTOA_BUF_LEN]; 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 * (i.e. old or broken) and the other side will let us make a second * connection without dropping it immediately... */ - if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN || - (n_conn->is_obsolete && + if (!n_conn || n_conn->_base.state != OR_CONN_STATE_OPEN || + (n_conn->_base.or_is_obsolete && router_digest_version_as_new_as(firsthop->extend_info->identity_digest, "0.1.1.9-alpha-cvs"))) { /* not currently connected */ circ->_base.n_addr = firsthop->extend_info->addr; 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, firsthop->extend_info->port, firsthop->extend_info->identity_digest); @@ -323,8 +322,8 @@ circuit_handle_first_hop(origin_circuit_t *circ) */ return 0; } else { /* it's already open. use it. */ - circ->_base.n_addr = n_conn->addr; - circ->_base.n_port = n_conn->port; + circ->_base.n_addr = n_conn->_base.addr; + circ->_base.n_port = n_conn->_base.port; circ->_base.n_conn = n_conn; log_debug(LD_CIRC,"Conn open. Delivering first onion skin."); 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. */ 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; 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->n_conn); - tor_assert(circ->n_conn->type == CONN_TYPE_OR); tor_assert(payload); tor_assert(cell_type == CELL_CREATE || cell_type == CELL_CREATE_FAST); @@ -621,7 +619,7 @@ circuit_note_clock_jumped(int seconds_elapsed) int circuit_extend(cell_t *cell, circuit_t *circ) { - connection_t *n_conn; + or_connection_t *n_conn; relay_header_t rh; char *onionskin; 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 * (i.e. old or broken) and the other side will let us make a second * connection without dropping it immediately... */ - if (!n_conn || n_conn->state != OR_CONN_STATE_OPEN || - (n_conn->is_obsolete && + if (!n_conn || n_conn->_base.state != OR_CONN_STATE_OPEN || + (n_conn->_base.or_is_obsolete && router_digest_version_as_new_as(id_digest,"0.1.1.9-alpha-cvs"))) { struct in_addr in; 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 */ memcpy(circ->n_conn_id_digest, id_digest, DIGEST_LEN); - if (n_conn && !n_conn->is_obsolete) { - circ->n_addr = n_conn->addr; - circ->n_port = n_conn->port; + if (n_conn && !n_conn->_base.or_is_obsolete) { + circ->n_addr = n_conn->_base.addr; + circ->n_port = n_conn->_base.port; } else { /* we should try to open a connection */ 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 */ - circ->n_addr = n_conn->addr; - circ->n_port = n_conn->port; + circ->n_addr = n_conn->_base.addr; + circ->n_port = n_conn->_base.port; circ->n_conn = n_conn; 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) 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); 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)) { /* record that we could process create cells from a non-local conn * 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 && conn->state == AP_CONN_STATE_CIRCUIT_WAIT && !conn->marked_for_close && - !connection_edge_is_rendezvous_stream(conn) && - !circuit_stream_is_being_handled(conn, 0, MIN_CIRCUITS_HANDLING_STREAM)) + !connection_edge_is_rendezvous_stream(TO_EDGE_CONN(conn)) && + !circuit_stream_is_being_handled(TO_EDGE_CONN(conn), 0, + MIN_CIRCUITS_HANDLING_STREAM)) return 1; 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 */ if (!ap_stream_wants_exit_attention(carray[j])) 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]; // log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.", // router->nickname, i, n_supported[i]); diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index db8b7577f2..90929d0051 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -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.) */ typedef struct orconn_circid_circuit_map_t { HT_ENTRY(orconn_circid_circuit_map_t) node; - connection_t *or_conn; + or_connection_t *or_conn; uint16_t circ_id; circuit_t *circuit; } orconn_circid_circuit_map_t; @@ -70,8 +70,8 @@ orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL; static void circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id, - connection_t *conn, - uint16_t old_id, connection_t *old_conn) + or_connection_t *conn, + uint16_t old_id, or_connection_t *old_conn) { orconn_circid_circuit_map_t search; 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 */ - tor_assert(old_conn->magic == CONNECTION_MAGIC); + tor_assert(old_conn->_base.magic == OR_CONNECTION_MAGIC); search.circ_id = old_id; search.or_conn = old_conn; 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. */ void circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id, - connection_t *conn) + or_connection_t *conn) { uint16_t old_id; - connection_t *old_conn; + or_connection_t *old_conn; old_id = circ->p_circ_id; 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. */ void circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id, - connection_t *conn) + or_connection_t *conn) { uint16_t old_id; - connection_t *old_conn; + or_connection_t *old_conn; old_id = circ->n_circ_id; old_conn = circ->n_conn; @@ -279,7 +279,7 @@ origin_circuit_new(void) } 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 */ or_circuit_t *circ; @@ -379,9 +379,9 @@ circuit_free_all(void) if (! CIRCUIT_IS_ORIGIN(global_circuitlist)) { or_circuit_t *or_circ = TO_OR_CIRCUIT(global_circuitlist); while (or_circ->resolving_streams) { - connection_t *next; + edge_connection_t *next; 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; } } @@ -439,7 +439,7 @@ void circuit_dump_by_conn(connection_t *conn, int severity) { circuit_t *circ; - connection_t *tmpconn; + edge_connection_t *tmpconn; for (circ=global_circuitlist;circ;circ = circ->next) { 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)) 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", p_circ_id, n_circ_id); if (CIRCUIT_IS_ORIGIN(circ)) { for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn; tmpconn=tmpconn->next_stream) { - if (tmpconn == conn) { + if (TO_CONN(tmpconn) == conn) { circuit_dump_details(severity, circ, conn->poll_index, "App-ward", 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", n_circ_id, p_circ_id); if (! CIRCUIT_IS_ORIGIN(circ)) { for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn; tmpconn=tmpconn->next_stream) { - if (tmpconn == conn) { + if (TO_CONN(tmpconn) == conn) { circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward", 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 && circ->n_addr == conn->addr && 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, (circ->state == CIRCUIT_STATE_OPEN && !CIRCUIT_IS_ORIGIN(circ)) ? @@ -509,13 +512,11 @@ circuit_get_by_global_id(uint32_t id) * Return NULL if no such circuit exists. */ 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 *found; - tor_assert(conn->type == CONN_TYPE_OR); - if (_last_circid_orconn_ent && circ_id == _last_circid_orconn_ent->circ_id && 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. */ 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); 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. */ 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); 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. */ circuit_t * -circuit_get_by_edge_conn(connection_t *conn) +circuit_get_by_edge_conn(edge_connection_t *conn) { circuit_t *circ; - tor_assert(CONN_IS_EDGE(conn)); circ = conn->on_circuit; tor_assert(!circ || @@ -605,7 +605,7 @@ circuit_get_by_edge_conn(connection_t *conn) * been marked already. */ 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; for (circ = global_circuitlist; circ; circ = circ->next) { @@ -820,8 +820,6 @@ void _circuit_mark_for_close(circuit_t *circ, int reason, int line, const char *file) { - connection_t *conn; - assert_circuit_ok(circ); tor_assert(line); tor_assert(file); @@ -889,18 +887,19 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, if (! CIRCUIT_IS_ORIGIN(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) connection_edge_destroy(or_circ->p_circ_id, conn); while (or_circ->resolving_streams) { conn = or_circ->resolving_streams; 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 * are closing because the circuit is getting torn down. No need * to send an end cell. */ - conn->has_sent_end = 1; - connection_mark_for_close(conn); + conn->_base.edge_has_sent_end = 1; + connection_mark_for_close(TO_CONN(conn)); } 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); } else { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); + edge_connection_t *conn; for (conn=ocirc->p_streams; conn; conn=conn->next_stream) connection_edge_destroy(circ->n_circ_id, conn); } @@ -987,7 +987,7 @@ assert_cpath_ok(const crypt_path_t *cp) void assert_circuit_ok(const circuit_t *c) { - connection_t *conn; + edge_connection_t *conn; const or_circuit_t *or_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); 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, DIGEST_LEN)); if (c->n_circ_id) tor_assert(c == circuit_get_by_circid_orconn(c->n_circ_id, c->n_conn)); } if (or_circ && or_circ->p_conn) { - tor_assert(or_circ->p_conn->type == CONN_TYPE_OR); if (or_circ->p_circ_id) tor_assert(c == circuit_get_by_circid_orconn(or_circ->p_circ_id, or_circ->p_conn)); } if (origin_circ) 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) 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->package_window >= 0); diff --git a/src/or/circuituse.c b/src/or/circuituse.c index bad840a032..aac359809d 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -26,7 +26,7 @@ static void circuit_increment_failure_count(void); * Else return 0. */ 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 need_uptime, int need_internal, 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. */ 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) { circuit_t *circ, *best=NULL; @@ -255,7 +255,7 @@ circuit_expire_building(time_t now) if (victim->n_conn) 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->purpose); else @@ -296,7 +296,7 @@ circuit_remove_handled_ports(smartlist_t *needed_ports) * Else return 0. */ 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; 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. */ 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(conn); @@ -536,10 +536,11 @@ circuit_about_to_close_connection(connection_t *conn) if (!connection_state_is_open(conn)) { /* Inform any pending (not attached) circs that they should * 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. */ - 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; } case CONN_TYPE_AP: @@ -550,11 +551,11 @@ circuit_about_to_close_connection(connection_t *conn) * 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) return; - circuit_detach_stream(circ, conn); + circuit_detach_stream(circ, TO_EDGE_CONN(conn)); } } /* end switch */ } @@ -683,7 +684,7 @@ circuit_build_failed(origin_circuit_t *circ) circ->cpath->state != CPATH_STATE_OPEN) { /* We failed at the first hop. If there's an OR connection to blame, blame it. */ - connection_t *n_conn = NULL; + or_connection_t *n_conn = NULL; if (circ->_base.n_conn) { n_conn = circ->_base.n_conn; } else if (circ->_base.state == CIRCUIT_STATE_OR_WAIT) { @@ -695,8 +696,8 @@ circuit_build_failed(origin_circuit_t *circ) log_info(LD_OR, "Our circuit failed to get a response from the first hop " "(%s:%d). I'm going to try to rotate to a better connection.", - n_conn->address, n_conn->port); - n_conn->is_obsolete = 1; + n_conn->_base.address, n_conn->_base.port); + n_conn->_base.or_is_obsolete = 1; 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. */ 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, origin_circuit_t **circp) { @@ -903,7 +904,7 @@ circuit_get_open_circ_or_launch(connection_t *conn, tor_assert(conn); 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; 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.", safe_str(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; } 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. */ 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 */ log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.", circ->_base.n_circ_id); /* 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->on_circuit = TO_CIRCUIT(circ); /* 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 * use. */ 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; 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 * for connection_ap_handshake_attach_circuit. */ int -connection_ap_handshake_attach_chosen_circuit(connection_t *conn, +connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, origin_circuit_t *circ) { tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_AP); - tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT || - conn->state == AP_CONN_STATE_CONTROLLER_WAIT); + tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT || + conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT); tor_assert(conn->socks_request); tor_assert(circ); 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) 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. */ int -connection_ap_handshake_attach_circuit(connection_t *conn) +connection_ap_handshake_attach_circuit(edge_connection_t *conn) { int retval; int conn_age; int severity; tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_AP); - tor_assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT); + tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(conn->socks_request); - conn_age = time(NULL) - conn->timestamp_created; - severity = (!conn->addr && !conn->port) ? LOG_INFO : LOG_NOTICE; + conn_age = time(NULL) - conn->_base.timestamp_created; + severity = (!conn->_base.addr && !conn->_base.port) ? LOG_INFO : LOG_NOTICE; if (conn_age > get_options()->SocksTimeout) { log_fn(severity, LD_APP, "Tried for %d seconds to get a connection to %s:%d. Giving up.", diff --git a/src/or/command.c b/src/or/command.c index 49fcc654c7..9e3e529737 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -27,10 +27,10 @@ uint64_t stats_n_relay_cells_processed = 0; uint64_t stats_n_destroy_cells_processed = 0; /* 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_created_cell(cell_t *cell, connection_t *conn); -static void command_process_relay_cell(cell_t *cell, connection_t *conn); -static void command_process_destroy_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, or_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, or_connection_t *conn); #ifdef KEEP_TIMING_STATS /** 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>. */ static void -command_time_process_cell(cell_t *cell, connection_t *conn, int *time, - void (*func)(cell_t *, connection_t *)) +command_time_process_cell(cell_t *cell, or_connection_t *conn, int *time, + void (*func)(cell_t *, or_connection_t *)) { struct timeval start, end; long time_passed; @@ -68,7 +68,7 @@ command_time_process_cell(cell_t *cell, connection_t *conn, int *time, * process each type of cell. */ void -command_process_cell(cell_t *cell, connection_t *conn) +command_process_cell(cell_t *cell, or_connection_t *conn) { #ifdef KEEP_TIMING_STATS /* 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. */ 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; 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, "Received CREATE cell (circID %d) for known circ. " "Dropping (age %d).", - cell->circ_id, (int)(time(NULL) - conn->timestamp_created)); + cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created)); if (router) log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "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. */ 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; @@ -290,7 +290,7 @@ command_process_created_cell(cell_t *cell, connection_t *conn) * circuit_receive_relay_cell() for actual processing. */ 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; int reason; @@ -300,7 +300,7 @@ command_process_relay_cell(cell_t *cell, connection_t *conn) if (!circ) { log_debug(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; } @@ -345,7 +345,7 @@ command_process_relay_cell(cell_t *cell, connection_t *conn) * and passes the destroy cell onward if necessary). */ 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; uint8_t reason; @@ -354,7 +354,7 @@ command_process_destroy_cell(cell_t *cell, connection_t *conn) reason = (uint8_t)cell->payload[0]; if (!circ) { 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; } log_debug(LD_OR,"Received for circID %d.",cell->circ_id); diff --git a/src/or/connection.c b/src/or/connection.c index f3c4eea534..21f3d89974 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -18,7 +18,7 @@ static connection_t *connection_create_listener(const char *listenaddress, uint16_t listenport, int type); static int connection_init_accepted_conn(connection_t *conn); 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_flushed_some(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; connection_t *conn; time_t now = time(NULL); + size_t length; + uint32_t magic; - conn = tor_malloc_zero(sizeof(connection_t)); - conn->magic = CONNECTION_MAGIC; + switch (type) { + 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->poll_index = -1; /* also default to 'not used' */ conn->global_identifier = n_connections_allocated++; @@ -174,10 +200,11 @@ connection_new(int type) conn->outbuf = buf_new(); } 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)); } - - conn->next_circ_id = crypto_rand_int(1<<15); + if (type == CONN_TYPE_OR) + TO_OR_CONN(conn)->next_circ_id = crypto_rand_int(1<<15); conn->timestamp_created = now; conn->timestamp_lastread = now; @@ -209,28 +236,72 @@ connection_unregister(connection_t *conn) static void _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)) { buf_free(conn->inbuf); buf_free(conn->outbuf); } + tor_free(conn->address); - tor_free(conn->chosen_exit_name); if (connection_speaks_cells(conn)) { - if (conn->tls) { - tor_tls_free(conn->tls); - conn->tls = NULL; + or_connection_t *or_conn = TO_OR_CONN(conn); + if (or_conn->tls) { + 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->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) { log_debug(LD_NET,"closing fd %d.",conn->s); @@ -238,21 +309,13 @@ _connection_free(connection_t *conn) } 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"); - connection_or_remove_from_identity_map(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); + connection_or_remove_from_identity_map(TO_OR_CONN(conn)); } - if (conn->cached_dir) - cached_dir_decref(conn->cached_dir); 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. @@ -266,12 +329,12 @@ connection_free(connection_t *conn) if (connection_speaks_cells(conn)) { if (conn->state == OR_CONN_STATE_OPEN) directory_set_dirty(); - if (!tor_digest_is_zero(conn->identity_digest)) { - connection_or_remove_from_identity_map(conn); + if (!tor_digest_is_zero(TO_OR_CONN(conn)->identity_digest)) { + connection_or_remove_from_identity_map(TO_OR_CONN(conn)); } } if (conn->type == CONN_TYPE_CONTROL) { - conn->event_mask = 0; + TO_CONTROL_CONN(conn)->event_mask = 0; control_update_global_event_mask(); } connection_unregister(conn); @@ -297,7 +360,7 @@ connection_free_all(void) /* We don't want to log any messages to controllers. */ for (i=0;i<n;i++) 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(); /* Unlink everything from the identity map. */ @@ -326,11 +389,14 @@ void connection_about_to_close_connection(connection_t *conn) { circuit_t *circ; + dir_connection_t *dir_conn; + or_connection_t *or_conn; + edge_connection_t *edge_conn; assert(conn->marked_for_close); 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) " "hasn't sent end yet?", conn->marked_for_close_file, conn->marked_for_close); @@ -340,23 +406,25 @@ connection_about_to_close_connection(connection_t *conn) switch (conn->type) { case CONN_TYPE_DIR: + dir_conn = TO_DIR_CONN(conn); if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) { /* It's a directory connection and connecting or fetching * 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 } 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; case CONN_TYPE_OR: + or_conn = TO_OR_CONN(conn); /* Remember why we're closing this connection. */ if (conn->state != OR_CONN_STATE_OPEN) { - if (connection_or_nonopen_was_started_here(conn)) { - rep_hist_note_connect_failed(conn->identity_digest, time(NULL)); - entry_guard_set_status(conn->identity_digest, 0); - router_set_status(conn->identity_digest, 0); - control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED); + if (connection_or_nonopen_was_started_here(or_conn)) { + rep_hist_note_connect_failed(or_conn->identity_digest, time(NULL)); + entry_guard_set_status(or_conn->identity_digest, 0); + router_set_status(or_conn->identity_digest, 0); + control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED); } } else if (conn->hold_open_until_flushed) { /* 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 * improvement. -NM */ - rep_hist_note_disconnect(conn->identity_digest, time(NULL)); - control_event_or_conn_status(conn, OR_CONN_EVENT_CLOSED); - } else if (conn->identity_digest) { - rep_hist_note_connection_died(conn->identity_digest, time(NULL)); - control_event_or_conn_status(conn, OR_CONN_EVENT_CLOSED); + rep_hist_note_disconnect(or_conn->identity_digest, time(NULL)); + control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED); + } else if (or_conn->identity_digest) { + rep_hist_note_connection_died(or_conn->identity_digest, time(NULL)); + control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED); } break; 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, * 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" " back a socks reply.", conn->marked_for_close_file, conn->marked_for_close); } else { - control_event_stream_status(conn, STREAM_EVENT_CLOSED); + control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED); } break; case CONN_TYPE_EXIT: + edge_conn = TO_EDGE_CONN(conn); if (conn->state == EXIT_CONN_STATE_RESOLVING) { - circ = circuit_get_by_edge_conn(conn); + circ = circuit_get_by_edge_conn(edge_conn); if (circ) - circuit_detach_stream(circ, conn); - connection_dns_remove(conn); + circuit_detach_stream(circ, edge_conn); + connection_dns_remove(edge_conn); } break; case CONN_TYPE_DNSWORKER: @@ -731,8 +801,8 @@ connection_init_accepted_conn(connection_t *conn) switch (conn->type) { case CONN_TYPE_OR: - control_event_or_conn_status(conn, OR_CONN_EVENT_NEW); - return connection_tls_start_handshake(conn, 1); + control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW); + return connection_tls_start_handshake(TO_OR_CONN(conn), 1); case CONN_TYPE_AP: conn->state = AP_CONN_STATE_SOCKS_WAIT; break; @@ -1006,9 +1076,11 @@ connection_bucket_read_limit(connection_t *conn) if (at_most > global_read_bucket) at_most = global_read_bucket; - if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) - if (at_most > conn->receiver_bucket) - at_most = conn->receiver_bucket; + if (connection_speaks_cells(conn) && conn->state == OR_CONN_STATE_OPEN) { + or_connection_t *or_conn = TO_OR_CONN(conn); + if (at_most > or_conn->receiver_bucket) + at_most = or_conn->receiver_bucket; + } if (at_most < 0) return 0; @@ -1052,7 +1124,7 @@ connection_read_bucket_decrement(connection_t *conn, int num_read) { global_read_bucket -= num_read; 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) && conn->state == OR_CONN_STATE_OPEN && - conn->receiver_bucket <= 0) { + TO_OR_CONN(conn)->receiver_bucket <= 0) { LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,"receiver bucket exhausted. Pausing.")); conn->wants_to_read = 1; @@ -1114,12 +1186,15 @@ connection_bucket_refill(struct timeval *now) for (i=0;i<n;i++) { conn = carray[i]; - if (connection_receiver_bucket_should_increase(conn)) { - conn->receiver_bucket += conn->bandwidthrate; - if (conn->receiver_bucket > conn->bandwidthburst) - conn->receiver_bucket = conn->bandwidthburst; - //log_fn(LOG_DEBUG,"Receiver bucket %d now %d.", i, - // conn->receiver_bucket); + if (connection_speaks_cells(conn)) { + or_connection_t *or_conn = TO_OR_CONN(conn); + if (connection_receiver_bucket_should_increase(or_conn)) { + or_conn->receiver_bucket += or_conn->bandwidthrate; + if (or_conn->receiver_bucket > or_conn->bandwidthburst) + 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 */ @@ -1128,7 +1203,7 @@ connection_bucket_refill(struct timeval *now) * not the best place to check this.) */ && (!connection_speaks_cells(conn) || 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 */ LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET,"waking up conn (fd %d)",conn->s)); conn->wants_to_read = 0; @@ -1145,15 +1220,12 @@ connection_bucket_refill(struct timeval *now) * should add another pile of tokens to it? */ static int -connection_receiver_bucket_should_increase(connection_t *conn) +connection_receiver_bucket_should_increase(or_connection_t *conn) { tor_assert(conn); - if (!connection_speaks_cells(conn)) - return 0; /* edge connections don't use receiver_buckets */ - if (conn->state != OR_CONN_STATE_OPEN) + if (conn->_base.state != OR_CONN_STATE_OPEN) return 0; /* only open connections play the rate limiting game */ - if (conn->receiver_bucket >= conn->bandwidthburst) return 0; @@ -1200,15 +1272,15 @@ loop_again: /* There's a read error; kill the connection.*/ connection_close_immediate(conn); /* Don't flush; connection is dead. */ if (CONN_IS_EDGE(conn)) { - connection_edge_end_errno(conn, conn->cpath_layer); - if (conn->socks_request) /* broken, so don't send a socks reply back */ - conn->socks_request->has_finished = 1; + edge_connection_t *edge_conn = TO_EDGE_CONN(conn); + connection_edge_end_errno(edge_conn, edge_conn->cpath_layer); + 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); return -1; } - if (CONN_IS_EDGE(conn) && - try_to_read != max_to_read) { + if (CONN_IS_EDGE(conn) && try_to_read != max_to_read) { /* instruct it not to try to package partial cells. */ if (connection_process_inbuf(conn, 0) < 0) { return -1; @@ -1265,29 +1337,32 @@ connection_read_to_buf(connection_t *conn, int *max_to_read) if (connection_speaks_cells(conn) && conn->state > OR_CONN_STATE_PROXY_READING) { int pending; + or_connection_t *or_conn = TO_OR_CONN(conn); if (conn->state == OR_CONN_STATE_HANDSHAKING) { /* 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, "%d: starting, inbuf_datalen %d (%d pending in tls object)." " at_most %d.", 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 */ - 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) { case TOR_TLS_CLOSE: log_info(LD_NET,"TLS connection closed on read. Closing. " "(Nickname %s, address %s", - conn->nickname ? conn->nickname : "not set", conn->address); + or_conn->nickname ? or_conn->nickname : "not set", + conn->address); return -1; case TOR_TLS_ERROR: 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; case TOR_TLS_WANTWRITE: connection_start_writing(conn); @@ -1299,12 +1374,12 @@ connection_read_to_buf(connection_t *conn, int *max_to_read) default: break; } - pending = tor_tls_get_pending_bytes(conn->tls); + pending = tor_tls_get_pending_bytes(or_conn->tls); if (pending) { /* XXXX If we have any pending bytes, read them now. This *can* * take us over our read allotment, but really we shouldn't be * 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) { log_warn(LD_BUG, "Bug: apparently, reading pending bytes can fail."); return -1; @@ -1409,7 +1484,8 @@ connection_handle_write(connection_t *conn) log_warn(LD_BUG, "getsockopt() syscall failed?! Please report to tor-ops."); 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); return -1; } @@ -1418,7 +1494,8 @@ connection_handle_write(connection_t *conn) if (!ERRNO_IS_CONN_EINPROGRESS(e)) { log_info(LD_NET,"in-progress connect failed. Removing."); 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_mark_for_close(conn); @@ -1426,7 +1503,7 @@ connection_handle_write(connection_t *conn) * ignores unrecognized routers */ 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; } else { 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) && conn->state > OR_CONN_STATE_PROXY_READING) { + or_connection_t *or_conn = TO_OR_CONN(conn); if (conn->state == OR_CONN_STATE_HANDSHAKING) { 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. */ connection_close_immediate(conn); connection_mark_for_close(conn); @@ -1453,7 +1531,7 @@ connection_handle_write(connection_t *conn) } /* 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); switch (result) { case TOR_TLS_ERROR: @@ -1491,7 +1569,8 @@ connection_handle_write(connection_t *conn) max_to_write, &conn->outbuf_flushlen)); if (result < 0) { 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_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 * need to write it onto controller <b>conn</b> immediately. */ 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 * 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. */ int result; - tor_assert(conn); - tor_assert(!conn->tls); - tor_assert(conn->type == CONN_TYPE_CONTROL); + connection_t *conn; + tor_assert(control_conn); + conn = TO_CONN(control_conn); + if (conn->marked_for_close || conn->s < 0) 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. */ log_warn(LD_NET, "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); } else { log_warn(LD_NET, @@ -1595,15 +1675,17 @@ connection_write_to_buf(const char *string, size_t len, connection_t *conn) } void -connection_write_to_buf_zlib(connection_t *conn, +connection_write_to_buf_zlib(dir_connection_t *dir_conn, tor_zlib_state_t *state, const char *data, size_t data_len, int done) { int r; size_t old_datalen; + connection_t *conn; if (!data_len) return; + conn = TO_CONN(dir_conn); /* 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) return; @@ -1614,18 +1696,9 @@ connection_write_to_buf_zlib(connection_t *conn, conn->outbuf, state, data, data_len, done)); if (r < 0) { - if (CONN_IS_EDGE(conn)) { - /* if it failed, it means we have our package/delivery windows set - wrong compared to our max outbuf size. close the whole circuit. */ - 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); - } + log_warn(LD_NET, + "write_to_buf failed. Closing connection (fd %d).", conn->s); + connection_mark_for_close(conn); return; } @@ -1635,11 +1708,12 @@ connection_write_to_buf_zlib(connection_t *conn, /** Return the conn to addr/port that has the most recent * 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) { int i, n; - connection_t *conn, *best=NULL; + connection_t *conn; + or_connection_t *best=NULL; connection_t **carray; 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->port == port && !conn->marked_for_close && - (!best || best->timestamp_created < conn->timestamp_created)) - best = conn; + (!best || best->_base.timestamp_created < conn->timestamp_created)) + best = TO_OR_CONN(conn); } return best; } @@ -1772,14 +1846,22 @@ connection_get_by_type_state_rendquery(int type, int state, connection_t *conn; connection_t **carray; + tor_assert(type == CONN_TYPE_DIR || + type == CONN_TYPE_AP || type == CONN_TYPE_EXIT); + get_connection_array(&carray,&n); for (i=0;i<n;i++) { conn = carray[i]; if (conn->type == type && !conn->marked_for_close && - (!state || state == conn->state) && - !rend_cmp_service_ids(rendquery, conn->rend_query)) - return conn; + (!state || state == conn->state)) { + if (type == CONN_TYPE_DIR && + 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; } @@ -1949,18 +2031,18 @@ connection_process_inbuf(connection_t *conn, int package_partial) switch (conn->type) { 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_AP: - return connection_edge_process_inbuf(conn, package_partial); + return connection_edge_process_inbuf(TO_EDGE_CONN(conn), package_partial); case CONN_TYPE_DIR: - return connection_dir_process_inbuf(conn); + return connection_dir_process_inbuf(TO_DIR_CONN(conn)); case CONN_TYPE_DNSWORKER: return connection_dns_process_inbuf(conn); case CONN_TYPE_CPUWORKER: return connection_cpu_process_inbuf(conn); case CONN_TYPE_CONTROL: - return connection_control_process_inbuf(conn); + return connection_control_process_inbuf(TO_CONTROL_CONN(conn)); default: log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type); tor_fragile_assert(); @@ -1974,7 +2056,7 @@ connection_flushed_some(connection_t *conn) { if (conn->type == CONN_TYPE_DIR && conn->state == DIR_CONN_STATE_SERVER_WRITING) - return connection_dirserv_flushed_some(conn); + return connection_dirserv_flushed_some(TO_DIR_CONN(conn)); else return 0; } @@ -1994,18 +2076,18 @@ connection_finished_flushing(connection_t *conn) switch (conn->type) { 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_EXIT: - return connection_edge_finished_flushing(conn); + return connection_edge_finished_flushing(TO_EDGE_CONN(conn)); case CONN_TYPE_DIR: - return connection_dir_finished_flushing(conn); + return connection_dir_finished_flushing(TO_DIR_CONN(conn)); case CONN_TYPE_DNSWORKER: return connection_dns_finished_flushing(conn); case CONN_TYPE_CPUWORKER: return connection_cpu_finished_flushing(conn); case CONN_TYPE_CONTROL: - return connection_control_finished_flushing(conn); + return connection_control_finished_flushing(TO_CONTROL_CONN(conn)); default: log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type); tor_fragile_assert(); @@ -2026,11 +2108,11 @@ connection_finished_connecting(connection_t *conn) switch (conn->type) { case CONN_TYPE_OR: - return connection_or_finished_connecting(conn); + return connection_or_finished_connecting(TO_OR_CONN(conn)); case CONN_TYPE_EXIT: - return connection_edge_finished_connecting(conn); + return connection_edge_finished_connecting(TO_EDGE_CONN(conn)); case CONN_TYPE_DIR: - return connection_dir_finished_connecting(conn); + return connection_dir_finished_connecting(TO_DIR_CONN(conn)); default: log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type); tor_fragile_assert(); @@ -2044,18 +2126,18 @@ connection_reached_eof(connection_t *conn) { switch (conn->type) { 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_EXIT: - return connection_edge_reached_eof(conn); + return connection_edge_reached_eof(TO_EDGE_CONN(conn)); case CONN_TYPE_DIR: - return connection_dir_reached_eof(conn); + return connection_dir_reached_eof(TO_DIR_CONN(conn)); case CONN_TYPE_DNSWORKER: return connection_dns_reached_eof(conn); case CONN_TYPE_CPUWORKER: return connection_cpu_reached_eof(conn); case CONN_TYPE_CONTROL: - return connection_control_reached_eof(conn); + return connection_control_reached_eof(TO_CONTROL_CONN(conn)); default: log_err(LD_BUG,"Bug: got unexpected conn type %d.", conn->type); tor_fragile_assert(); @@ -2071,9 +2153,26 @@ assert_connection_ok(connection_t *conn, time_t now) { (void) now; /* XXXX unused. */ tor_assert(conn); - tor_assert(conn->magic == CONNECTION_MAGIC); tor_assert(conn->type >= _CONN_TYPE_MIN); 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) { tor_assert(connection_is_writing(conn) || conn->wants_to_write); @@ -2100,9 +2199,8 @@ assert_connection_ok(connection_t *conn, time_t now) */ #endif - if (conn->type != CONN_TYPE_OR) { - tor_assert(!conn->tls); - } else { + if (conn->type == CONN_TYPE_OR) { + or_connection_t *or_conn = TO_OR_CONN(conn); if (conn->state == OR_CONN_STATE_OPEN) { /* tor_assert(conn->bandwidth > 0); */ /* 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->address); if (conn->state > OR_CONN_STATE_PROXY_READING) - tor_assert(conn->tls); + tor_assert(or_conn->tls); } - if (! CONN_IS_EDGE(conn)) { - tor_assert(!conn->stream_id); - 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 { + if (CONN_IS_EDGE(conn)) { + edge_connection_t *edge_conn = TO_EDGE_CONN(conn); /* XXX unchecked: package window, deliver window. */ - } - if (conn->type == CONN_TYPE_AP) { - tor_assert(conn->socks_request); - if (conn->state == AP_CONN_STATE_OPEN) { - tor_assert(conn->socks_request->has_finished); - if (!conn->marked_for_close) { - tor_assert(conn->cpath_layer); - assert_cpath_layer_ok(conn->cpath_layer); + if (conn->type == CONN_TYPE_AP) { + + tor_assert(edge_conn->socks_request); + if (conn->state == AP_CONN_STATE_OPEN) { + tor_assert(edge_conn->socks_request->has_finished); + if (!conn->marked_for_close) { + tor_assert(edge_conn->cpath_layer); + assert_cpath_layer_ok(edge_conn->cpath_layer); + } } } - } else { - tor_assert(!conn->socks_request); - } - 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_EXIT) { + tor_assert(conn->purpose == EXIT_PURPOSE_CONNECT || + conn->purpose == EXIT_PURPOSE_RESOLVE); + } } if (conn->type != CONN_TYPE_DIR) { - tor_assert(!conn->requested_resource); + tor_assert(!conn->purpose); /* only used for dir types currently */ } switch (conn->type) @@ -2164,7 +2250,7 @@ assert_connection_ok(connection_t *conn, time_t now) case CONN_TYPE_OR: tor_assert(conn->state >= _OR_CONN_STATE_MIN); tor_assert(conn->state <= _OR_CONN_STATE_MAX); - tor_assert(conn->n_circuits >= 0); + tor_assert(TO_OR_CONN(conn)->n_circuits >= 0); break; case CONN_TYPE_EXIT: 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: tor_assert(conn->state >= _AP_CONN_STATE_MIN); tor_assert(conn->state <= _AP_CONN_STATE_MAX); - tor_assert(conn->socks_request); + tor_assert(TO_EDGE_CONN(conn)->socks_request); break; case CONN_TYPE_DIR: tor_assert(conn->state >= _DIR_CONN_STATE_MIN); diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 10284723d4..a70ad9a6ff 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -16,22 +16,22 @@ const char connection_edge_c_id[] = /* List of exit_redirect_t */ 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 * a socks reply, send one now (based on endreason). Also set * has_sent_end to 1, and mark the conn. */ 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) { - tor_assert(conn->type == CONN_TYPE_AP); - conn->has_sent_end = 1; /* no circ yet */ + tor_assert(conn->_base.type == CONN_TYPE_AP); + 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. */ - _connection_mark_for_close(conn, line, file); + _connection_mark_for_close(TO_CONN(conn), line, file); return; } @@ -51,27 +51,28 @@ _connection_mark_unattached_ap(connection_t *conn, int endreason, 0, NULL, -1); } - _connection_mark_for_close(conn, line, file); - conn->hold_open_until_flushed = 1; + _connection_mark_for_close(TO_CONN(conn), line, file); + conn->_base.hold_open_until_flushed = 1; } /** There was an EOF. Send an end and mark the connection for close. */ 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. */ return 0; } - log_info(LD_EDGE,"conn (fd %d) reached eof. Closing.", conn->s); - if (!conn->marked_for_close) { + log_info(LD_EDGE,"conn (fd %d) reached eof. Closing.", conn->_base.s); + if (!conn->_base.marked_for_close) { /* only mark it if not already marked. it's possible to * get the 'end' right around when the client hangs up on us. */ connection_edge_end(conn, END_STREAM_REASON_DONE, conn->cpath_layer); if (conn->socks_request) /* eof, so don't send a socks reply back */ conn->socks_request->has_finished = 1; - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); } return 0; } @@ -86,12 +87,11 @@ connection_edge_reached_eof(connection_t *conn) * else return 0. */ 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_IS_EDGE(conn)); - switch (conn->state) { + switch (conn->_base.state) { case AP_CONN_STATE_SOCKS_WAIT: if (connection_ap_handshake_process_socks(conn) < 0) { /* already marked */ @@ -102,7 +102,7 @@ connection_edge_process_inbuf(connection_t *conn, int package_partial) case EXIT_CONN_STATE_OPEN: if (connection_edge_package_raw_inbuf(conn, package_partial) < 0) { /* (We already sent an end cell if possible) */ - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); return -1; } return 0; @@ -114,13 +114,13 @@ connection_edge_process_inbuf(connection_t *conn, int package_partial) case AP_CONN_STATE_CONTROLLER_WAIT: log_info(LD_EDGE, "data from edge while in '%s' state. Leaving it on buffer.", - conn_state_to_string(conn->type, conn->state)); + conn_state_to_string(conn->_base.type, conn->_base.state)); 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(); 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; } @@ -128,19 +128,17 @@ connection_edge_process_inbuf(connection_t *conn, int package_partial) * Mark it for close and return 0. */ 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->marked_for_close) { + if (!conn->_base.marked_for_close) { log_info(LD_EDGE, "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); } else { - conn->has_sent_end = 1; /* closing the circuit, nothing to send to */ - connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; + conn->_base.edge_has_sent_end = 1; /* closing the circuit, nothing to send to */ + connection_mark_for_close(TO_CONN(conn)); + conn->_base.hold_open_until_flushed = 1; } } conn->cpath_layer = NULL; @@ -157,44 +155,46 @@ connection_edge_destroy(uint16_t circ_id, connection_t *conn) * else return 0. */ 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]; size_t payload_len=1; 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) " "on an already ended stream?", reason); tor_fragile_assert(); return -1; } - if (conn->marked_for_close) { + if (conn->_base.marked_for_close) { log_warn(LD_BUG, "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; } payload[0] = reason; if (reason == END_STREAM_REASON_EXITPOLICY && !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))); payload_len += 8; } circ = circuit_get_by_edge_conn(conn); 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, payload, payload_len, cpath_layer); } 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; } @@ -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>. **/ 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; 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); } @@ -222,15 +222,14 @@ connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer) * return 0. */ int -connection_edge_finished_flushing(connection_t *conn) +connection_edge_finished_flushing(edge_connection_t *conn) { tor_assert(conn); - tor_assert(CONN_IS_EDGE(conn)); - switch (conn->state) { + switch (conn->_base.state) { case AP_CONN_STATE_OPEN: case EXIT_CONN_STATE_OPEN: - connection_stop_writing(conn); + connection_stop_writing(TO_CONN(conn)); connection_edge_consider_sending_sendme(conn); return 0; 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_CONNECT_WAIT: case AP_CONN_STATE_CONTROLLER_WAIT: - connection_stop_writing(conn); + connection_stop_writing(TO_CONN(conn)); return 0; 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(); return -1; } @@ -252,13 +251,15 @@ connection_edge_finished_flushing(connection_t *conn) * data, deliver 'CONNECTED' relay cells as appropriate, and check * any pending data that may have been received. */ int -connection_edge_finished_connecting(connection_t *conn) +connection_edge_finished_connecting(edge_connection_t *edge_conn) { char valbuf[INET_NTOA_BUF_LEN]; + connection_t *conn; struct in_addr in; - tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_EXIT); + tor_assert(edge_conn); + tor_assert(edge_conn->_base.type == CONN_TYPE_EXIT); + conn = TO_CONN(edge_conn); tor_assert(conn->state == EXIT_CONN_STATE_CONNECTING); in.s_addr = htonl(conn->addr); @@ -272,23 +273,27 @@ connection_edge_finished_connecting(connection_t *conn) * cells */ connection_start_writing(conn); /* deliver a 'connected' relay cell back through the circuit. */ - if (connection_edge_is_rendezvous_stream(conn)) { - if (connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), + if (connection_edge_is_rendezvous_stream(edge_conn)) { + if (connection_edge_send_command(edge_conn, + circuit_get_by_edge_conn(edge_conn), RELAY_COMMAND_CONNECTED, NULL, 0, - conn->cpath_layer) < 0) + edge_conn->cpath_layer) < 0) return 0; /* circuit is closed, don't continue */ } else { char connected_payload[8]; set_uint32(connected_payload, htonl(conn->addr)); set_uint32(connected_payload+4, - htonl(dns_clip_ttl(conn->address_ttl))); - if (connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), - RELAY_COMMAND_CONNECTED, connected_payload, 8, conn->cpath_layer) < 0) + htonl(dns_clip_ttl(edge_conn->address_ttl))); + if (connection_edge_send_command(edge_conn, + 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 */ } - tor_assert(conn->package_window > 0); + tor_assert(edge_conn->package_window > 0); /* 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 @@ -297,7 +302,7 @@ connection_edge_finished_connecting(connection_t *conn) * 10 seconds for the second, and 15 seconds for each retry after * that. Hopefully this will improve the expected experience. */ static int -compute_socks_timeout(connection_t *conn) +compute_socks_timeout(edge_connection_t *conn) { if (conn->num_socks_retries == 0) return 5; @@ -319,7 +324,7 @@ void connection_ap_expire_beginning(void) { connection_t **carray; - connection_t *conn; + edge_connection_t *conn; circuit_t *circ; const char *nickname; int n, i; @@ -331,24 +336,24 @@ connection_ap_expire_beginning(void) get_connection_array(&carray, &n); for (i = 0; i < n; ++i) { - conn = carray[i]; - if (conn->type != CONN_TYPE_AP) + if (carray[i]->type != CONN_TYPE_AP) continue; + conn = TO_EDGE_CONN(carray[i]); /* if it's an internal bridge connection, don't yell its status. */ - severity = (!conn->addr && !conn->port) ? LOG_INFO : LOG_NOTICE; - if (conn->state == AP_CONN_STATE_CONTROLLER_WAIT) { - if (now - conn->timestamp_lastread >= options->SocksTimeout) { + severity = (!conn->_base.addr && !conn->_base.port) ? LOG_INFO : LOG_NOTICE; + if (conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT) { + if (now - conn->_base.timestamp_lastread >= options->SocksTimeout) { log_fn(severity, LD_APP, "Closing unattached stream."); connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT); } continue; } - if (conn->state != AP_CONN_STATE_RESOLVE_WAIT && - conn->state != AP_CONN_STATE_CONNECT_WAIT) + if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT && + conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) continue; cutoff = compute_socks_timeout(conn); - if (now - conn->timestamp_lastread < cutoff) + if (now - conn->_base.timestamp_lastread < cutoff) continue; circ = circuit_get_by_edge_conn(conn); if (!circ) { /* it's vanished? */ @@ -358,11 +363,11 @@ connection_ap_expire_beginning(void) continue; } 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, "Rend stream is %d seconds late. Giving up on address" " '%s.onion'.", - (int)(now - conn->timestamp_lastread), + (int)(now - conn->_base.timestamp_lastread), safe_str(conn->socks_request->address)); connection_edge_end(conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer); @@ -376,20 +381,20 @@ connection_ap_expire_beginning(void) log_fn(cutoff < 15 ? LOG_INFO : severity, LD_APP, "We tried for %d seconds to connect to '%s' using exit '%s'." " Retrying on a new circuit.", - (int)(now - conn->timestamp_lastread), + (int)(now - conn->_base.timestamp_lastread), safe_str(conn->socks_request->address), nickname ? nickname : "*unnamed*"); /* send an end down the circuit */ connection_edge_end(conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer); /* 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 * current streams on it to survive if they can: make it * unattractive to use for new streams */ tor_assert(circ->timestamp_dirty); circ->timestamp_dirty -= options->MaxCircuitDirtiness; /* give our stream another 'cutoff' seconds to try */ - conn->timestamp_lastread += cutoff; + conn->_base.timestamp_lastread += cutoff; conn->num_socks_retries++; /* move it back into 'pending' state, and try to attach. */ 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 *conn; + edge_connection_t *edge_conn; int n, i; get_connection_array(&carray, &n); @@ -416,8 +422,9 @@ connection_ap_attach_pending(void) conn->type != CONN_TYPE_AP || conn->state != AP_CONN_STATE_CIRCUIT_WAIT) continue; - if (connection_ap_handshake_attach_circuit(conn) < 0) { - connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); + edge_conn = TO_EDGE_CONN(conn); + 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. */ 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); - conn->timestamp_lastread = time(NULL); + conn->_base.timestamp_lastread = time(NULL); 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); return connection_ap_handshake_attach_circuit(conn); } else { - conn->state = AP_CONN_STATE_CONTROLLER_WAIT; + conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; circuit_detach_stream(TO_CIRCUIT(circ),conn); return 0; } @@ -1011,7 +1018,7 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires, * rendezvous descriptor is already here and fresh enough). */ int -connection_ap_handshake_rewrite_and_attach(connection_t *conn, +connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, origin_circuit_t *circ) { 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 */ 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 && connection_ap_handshake_attach_chosen_circuit(conn, circ) < 0) || (!circ && @@ -1182,21 +1189,21 @@ connection_ap_handshake_rewrite_and_attach(connection_t *conn, return -1; } 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.", safe_str(conn->rend_query)); rend_client_refetch_renddesc(conn->rend_query); } else { /* r > 0 */ #define NUM_SECONDS_BEFORE_REFETCH (60*15) 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."); if (connection_ap_handshake_attach_circuit(conn) < 0) { connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); return -1; } } else { - conn->state = AP_CONN_STATE_RENDDESC_WAIT; + conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; log_info(LD_REND, "Stale descriptor %s. Refetching.", safe_str(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. */ static int -connection_ap_handshake_process_socks(connection_t *conn) +connection_ap_handshake_process_socks(edge_connection_t *conn) { socks_request_t *socks; int sockshere; or_options_t *options = get_options(); tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_AP); - tor_assert(conn->state == AP_CONN_STATE_SOCKS_WAIT); + tor_assert(conn->_base.type == CONN_TYPE_AP); + tor_assert(conn->_base.state == AP_CONN_STATE_SOCKS_WAIT); tor_assert(conn->socks_request); socks = conn->socks_request; 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); if (sockshere == 0) { 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 */ socks->replylen = 0; } else { @@ -1263,7 +1270,7 @@ connection_ap_handshake_process_socks(connection_t *conn) control_event_stream_status(conn, STREAM_EVENT_NEW_RESOLVE); if (options->LeaveStreamsUnattached) { - conn->state = AP_CONN_STATE_CONTROLLER_WAIT; + conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; return 0; } return connection_ap_handshake_rewrite_and_attach(conn, NULL); @@ -1275,7 +1282,7 @@ connection_ap_handshake_process_socks(connection_t *conn) static uint16_t get_unique_stream_id_by_circ(origin_circuit_t *circ) { - connection_t *tmpconn; + edge_connection_t *tmpconn; uint16_t test_stream_id; uint32_t attempts=0; @@ -1300,14 +1307,14 @@ again: * If ap_conn is broken, mark it for close and return -1. Else return 0. */ int -connection_ap_handshake_send_begin(connection_t *ap_conn, +connection_ap_handshake_send_begin(edge_connection_t *ap_conn, origin_circuit_t *circ) { char payload[CELL_PAYLOAD_SIZE]; int payload_len; - tor_assert(ap_conn->type == CONN_TYPE_AP); - tor_assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); + tor_assert(ap_conn->_base.type == CONN_TYPE_AP); + tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(ap_conn->socks_request); 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->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", - 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); 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. */ int -connection_ap_handshake_send_resolve(connection_t *ap_conn, +connection_ap_handshake_send_resolve(edge_connection_t *ap_conn, origin_circuit_t *circ) { int payload_len; const char *string_addr; - tor_assert(ap_conn->type == CONN_TYPE_AP); - tor_assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); + tor_assert(ap_conn->_base.type == CONN_TYPE_AP); + tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(ap_conn->socks_request); tor_assert(ap_conn->socks_request->command == SOCKS_COMMAND_RESOLVE); 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) 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", - 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); return 0; } @@ -1395,7 +1402,7 @@ int connection_ap_make_bridge(char *address, uint16_t port) { int fd[2]; - connection_t *conn; + edge_connection_t *conn; int err; 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[1]); - conn = connection_new(CONN_TYPE_AP); - conn->s = fd[0]; + conn = TO_EDGE_CONN(connection_new(CONN_TYPE_AP)); + conn->_base.s = fd[0]; /* 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->command = SOCKS_COMMAND_CONNECT; - conn->address = tor_strdup("(local bridge)"); - conn->addr = 0; - conn->port = 0; + conn->_base.address = tor_strdup("(local bridge)"); + conn->_base.addr = 0; + conn->_base.port = 0; - if (connection_add(conn) < 0) { /* no space, forget it */ - connection_free(conn); /* this closes fd[0] */ + if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */ + connection_free(TO_CONN(conn)); /* this closes fd[0] */ tor_close_socket(fd[1]); return -1; } - conn->state = AP_CONN_STATE_CIRCUIT_WAIT; - connection_start_reading(conn); + conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; + connection_start_reading(TO_CONN(conn)); /* attaching to a dirty circuit is fine */ 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. **/ void -connection_ap_handshake_socks_resolved(connection_t *conn, +connection_ap_handshake_socks_resolved(edge_connection_t *conn, int answer_type, size_t answer_len, 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. */ 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, socks5_reply_status_t status) { char buf[256]; @@ -1538,7 +1545,7 @@ connection_ap_handshake_socks_reply(connection_t *conn, char *reply, return; } 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; return; } @@ -1548,7 +1555,7 @@ connection_ap_handshake_socks_reply(connection_t *conn, char *reply, #define SOCKS4_REJECT 91 buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT); /* 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) { buf[0] = 5; /* version 5 */ buf[1] = (char)status; @@ -1556,7 +1563,7 @@ connection_ap_handshake_socks_reply(connection_t *conn, char *reply, buf[3] = 1; /* ipv4 addr */ memset(buf+4,0,6); /* Set external addr/port to 0. 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. * This can happen in the case of AP bridges. */ @@ -1583,7 +1590,7 @@ connection_ap_handshake_socks_reply(connection_t *conn, char *reply, int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { - connection_t *n_stream; + edge_connection_t *n_stream; relay_header_t rh; char *address=NULL; uint16_t port; @@ -1623,11 +1630,11 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) #endif log_debug(LD_EXIT,"Creating new exit connection."); - n_stream = connection_new(CONN_TYPE_EXIT); - n_stream->purpose = EXIT_PURPOSE_CONNECT; + n_stream = TO_EDGE_CONN(connection_new(CONN_TYPE_EXIT)); + n_stream->_base.purpose = EXIT_PURPOSE_CONNECT; 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 */ n_stream->package_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) { origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ); log_debug(LD_REND,"begin is for rendezvous. configuring stream."); - n_stream->address = tor_strdup("(rendezvous)"); - n_stream->state = EXIT_CONN_STATE_CONNECTING; + n_stream->_base.address = tor_strdup("(rendezvous)"); + n_stream->_base.state = EXIT_CONN_STATE_CONNECTING; strlcpy(n_stream->rend_query, origin_circ->rend_query, sizeof(n_stream->rend_query)); tor_assert(connection_edge_is_rendezvous_stream(n_stream)); assert_circuit_ok(circ); if (rend_service_set_connection_addr_port(n_stream, origin_circ) < 0) { 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, n_stream->cpath_layer); - connection_free(n_stream); + connection_free(TO_CONN(n_stream)); /* knock the whole thing down, somebody screwed up */ circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED); tor_free(address); @@ -1667,14 +1674,14 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) return 0; } tor_strlower(address); - n_stream->address = address; - n_stream->state = EXIT_CONN_STATE_RESOLVEFAILED; + n_stream->_base.address = address; + n_stream->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; /* default to failed, change in dns_resolve if it turns out not to fail */ if (we_are_hibernating()) { connection_edge_end(n_stream, END_STREAM_REASON_HIBERNATING, n_stream->cpath_layer); - connection_free(n_stream); + connection_free(TO_CONN(n_stream)); return 0; } 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 connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) { - connection_t *dummy_conn; + edge_connection_t *dummy_conn; relay_header_t rh; 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, * 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->address = tor_strndup(cell->payload+RELAY_HEADER_SIZE, - rh.length); - dummy_conn->port = 0; - dummy_conn->state = EXIT_CONN_STATE_RESOLVEFAILED; - dummy_conn->purpose = EXIT_PURPOSE_RESOLVE; + dummy_conn->_base.address = tor_strndup(cell->payload+RELAY_HEADER_SIZE, + rh.length); + dummy_conn->_base.port = 0; + dummy_conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; + dummy_conn->_base.purpose = EXIT_PURPOSE_RESOLVE; /* send it off to the gethostbyname farm */ 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. */ return 0; case 1: /* The result was cached; a resolved cell was sent. */ - if (!dummy_conn->marked_for_close) - connection_free(dummy_conn); + if (!dummy_conn->_base.marked_for_close) + connection_free(TO_CONN(dummy_conn)); return 0; case 0: /* resolve added to pending list */ 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.) */ void -connection_exit_connect(connection_t *conn) +connection_exit_connect(edge_connection_t *edge_conn) { uint32_t addr; uint16_t port; + connection_t *conn = TO_CONN(edge_conn); - if (!connection_edge_is_rendezvous_stream(conn) && - router_compare_to_my_exit_policy(conn)) { + if (!connection_edge_is_rendezvous_stream(edge_conn) && + router_compare_to_my_exit_policy(edge_conn)) { log_info(LD_EXIT,"%s:%d failed exit policy. Closing.", escaped_safe_str(conn->address), conn->port); - connection_edge_end(conn, END_STREAM_REASON_EXITPOLICY, conn->cpath_layer); - circuit_detach_stream(circuit_get_by_edge_conn(conn), conn); + connection_edge_end(edge_conn, END_STREAM_REASON_EXITPOLICY, + edge_conn->cpath_layer); + circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn); connection_free(conn); return; } @@ -1802,8 +1811,8 @@ connection_exit_connect(connection_t *conn) log_debug(LD_EXIT,"about to try connecting"); switch (connection_connect(conn, conn->address, addr, port)) { case -1: - connection_edge_end_errno(conn, conn->cpath_layer); - circuit_detach_stream(circuit_get_by_edge_conn(conn), conn); + connection_edge_end_errno(edge_conn, edge_conn->cpath_layer); + circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn); connection_free(conn); return; case 0: @@ -1825,20 +1834,20 @@ connection_exit_connect(connection_t *conn) connection_watch_events(conn, EV_READ); /* 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! */ - 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, - NULL, 0, conn->cpath_layer); + NULL, 0, edge_conn->cpath_layer); } else { /* normal stream */ /* This must be the original address, not the redirected address. */ char connected_payload[8]; set_uint32(connected_payload, htonl(conn->addr)); set_uint32(connected_payload+4, - htonl(dns_clip_ttl(conn->address_ttl))); - connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), + htonl(dns_clip_ttl(edge_conn->address_ttl))); + connection_edge_send_command(edge_conn, circuit_get_by_edge_conn(edge_conn), 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. */ int -connection_edge_is_rendezvous_stream(connection_t *conn) +connection_edge_is_rendezvous_stream(edge_connection_t *conn) { tor_assert(conn); if (*conn->rend_query) /* XXX */ @@ -1860,10 +1869,10 @@ connection_edge_is_rendezvous_stream(connection_t *conn) * resolved.) */ 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->type == CONN_TYPE_AP); + tor_assert(conn->_base.type == CONN_TYPE_AP); tor_assert(conn->socks_request); tor_assert(exit); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 9b574d4902..4a9f8f4e93 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -19,8 +19,8 @@ const char connection_or_c_id[] = #define TIGHT_CERT_ALLOW_SKEW (90*60) -static int connection_tls_finish_handshake(connection_t *conn); -static int connection_or_process_cells_from_inbuf(connection_t *conn); +static int connection_tls_finish_handshake(or_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 * conn->identity_digest. */ 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->type == CONN_TYPE_OR); if (!orconn_identity_map) return; 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) { connection_t* conn = carray[i]; if (conn->type == CONN_TYPE_OR) { - memset(conn->identity_digest, 0, DIGEST_LEN); - conn->next_with_same_id = NULL; + or_connection_t *or_conn = TO_OR_CONN(conn); + 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 * orconn_digest_map. */ 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->type == CONN_TYPE_OR); tor_assert(digest); if (!orconn_identity_map) @@ -136,10 +135,10 @@ cell_unpack(cell_t *dest, const char *src) } 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."); - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); return 0; } @@ -149,13 +148,14 @@ connection_or_reached_eof(connection_t *conn) * and hope for better luck next time. */ static int -connection_or_read_proxy_response(connection_t *conn) +connection_or_read_proxy_response(or_connection_t *or_conn) { char *headers; char *reason=NULL; int status_code; time_t date_header; int compression; + connection_t *conn = TO_CONN(or_conn); switch (fetch_from_buf_http(conn->inbuf, &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.", conn->address, escaped(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. */ connection_mark_for_close(conn); @@ -209,12 +209,11 @@ connection_or_read_proxy_response(connection_t *conn) * (else do nothing). */ int -connection_or_process_inbuf(connection_t *conn) +connection_or_process_inbuf(or_connection_t *conn) { tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_OR); - switch (conn->state) { + switch (conn->_base.state) { case OR_CONN_STATE_PROXY_READING: return connection_or_read_proxy_response(conn); case OR_CONN_STATE_OPEN: @@ -233,24 +232,22 @@ connection_or_process_inbuf(connection_t *conn) * return 0. */ int -connection_or_finished_flushing(connection_t *conn) +connection_or_finished_flushing(or_connection_t *conn) { tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_OR); - - assert_connection_ok(conn,0); + assert_connection_ok(TO_CONN(conn),0); - switch (conn->state) { + switch (conn->_base.state) { case OR_CONN_STATE_PROXY_FLUSHING: log_debug(LD_OR,"finished sending CONNECT to proxy."); - conn->state = OR_CONN_STATE_PROXY_READING; - connection_stop_writing(conn); + conn->_base.state = OR_CONN_STATE_PROXY_READING; + connection_stop_writing(TO_CONN(conn)); break; case OR_CONN_STATE_OPEN: - connection_stop_writing(conn); + connection_stop_writing(TO_CONN(conn)); break; 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(); return -1; } @@ -260,10 +257,11 @@ connection_or_finished_flushing(connection_t *conn) /** Connected handler for OR connections: begin the TLS handshake. */ int -connection_or_finished_connecting(connection_t *conn) +connection_or_finished_connecting(or_connection_t *or_conn) { - tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_OR); + connection_t *conn; + tor_assert(or_conn); + conn = TO_CONN(or_conn); tor_assert(conn->state == OR_CONN_STATE_CONNECTING); 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; } - if (connection_tls_start_handshake(conn, 0) < 0) { + if (connection_tls_start_handshake(or_conn, 0) < 0) { /* TLS handshaking error of some kind. */ connection_mark_for_close(conn); 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 * by checking to see if this describes a router we know. */ 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, const char *id_digest, int started_here) @@ -320,19 +318,19 @@ connection_or_init_conn_from_address(connection_t *conn, conn->bandwidthrate = (int)options->BandwidthRate; conn->receiver_bucket = conn->bandwidthburst = (int)options->BandwidthBurst; connection_or_set_identity_digest(conn, id_digest); - conn->addr = addr; - conn->port = port; + conn->_base.addr = addr; + conn->_base.port = port; if (r) { if (!started_here) { /* Override the addr/port, so our log messages will make sense. * This is dangerous, since if we ever try looking up a conn by * its actual addr/port, we won't remember. Careful! */ - conn->addr = r->addr; - conn->port = r->or_port; + conn->_base.addr = r->addr; + conn->_base.port = r->or_port; } conn->nickname = tor_strdup(r->nickname); - tor_free(conn->address); - conn->address = tor_strdup(r->address); + tor_free(conn->_base.address); + conn->_base.address = tor_strdup(r->address); } else { const char *n; /* 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, conn->identity_digest, DIGEST_LEN); } - tor_free(conn->address); - conn->address = tor_dup_addr(addr); + tor_free(conn->_base.address); + 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. * 5) Of the remaining conns, prefer newer conns. */ -connection_t * +or_connection_t * connection_or_get_by_identity_digest(const char *digest) { int newer; - connection_t *conn, *best=NULL; + or_connection_t *conn, *best=NULL; if (!orconn_identity_map) return NULL; @@ -372,26 +370,26 @@ connection_or_get_by_identity_digest(const char *digest) conn = digestmap_get(orconn_identity_map, digest); for (; conn; conn = conn->next_with_same_id) { - tor_assert(conn->magic == CONNECTION_MAGIC); - tor_assert(conn->type == CONN_TYPE_OR); + tor_assert(conn->_base.magic == OR_CONNECTION_MAGIC); + tor_assert(conn->_base.type == CONN_TYPE_OR); tor_assert(!memcmp(conn->identity_digest, digest, DIGEST_LEN)); - if (conn->marked_for_close) + if (conn->_base.marked_for_close) continue; if (!best) { best = conn; /* whatever it is, it's better than nothing. */ continue; } - if (best->state == OR_CONN_STATE_OPEN && - conn->state != OR_CONN_STATE_OPEN) + if (best->_base.state == OR_CONN_STATE_OPEN && + conn->_base.state != OR_CONN_STATE_OPEN) 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. */ if ( /* 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: */ (best->n_circuits && conn->n_circuits && 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. */ -connection_t * +or_connection_t * 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(); tor_assert(id_digest); @@ -431,11 +429,11 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest) 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 */ 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); if (options->HttpsProxy) { @@ -444,7 +442,7 @@ connection_or_connect(uint32_t addr, uint16_t port, const char *id_digest) port = options->HttpsProxyPort; } - switch (connection_connect(conn, conn->address, addr, port)) { + switch (connection_connect(TO_CONN(conn), conn->_base.address, addr, port)) { case -1: /* If the connection failed immediately, and we're using * 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); } control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED); - connection_free(conn); + connection_free(TO_CONN(conn)); return NULL; 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, error indicates broken link on windows */ 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. */ 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->tls = tor_tls_new(conn->s, receiving); + conn->_base.state = OR_CONN_STATE_HANDSHAKING; + conn->tls = tor_tls_new(conn->_base.s, receiving); if (!conn->tls) { log_warn(LD_BUG,"tor_tls_new failed. Closing."); return -1; } - connection_start_reading(conn); - log_debug(LD_OR,"starting TLS handshake on fd %d", conn->s); + connection_start_reading(TO_CONN(conn)); + log_debug(LD_OR,"starting TLS handshake on fd %d", conn->_base.s); if (connection_tls_continue_handshake(conn) < 0) { 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. */ int -connection_tls_continue_handshake(connection_t *conn) +connection_tls_continue_handshake(or_connection_t *conn) { check_no_tls_errors(); switch (tor_tls_handshake(conn->tls)) { @@ -513,7 +511,7 @@ connection_tls_continue_handshake(connection_t *conn) case TOR_TLS_DONE: return connection_tls_finish_handshake(conn); case TOR_TLS_WANTWRITE: - connection_start_writing(conn); + connection_start_writing(TO_CONN(conn)); log_debug(LD_OR,"wanted write"); return 0; 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. */ 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) return 1; /* it's still in proxy states or something */ 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. */ 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; 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(); if (! tor_tls_peer_has_cert(conn->tls)) { 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; } check_no_tls_errors(); @@ -576,17 +574,17 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd) sizeof(nickname))) { log_fn(severity,LD_PROTOCOL,"Other side (%s:%d) has a cert without a " "valid nickname. Closing.", - conn->address, conn->port); + conn->_base.address, conn->_base.port); return -1; } check_no_tls_errors(); 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) { log_fn(severity,LD_OR,"Other side, which claims to be router '%s' (%s:%d)," " has a cert but it's invalid. Closing.", - nickname, conn->address, conn->port); + nickname, conn->_base.address, conn->_base.port); return -1; } check_no_tls_errors(); @@ -607,7 +605,7 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd) log_fn(severity, LD_OR, "Identity key not as expected for router claiming to be " "'%s' (%s:%d)", - nickname, conn->address, conn->port); + nickname, conn->_base.address, conn->_base.port); return -1; } @@ -623,7 +621,7 @@ connection_or_check_valid_handshake(connection_t *conn, char *digest_rcvd) log_fn(severity, LD_OR, "Identity key not as expected for router at %s:%d: wanted %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); router_set_status(conn->identity_digest, 0); 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 * 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); } 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). */ static int -connection_tls_finish_handshake(connection_t *conn) +connection_tls_finish_handshake(or_connection_t *conn) { char digest_rcvd[DIGEST_LEN]; int started_here = connection_or_nonopen_was_started_here(conn); @@ -664,7 +662,7 @@ connection_tls_finish_handshake(connection_t *conn) return -1; 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); /* 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 * Tor 0.1.1.x where middle hops don't always send their create * 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(); } 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); if (started_here) { 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); } - 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. */ return 0; } @@ -704,18 +702,17 @@ connection_tls_finish_handshake(connection_t *conn) * ready, then try to flush the record now. */ 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 *n = networkcell; tor_assert(cell); tor_assert(conn); - tor_assert(connection_speaks_cells(conn)); 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 /* 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 * input before pushing any data out. It also has the feature of not * growing huge outbufs unless something is slow. */ - if (conn->outbuf_flushlen-CELL_NETWORK_SIZE < MIN_TLS_FLUSHLEN && - conn->outbuf_flushlen >= MIN_TLS_FLUSHLEN) { - int extra = conn->outbuf_flushlen - MIN_TLS_FLUSHLEN; - conn->outbuf_flushlen = MIN_TLS_FLUSHLEN; - if (connection_handle_write(conn) < 0) { - if (!conn->marked_for_close) { + if (conn->_base.outbuf_flushlen-CELL_NETWORK_SIZE < MIN_TLS_FLUSHLEN && + conn->_base.outbuf_flushlen >= MIN_TLS_FLUSHLEN) { + int extra = conn->_base.outbuf_flushlen - MIN_TLS_FLUSHLEN; + conn->_base.outbuf_flushlen = MIN_TLS_FLUSHLEN; + if (connection_handle_write(TO_CONN(conn)) < 0) { + if (!conn->_base.marked_for_close) { /* this connection is broken. remove it. */ log_warn(LD_BUG, "Bug: unhandled error on write for OR conn (fd %d); removing", - conn->s); + conn->_base.s); 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? */ - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); } return; } if (extra) { - conn->outbuf_flushlen += extra; - connection_start_writing(conn); + conn->_base.outbuf_flushlen += extra; + 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. */ 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]; cell_t cell; @@ -763,13 +762,13 @@ connection_or_process_cells_from_inbuf(connection_t *conn) loop: log_debug(LD_OR, "%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)); - if (buf_datalen(conn->inbuf) < CELL_NETWORK_SIZE) /* whole response - available? */ + if (buf_datalen(conn->_base.inbuf) < CELL_NETWORK_SIZE) /* whole response + available? */ 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 * network-order string) */ @@ -787,12 +786,11 @@ loop: * Return 0. */ 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; tor_assert(conn); - tor_assert(connection_speaks_cells(conn)); memset(&cell, 0, sizeof(cell_t)); cell.circ_id = circ_id; diff --git a/src/or/control.c b/src/or/control.c index 7737e9a21f..d8e2fb5a7b 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -131,57 +131,57 @@ static int disable_log_messages = 0; static int authentication_cookie_is_set = 0; 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, ...) CHECK_PRINTF(2,3); /*static*/ size_t write_escaped_data(const char *data, size_t len, int translate_newlines, char **out); /*static*/ size_t read_escaped_data(const char *data, size_t len, 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); -static void send_control_done(connection_t *conn); -static void send_control_done2(connection_t *conn, const char *msg, +static void send_control_done(control_connection_t *conn); +static void send_control_done2(control_connection_t *conn, const char *msg, 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); static void send_control0_event(uint16_t event, uint32_t len, const char *body); static void send_control1_event(uint16_t event, const char *format, ...) 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); -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); -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); -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); -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); -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); -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); -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); -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); -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); -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); -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); -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); -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); -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); -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); -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); /** 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) { if (conns[i]->type == CONN_TYPE_CONTROL && STATE_IS_OPEN(conns[i]->state)) { - if (STATE_IS_V0(conns[i]->state)) - global_event_mask0 |= conns[i]->event_mask; + control_connection_t *conn = TO_CONTROL_CONN(conns[i]); + if (STATE_IS_V0(conn->_base.state)) + global_event_mask0 |= conn->event_mask; 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 */ 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); - 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 @@ -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 * ending \n\r\0. */ 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 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-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 * from <b>body</b> along the control connection <b>conn</b> */ static void -send_control0_message(connection_t *conn, uint16_t type, uint32_t len, - const char *body) +send_control0_message(control_connection_t *conn, uint16_t type, uint32_t len, + const char *body) { char buf[10]; tor_assert(conn); - tor_assert(STATE_IS_V0(conn->state)); + tor_assert(STATE_IS_V0(conn->_base.state)); tor_assert(len || !body); tor_assert(type <= _CONTROL0_CMD_MAX_RECOGNIZED); if (len < 65536) { set_uint16(buf, htons(len)); set_uint16(buf+2, htons(type)); - connection_write_to_buf(buf, 4, conn); + connection_write_to_buf(buf, 4, TO_CONN(conn)); if (len) - connection_write_to_buf(body, len, conn); + connection_write_to_buf(body, len, TO_CONN(conn)); } else { set_uint16(buf, htons(65535)); set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENTHEADER)); set_uint16(buf+4, htons(type)); set_uint32(buf+6, htonl(len)); - connection_write_to_buf(buf, 10, conn); - connection_write_to_buf(body, 65535-6, conn); + connection_write_to_buf(buf, 10, TO_CONN(conn)); + connection_write_to_buf(body, 65535-6, TO_CONN(conn)); len -= (65535-6); body += (65535-6); while (len) { size_t chunklen = (len<65535)?len:65535; set_uint16(buf, htons((uint16_t)chunklen)); set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENT)); - connection_write_to_buf(buf, 4, conn); - connection_write_to_buf(body, chunklen, conn); + connection_write_to_buf(buf, 4, TO_CONN(conn)); + connection_write_to_buf(body, chunklen, TO_CONN(conn)); len -= 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> */ 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); } else { 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>. */ 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) 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 * <b>message</b> down the connection <b>conn</b> */ 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]; 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) { if (conns[i]->type == CONN_TYPE_CONTROL && !conns[i]->marked_for_close && - conns[i]->state == CONTROL_CONN_STATE_OPEN_V0 && - conns[i]->event_mask & (1<<event)) { - send_control0_message(conns[i], CONTROL0_CMD_EVENT, buflen, buf); - if (event == EVENT_ERR_MSG) - _connection_controller_force_write(conns[i]); + conns[i]->state == CONTROL_CONN_STATE_OPEN_V0) { + control_connection_t *control_conn = TO_CONTROL_CONN(conns[i]); + if (control_conn->event_mask & (1<<event)) { + send_control0_message(control_conn, CONTROL0_CMD_EVENT, buflen, buf); + 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) { if (conns[i]->type == CONN_TYPE_CONTROL && !conns[i]->marked_for_close && - conns[i]->state == CONTROL_CONN_STATE_OPEN_V1 && - conns[i]->event_mask & (1<<event)) { - connection_write_to_buf(msg, strlen(msg), conns[i]); - if (event == EVENT_ERR_MSG) - _connection_controller_force_write(conns[i]); + conns[i]->state == CONTROL_CONN_STATE_OPEN_V1) { + control_connection_t *control_conn = TO_CONTROL_CONN(conns[i]); + if (control_conn->event_mask & (1<<event)) { + connection_write_to_buf(msg, strlen(msg), TO_CONN(control_conn)); + 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(). */ 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 r; config_line_t *lines=NULL; char *start = body; char *errstring = NULL; - int v0 = STATE_IS_V0(conn->state); + int v0 = STATE_IS_V0(conn->_base.state); if (!v0) { 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 * to update our configuration. Reply with a DONE or ERROR message. */ 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); } @@ -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 * to update our configuration. Reply with a DONE or ERROR message. */ 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); 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 * reply with a CONFVALUE or an ERROR message */ 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 *answers = NULL; @@ -787,7 +792,7 @@ handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body) char *msg = NULL; size_t msg_len; or_options_t *options = get_options(); - int v0 = STATE_IS_V0(conn->state); + int v0 = STATE_IS_V0(conn->_base.state); questions = smartlist_create(); (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); tmp[3] = ' '; 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 { 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, * and reply with DONE or ERROR. */ 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; uint32_t event_mask = 0; unsigned int extended = 0; - if (STATE_IS_V0(conn->state)) { + if (STATE_IS_V0(conn->_base.state)) { if (len % 2) { send_control0_error(conn, ERR_SYNTAX, "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); } conn->event_mask = event_mask; - conn->control_events_are_extended = extended; + conn->_base.control_events_are_extended = extended; control_update_global_event_mask(); send_control_done(conn); @@ -987,13 +992,13 @@ decode_hashed_password(char *buf, const char *hashed) * OPEN. Reply with DONE or ERROR. */ 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; or_options_t *options = get_options(); char *password; size_t password_len; - if (STATE_IS_V0(conn->state)) { + if (STATE_IS_V0(conn->_base.state)) { password = (char*)body; password_len = len; } else { @@ -1047,7 +1052,7 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body) } err: - if (STATE_IS_V0(conn->state)) + if (STATE_IS_V0(conn->_base.state)) send_control0_error(conn,ERR_REJECTED_AUTHENTICATION, "Authentication failed"); else { @@ -1061,12 +1066,12 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body) } return 0; 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); - if (STATE_IS_V0(conn->state)) - conn->state = CONTROL_CONN_STATE_OPEN_V0; + if (STATE_IS_V0(conn->_base.state)) + conn->_base.state = CONTROL_CONN_STATE_OPEN_V0; else { - conn->state = CONTROL_CONN_STATE_OPEN_V1; + conn->_base.state = CONTROL_CONN_STATE_OPEN_V1; tor_free(password); } 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 * disk, and report success or failure. */ static int -handle_control_saveconf(connection_t *conn, uint32_t len, +handle_control_saveconf(control_connection_t *conn, uint32_t len, const char *body) { (void) len; (void) body; if (options_save_current()<0) { - if (STATE_IS_V0(conn->state)) + if (STATE_IS_V0(conn->_base.state)) send_control0_error(conn, ERR_INTERNAL, "Unable to write configuration to disk."); 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 * may not be reported.) */ static int -handle_control_signal(connection_t *conn, uint32_t len, +handle_control_signal(control_connection_t *conn, uint32_t len, const char *body) { int sig; - if (STATE_IS_V0(conn->state)) { + if (STATE_IS_V0(conn->_base.state)) { if (len != 1) { send_control0_error(conn, ERR_SYNTAX, "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 (STATE_IS_V0(conn->state)) + if (STATE_IS_V0(conn->_base.state)) send_control0_error(conn, ERR_SYNTAX, "Unrecognized signal number."); else 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, * and report success or failrue. */ 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 *lines; smartlist_t *reply; char *r; 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. */ lines = smartlist_create(); @@ -1257,12 +1262,12 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body) if (smartlist_len(reply)) { ((char*)smartlist_get(reply,smartlist_len(reply)-1))[3] = ' '; 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); } else { const char *response = "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); for (i=0; i < n_conns; ++i) { const char *state; + edge_connection_t *conn; char *s; size_t slen; circuit_t *circ; @@ -1406,12 +1412,13 @@ handle_getinfo_helper(const char *question, char **answer) conns[i]->marked_for_close || conns[i]->state == AP_CONN_STATE_SOCKS_WAIT) 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_CIRCUIT_WAIT: - if (conns[i]->socks_request && - conns[i]->socks_request->command == SOCKS_COMMAND_RESOLVE) + if (conn->socks_request && + conn->socks_request->command == SOCKS_COMMAND_RESOLVE) state = "NEWRESOLVE"; else state = "NEW"; @@ -1425,15 +1432,15 @@ handle_getinfo_helper(const char *question, char **answer) state = "SUCCEEDED"; break; default: log_warn(LD_BUG, "Asked for stream in unknown state %d", - conns[i]->state); + conn->_base.state); continue; } - circ = circuit_get_by_edge_conn(conns[i]); - write_stream_target_to_buf(conns[i], buf, sizeof(buf)); + circ = circuit_get_by_edge_conn(conn); + write_stream_target_to_buf(conn, buf, sizeof(buf)); slen = strlen(buf)+strlen(state)+32; s = tor_malloc(slen+1); 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, buf); smartlist_add(status, s); @@ -1451,10 +1458,11 @@ handle_getinfo_helper(const char *question, char **answer) char *s; char name[128]; size_t slen; - connection_t *conn = conns[i]; - if (conn->type != CONN_TYPE_OR || conn->marked_for_close) + or_connection_t *conn; + if (conns[i]->type != CONN_TYPE_OR || conns[i]->marked_for_close) continue; - if (conn->state == OR_CONN_STATE_OPEN) + conn = TO_OR_CONN(conns[i]); + if (conn->_base.state == OR_CONN_STATE_OPEN) state = "CONNECTED"; else if (conn->nickname) state = "LAUNCHED"; @@ -1464,7 +1472,7 @@ handle_getinfo_helper(const char *question, char **answer) strlcpy(name, conn->nickname, sizeof(name)); else tor_snprintf(name, sizeof(name), "%s:%d", - conn->address, conn->port); + conn->_base.address, conn->_base.port); slen = strlen(name)+strlen(state)+2; 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 * information, and reply with information or error message. */ 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 *answers = NULL; smartlist_t *unrecognized = NULL; char *msg = NULL, *ans = NULL; 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. */ questions = smartlist_create(); @@ -1615,7 +1623,7 @@ handle_control_getinfo(connection_t *conn, uint32_t len, const char *body) size_t len; len = write_escaped_data(v, strlen(v), 1, &esc); 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); } } @@ -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 * circuit, and report success or failure. */ static int -handle_control_extendcircuit(connection_t *conn, uint32_t len, +handle_control_extendcircuit(control_connection_t *conn, uint32_t len, const char *body) { smartlist_t *router_nicknames=NULL, *routers=NULL; @@ -1672,7 +1680,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len, char reply[4]; 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(); if (v0) { @@ -1816,7 +1824,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len, * is 1) or SETROUTERPURPOSE message. If we can find * the circuit/router and it's a valid purpose, change it. */ 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) { circuit_t *circ = NULL; @@ -1868,14 +1876,15 @@ done: /** Called when we get an ATTACHSTREAM message. Try to attach the requested * stream, and report success or failure. */ static int -handle_control_attachstream(connection_t *conn, uint32_t len, +handle_control_attachstream(control_connection_t *conn, uint32_t len, const char *body) { connection_t *ap_conn = NULL; circuit_t *circ = NULL; 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 circ_id; 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 && ap_conn->state != AP_CONN_STATE_CONNECT_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, "Connection is not managed by controller."); } else { @@ -1938,20 +1947,23 @@ handle_control_attachstream(connection_t *conn, uint32_t len, return 0; } + edge_conn = TO_EDGE_CONN(ap_conn); + /* Do we need to detach it first? */ if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT) { - circuit_t *tmpcirc = circuit_get_by_edge_conn(ap_conn); - connection_edge_end(ap_conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer); + circuit_t *tmpcirc = circuit_get_by_edge_conn(edge_conn); + 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. */ - ap_conn->has_sent_end = 0; + ap_conn->edge_has_sent_end = 0; if (tmpcirc) - circuit_detach_stream(tmpcirc,ap_conn); + circuit_detach_stream(tmpcirc,edge_conn); ap_conn->state = AP_CONN_STATE_CONTROLLER_WAIT; } if (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, "Refuse to attach stream to non-open, origin circ."); else @@ -1960,9 +1972,9 @@ handle_control_attachstream(connection_t *conn, uint32_t len, conn); 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) { - if (STATE_IS_V0(conn->state)) + if (STATE_IS_V0(conn->_base.state)) send_control0_error(conn, ERR_INTERNAL, "Unable to attach stream."); else 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 * descriptor, and report success or failure. */ static int -handle_control_postdescriptor(connection_t *conn, uint32_t len, +handle_control_postdescriptor(control_connection_t *conn, uint32_t len, const char *body) { char *desc; - int v0 = STATE_IS_V0(conn->state); + int v0 = STATE_IS_V0(conn->_base.state); const char *msg=NULL; 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 * address of the named AP stream, and report success or failure. */ static int -handle_control_redirectstream(connection_t *conn, uint32_t len, +handle_control_redirectstream(control_connection_t *conn, uint32_t len, const char *body) { connection_t *ap_conn = NULL; uint32_t conn_id; char *new_addr = NULL; uint16_t new_port = 0; - if (STATE_IS_V0(conn->state)) { + if (STATE_IS_V0(conn->_base.state)) { if (len < 6) { send_control0_error(conn, ERR_SYNTAX, "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)) || ap_conn->state != CONN_TYPE_AP - || !ap_conn->socks_request) { + || !TO_EDGE_CONN(ap_conn)->socks_request) { send_control0_error(conn, ERR_NO_STREAM, "No AP connection found with given ID"); return 0; @@ -2066,7 +2078,7 @@ handle_control_redirectstream(connection_t *conn, uint32_t len, connection_printf_to_buf(conn, "512 Missing argument to REDIRECTSTREAM\r\n"); 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", (char*)smartlist_get(args, 0)); } else { @@ -2089,25 +2101,28 @@ handle_control_redirectstream(connection_t *conn, uint32_t len, return 0; } - strlcpy(ap_conn->socks_request->address, new_addr, - sizeof(ap_conn->socks_request->address)); - if (new_port) - ap_conn->socks_request->port = new_port; - tor_free(new_addr); - send_control_done(conn); - return 0; + { + edge_connection_t *ap = TO_EDGE_CONN(ap_conn); + strlcpy(ap->socks_request->address, new_addr, + sizeof(ap->socks_request->address)); + if (new_port) + ap->socks_request->port = new_port; + tor_free(new_addr); + send_control_done(conn); + return 0; + } } /** Called when we get a CLOSESTREAM command; try to close the named stream * and report success or failure. */ static int -handle_control_closestream(connection_t *conn, uint32_t len, +handle_control_closestream(control_connection_t *conn, uint32_t len, const char *body) { connection_t *ap_conn=NULL; uint8_t reason=0; - if (STATE_IS_V0(conn->state)) { + if (STATE_IS_V0(conn->_base.state)) { uint32_t conn_id; if (len < 6) { 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)) || ap_conn->state != CONN_TYPE_AP - || !ap_conn->socks_request) { + || !TO_EDGE_CONN(ap_conn)->socks_request) { send_control0_error(conn, ERR_NO_STREAM, "No AP connection found with given ID"); return 0; @@ -2151,7 +2166,7 @@ handle_control_closestream(connection_t *conn, uint32_t len, return 0; } - connection_mark_unattached_ap(ap_conn, reason); + connection_mark_unattached_ap(TO_EDGE_CONN(ap_conn), reason); send_control_done(conn); 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 * and report success or failure. */ static int -handle_control_closecircuit(connection_t *conn, uint32_t len, +handle_control_closecircuit(control_connection_t *conn, uint32_t len, const char *body) { circuit_t *circ = NULL; int safe = 0; - if (STATE_IS_V0(conn->state)) { + if (STATE_IS_V0(conn->_base.state)) { uint32_t circ_id; if (len < 5) { 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. */ 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) { 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. */ int -connection_control_finished_flushing(connection_t *conn) +connection_control_finished_flushing(control_connection_t *conn) { tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_CONTROL); - connection_stop_writing(conn); + connection_stop_writing(TO_CONN(conn)); return 0; } /** Called when <b>conn</b> has gotten its socket closed. */ int -connection_control_reached_eof(connection_t *conn) +connection_control_reached_eof(control_connection_t *conn) { tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_CONTROL); log_info(LD_CONTROL,"Control connection reached EOF. Closing."); - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); return 0; } @@ -2287,16 +2300,15 @@ connection_control_reached_eof(connection_t *conn) * commands from conn->inbuf, and execute them. */ static int -connection_control_process_inbuf_v1(connection_t *conn) +connection_control_process_inbuf_v1(control_connection_t *conn) { size_t data_len; int cmd_len; char *args; tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_CONTROL); - tor_assert(conn->state == CONTROL_CONN_STATE_OPEN_V1 || - conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1); + tor_assert(conn->_base.state == CONTROL_CONN_STATE_OPEN_V1 || + conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1); if (!conn->incoming_cmd) { conn->incoming_cmd = tor_malloc(1024); @@ -2311,7 +2323,7 @@ connection_control_process_inbuf_v1(connection_t *conn) /* First, fetch a line. */ do { 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, &data_len); if (r == 0) @@ -2361,11 +2373,11 @@ connection_control_process_inbuf_v1(connection_t *conn) if (!strcasecmp(conn->incoming_cmd, "QUIT")) { 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; } - if (conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1 && + if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1 && strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) { connection_write_str_to_buf("514 Authentication required.\r\n", conn); 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. */ static int -connection_control_process_inbuf_v0(connection_t *conn) +connection_control_process_inbuf_v0(control_connection_t *conn) { uint32_t body_len; uint16_t command_type; @@ -2444,15 +2456,15 @@ connection_control_process_inbuf_v0(connection_t *conn) again: /* Try to suck a control message from the buffer. */ - switch (fetch_from_buf_control0(conn->inbuf, &body_len, &command_type, &body, - conn->state == CONTROL_CONN_STATE_NEEDAUTH_V0)) + switch (fetch_from_buf_control0(conn->_base.inbuf, &body_len, &command_type, &body, + conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V0)) { case -2: tor_free(body); log_info(LD_CONTROL, "Detected v1 control protocol on connection (fd %d)", - conn->s); - conn->state = CONTROL_CONN_STATE_NEEDAUTH_V1; + conn->_base.s); + conn->_base.state = CONTROL_CONN_STATE_NEEDAUTH_V1; return connection_control_process_inbuf_v1(conn); case -1: 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 * 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) { log_info(LD_CONTROL, "Rejecting '%s' command; authentication needed.", 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. */ int -connection_control_process_inbuf(connection_t *conn) +connection_control_process_inbuf(control_connection_t *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); else 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 * failure. */ 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]; 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 * <b>conn</b>: tell any interested control connections. */ 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; size_t len; char buf[256]; - tor_assert(conn->type == CONN_TYPE_AP); tor_assert(conn->socks_request); 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); msg = tor_malloc(5+len+1); 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); 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); send_control1_event(EVENT_STREAM_STATUS, "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, buf); /* 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 * interested control connections. */ 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 */ size_t len; - tor_assert(conn->type == CONN_TYPE_OR); - if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS)) 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)); else tor_snprintf(name, sizeof(name), "%s:%d", - conn->address, conn->port); + conn->_base.address, conn->_base.port); switch (tp) { case OR_CONN_EVENT_LAUNCHED: status = "LAUNCHED"; break; diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 1ed91b0426..66827bf20e 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -137,7 +137,7 @@ connection_cpu_process_inbuf(connection_t *conn) uint32_t addr; uint16_t port; uint16_t circ_id; - connection_t *p_conn; + or_connection_t *p_conn; circuit_t *circ; 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."); 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; /* touch the lastwritten timestamp, since that's how we check to diff --git a/src/or/directory.c b/src/or/directory.c index c6af9b86a1..e788a0a1a9 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -38,16 +38,16 @@ directory_initiate_command(const char *address, uint32_t addr, uint16_t port, const char *payload, size_t payload_len); 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, 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 purpose_is_private(uint8_t purpose); 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 connection_dir_download_networkstatus_failed(connection_t *conn); -static void connection_dir_download_routerdesc_failed(connection_t *conn); +static void connection_dir_download_networkstatus_failed(dir_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_routerdesc_download_failed(smartlist_t *failed); 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. */ void -connection_dir_request_failed(connection_t *conn) +connection_dir_request_failed(dir_connection_t *conn) { if (router_digest_is_me(conn->identity_digest)) return; /* this was a test fetch. don't retry. */ router_set_status(conn->identity_digest, 0); /* don't try him again */ - if (conn->purpose == DIR_PURPOSE_FETCH_DIR || - conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) { + if (conn->_base.purpose == DIR_PURPOSE_FETCH_DIR || + conn->_base.purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) { log_info(LD_DIR, "Giving up on directory server at '%s:%d'; retrying", - conn->address, conn->port); - directory_get_from_dirserver(conn->purpose, NULL, + conn->_base.address, conn->_base.port); + directory_get_from_dirserver(conn->_base.purpose, NULL, 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", - conn->address); + conn->_base.address); 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", - conn->address); + conn->_base.address); connection_dir_download_routerdesc_failed(conn); } } @@ -288,7 +288,7 @@ connection_dir_request_failed(connection_t *conn) * retry the fetch now, later, or never. */ static void -connection_dir_download_networkstatus_failed(connection_t *conn) +connection_dir_download_networkstatus_failed(dir_connection_t *conn) { if (!conn->requested_resource) { /* 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_FOREACH(trusted_dirs, trusted_dir_server_t *, ds, ++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 */); } else if (!strcmpstart(conn->requested_resource, "fp/")) { /* 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. */ 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 * it's not their fault.*/ @@ -342,7 +342,7 @@ directory_initiate_command(const char *address, uint32_t addr, int private_connection, const char *resource, const char *payload, size_t payload_len) { - connection_t *conn; + dir_connection_t *conn; tor_assert(address); tor_assert(addr); @@ -376,18 +376,18 @@ directory_initiate_command(const char *address, uint32_t addr, 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 */ - conn->addr = addr; - conn->port = dir_port; - conn->address = tor_strdup(address); + conn->_base.addr = addr; + conn->_base.port = dir_port; + conn->_base.address = tor_strdup(address); memcpy(conn->identity_digest, digest, DIGEST_LEN); - conn->purpose = purpose; + conn->_base.purpose = purpose; /* give it an initial state */ - conn->state = DIR_CONN_STATE_CONNECTING; + conn->_base.state = DIR_CONN_STATE_CONNECTING; conn->dirconn_direct = (private_connection == 0); if (!private_connection) { @@ -398,19 +398,19 @@ directory_initiate_command(const char *address, uint32_t addr, 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: connection_dir_request_failed(conn); /* retry if we want */ - connection_free(conn); + connection_free(TO_CONN(conn)); return; 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 */ case 0: /* queue the command on the outbuf */ directory_send_command(conn, platform, purpose, resource, 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, 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 * socketpair and hook up both sides */ - conn->s = connection_ap_make_bridge(conn->address, conn->port); - if (conn->s < 0) { + conn->_base.s = connection_ap_make_bridge(conn->_base.address, + conn->_base.port); + if (conn->_base.s < 0) { log_warn(LD_NET,"Making AP bridge to dirserver failed."); - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); return; } - if (connection_add(conn) < 0) { + if (connection_add(TO_CONN(conn)) < 0) { log_warn(LD_NET,"Unable to add AP bridge to dirserver."); - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); return; } - conn->state = DIR_CONN_STATE_CLIENT_SENDING; + conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING; /* queue the command on the outbuf */ directory_send_command(conn, platform, purpose, resource, 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. */ 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, const char *payload, size_t payload_len) { @@ -456,18 +457,18 @@ directory_send_command(connection_t *conn, const char *platform, size_t len; tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_DIR); + tor_assert(conn->_base.type == CONN_TYPE_DIR); tor_free(conn->requested_resource); if (resource) conn->requested_resource = tor_strdup(resource); /* come up with a string for which Host: we want */ - if (conn->port == 80) { - strlcpy(hoststring, conn->address, sizeof(hoststring)); + if (conn->_base.port == 80) { + strlcpy(hoststring, conn->_base.address, sizeof(hoststring)); } else { 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. */ @@ -564,8 +565,8 @@ directory_send_command(connection_t *conn, const char *platform, } tor_snprintf(request, sizeof(request), "%s %s", httpcommand, proxystring); - connection_write_to_buf(request, strlen(request), conn); - connection_write_to_buf(url, strlen(url), conn); + connection_write_to_buf(request, strlen(request), TO_CONN(conn)); + connection_write_to_buf(url, strlen(url), TO_CONN(conn)); tor_free(url); if (!strcmp(httpcommand, "GET") && !payload) { @@ -580,11 +581,11 @@ directory_send_command(connection_t *conn, const char *platform, hoststring, proxyauthstring); } - connection_write_to_buf(request, strlen(request), conn); + connection_write_to_buf(request, strlen(request), TO_CONN(conn)); if (payload) { /* 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. */ static int -connection_dir_client_reached_eof(connection_t *conn) +connection_dir_client_reached_eof(dir_connection_t *conn) { char *body; char *headers; @@ -816,17 +817,17 @@ connection_dir_client_reached_eof(connection_t *conn) int compression; int plausible; 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; - switch (fetch_from_buf_http(conn->inbuf, + switch (fetch_from_buf_http(conn->_base.inbuf, &headers, MAX_HEADERS_SIZE, &body, &body_len, MAX_DIR_SIZE, allow_partial)) { case -1: /* overflow */ log_warn(LD_PROTOCOL, "'fetch' response too large (server '%s:%d'). Closing.", - conn->address, conn->port); + conn->_base.address, conn->_base.port); return -1; case 0: 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, &compression, &reason) < 0) { 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); return -1; } @@ -847,7 +848,7 @@ connection_dir_client_reached_eof(connection_t *conn) log_debug(LD_DIR, "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. */ if (server_mode(get_options())) { @@ -867,7 +868,7 @@ connection_dir_client_reached_eof(connection_t *conn) LD_HTTP, "Received directory with skewed time (server '%s:%d'): " "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 ? "behind" : "ahead"); 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) { log_info(LD_DIR,"Received http status code %d (%s) from server " "'%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); return -1; } - plausible = body_is_plausible(body, body_len, conn->purpose); + plausible = body_is_plausible(body, body_len, conn->_base.purpose); if (compression || !plausible) { char *new_body = NULL; 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, " "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.":""); } /* Try declared compression first if we can. */ @@ -929,7 +930,7 @@ connection_dir_client_reached_eof(connection_t *conn) if (!plausible && !new_body) { log_fn(LOG_PROTOCOL_WARN, LD_HTTP, "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); 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. */ 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) { log_warn(LD_DIR,"Received http status code %d (%s) from server " "'%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); return -1; } if (router_parse_directory(body) < 0) { 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); } - 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 */ log_info(LD_DIR,"Received running-routers list (size %d)", (int)body_len); if (status_code != 200) { log_warn(LD_DIR,"Received http status code %d (%s) from server " "'%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); return -1; } if (router_parse_runningrouters(body)<0) { log_warn(LD_DIR, "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); return -1; } @@ -980,16 +981,16 @@ connection_dir_client_reached_eof(connection_t *conn) "dl/running-routers", orig_len); } - if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) { + if (conn->_base.purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) { smartlist_t *which = NULL; char *cp; 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) { log_warn(LD_DIR, "Received http status code %d (%s) from server " "'%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); tor_free(body); tor_free(headers); tor_free(reason); 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; int n_asked_for = 0; 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); if (conn->requested_resource && !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, "Received http status code %d (%s) from server '%s:%d' " "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); if (!which) { 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 */ log_info(LD_DIR, "Received %d/%d routers requested from %s:%d", 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)) { dir_routerdesc_download_failed(which); } @@ -1098,13 +1099,13 @@ connection_dir_client_reached_eof(connection_t *conn) routerinfo_t *me = router_get_my_routerinfo(); if (me && router_digest_is_me(conn->identity_digest) && - me->addr == conn->addr && - me->dir_port == conn->port) + me->addr == conn->_base.addr && + me->dir_port == conn->_base.port) router_dirport_found_reachable(); } } - if (conn->purpose == DIR_PURPOSE_UPLOAD_DIR) { + if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) { switch (status_code) { case 200: log_info(LD_GENERAL,"eof (status 200) after uploading server " @@ -1113,7 +1114,7 @@ connection_dir_client_reached_eof(connection_t *conn) case 400: log_warn(LD_GENERAL,"http status 400 (%s) response from " "dirserver '%s:%d'. Please correct.", - escaped(reason), conn->address, conn->port); + escaped(reason), conn->_base.address, conn->_base.port); break; case 403: 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 " "fingerprint? Are you using the right key? Are you using a " "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; default: log_warn(LD_GENERAL, "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; } /* return 0 in all cases, since we don't want to mark any * 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 " "(%s))", (int)body_len, status_code, escaped(reason)); @@ -1145,7 +1146,7 @@ connection_dir_client_reached_eof(connection_t *conn) * cleans it up */ } else { /* 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); } break; @@ -1161,12 +1162,12 @@ connection_dir_client_reached_eof(connection_t *conn) default: log_warn(LD_REND,"http status %d (%s) response unexpected (server " "'%s:%d').", - status_code, escaped(reason), conn->address, conn->port); + status_code, escaped(reason), conn->_base.address, conn->_base.port); break; } } - if (conn->purpose == DIR_PURPOSE_UPLOAD_RENDDESC) { + if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) { switch (status_code) { case 200: log_info(LD_REND, @@ -1176,12 +1177,12 @@ connection_dir_client_reached_eof(connection_t *conn) case 400: log_warn(LD_REND,"http status 400 (%s) response from dirserver " "'%s:%d'. Malformed rendezvous descriptor?", - escaped(reason), conn->address, conn->port); + escaped(reason), conn->_base.address, conn->_base.port); break; default: log_warn(LD_REND,"http status %d (%s) response unexpected (server " "'%s:%d').", - status_code, escaped(reason), conn->address, conn->port); + status_code, escaped(reason), conn->_base.address, conn->_base.port); break; } } @@ -1191,20 +1192,20 @@ connection_dir_client_reached_eof(connection_t *conn) /** Called when a directory connection reaches EOF */ int -connection_dir_reached_eof(connection_t *conn) +connection_dir_reached_eof(dir_connection_t *conn) { 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."); - connection_close_immediate(conn); /* error: give up on flushing */ - connection_mark_for_close(conn); + connection_close_immediate(TO_CONN(conn)); /* error: give up on flushing */ + connection_mark_for_close(TO_CONN(conn)); return -1; } retval = connection_dir_client_reached_eof(conn); if (retval == 0) /* success */ - conn->state = DIR_CONN_STATE_CLIENT_FINISHED; - connection_mark_for_close(conn); + conn->_base.state = DIR_CONN_STATE_CLIENT_FINISHED; + connection_mark_for_close(TO_CONN(conn)); return retval; } @@ -1212,10 +1213,10 @@ connection_dir_reached_eof(connection_t *conn) * directory servers and connections <em>at</em> directory servers.) */ int -connection_dir_process_inbuf(connection_t *conn) +connection_dir_process_inbuf(dir_connection_t *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 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 (conn->state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) { + if (conn->_base.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) { if (directory_handle_command(conn) < 0) { - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); return -1; } 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 */ - if (!conn->inbuf_reached_eof) + if (!conn->_base.inbuf_reached_eof) log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf."); 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>. */ 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) { 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."); return; } - connection_write_to_buf(buf, strlen(buf), conn); + connection_write_to_buf(buf, strlen(buf), TO_CONN(conn)); } /** DOCDOC */ 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) { 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), "HTTP/1.0 200 OK\r\nDate: %s\r\nContent-Type: %s\r\n" X_ADDRESS_HEADER "%s\r\n", - date, type, conn->address); + date, type, conn->_base.address); cp += strlen(tmp); if (encoding) { 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); else 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 @@ -1308,7 +1309,7 @@ already_fetching_directory(int purpose) if (conn->type == CONN_TYPE_DIR && conn->purpose == purpose && !conn->marked_for_close && - !router_digest_is_me(conn->identity_digest)) + !router_digest_is_me(TO_DIR_CONN(conn)->identity_digest)) return 1; } return 0; @@ -1389,7 +1390,7 @@ directory_dump_request_log(void) * conn-\>outbuf. If the request is unrecognized, send a 400. * Always return 0. */ 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) { size_t dlen; @@ -1401,7 +1402,7 @@ directory_handle_command_get(connection_t *conn, char *headers, 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) { 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, deflated?"application/octet-stream":"text/plain", deflated?"deflate":"identity"); - connection_write_to_buf(cp, strlen(cp), conn); + connection_write_to_buf(cp, strlen(cp), TO_CONN(conn)); return 0; } @@ -1583,7 +1584,7 @@ directory_handle_command_get(connection_t *conn, char *headers, NULL); note_request("/tor/rendezvous?/", desc_len); /* 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; case 0: /* well-formed but not present */ 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(); size_t len = strlen(bytes); 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(url); return 0; @@ -1611,12 +1612,12 @@ directory_handle_command_get(connection_t *conn, char *headers, char robots[] = "User-agent: *\r\nDisallow: /\r\n"; size_t len = strlen(robots); 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); 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())) { /* XXX until weasel rewrites his scripts XXXX012 */ 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"); - connection_write_to_buf(new_directory, dlen, conn); + connection_write_to_buf(new_directory, dlen, TO_CONN(conn)); tor_free(new_directory); tor_free(url); 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 * 400. Always return 0. */ 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 *url = NULL; 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())) { /* 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: log_notice(LD_DIRSERV,"Rejected router descriptor from %s.", - conn->address); + conn->_base.address); /* malformed descriptor, or something wrong */ write_http_status_line(conn, 400, msg); break; @@ -1703,7 +1704,7 @@ directory_handle_command_post(connection_t *conn, char *headers, // char tmp[1024*2+1]; log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV, "Rejected rend descriptor (length %d) from %s.", - (int)body_len, conn->address); + (int)body_len, conn->_base.address); #if 0 if (body_len <= 1024) { 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. */ static int -directory_handle_command(connection_t *conn) +directory_handle_command(dir_connection_t *conn) { char *headers=NULL, *body=NULL; size_t body_len=0; int r; 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, &body, &body_len, MAX_BODY_SIZE, 0)) { case -1: /* overflow */ log_warn(LD_DIRSERV, - "Invalid input from address '%s'. Closing.", conn->address); + "Invalid input from address '%s'. Closing.", conn->_base.address); return -1; case 0: log_debug(LD_DIRSERV,"command not all here yet."); @@ -1753,7 +1754,7 @@ directory_handle_command(connection_t *conn) /* 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); if (!strncasecmp(headers,"GET",3)) @@ -1776,23 +1777,23 @@ directory_handle_command(connection_t *conn) * appropriate. */ int -connection_dir_finished_flushing(connection_t *conn) +connection_dir_finished_flushing(dir_connection_t *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: log_debug(LD_DIR,"client finished sending command."); - conn->state = DIR_CONN_STATE_CLIENT_READING; - connection_stop_writing(conn); + conn->_base.state = DIR_CONN_STATE_CLIENT_READING; + connection_stop_writing(TO_CONN(conn)); return 0; case DIR_CONN_STATE_SERVER_WRITING: log_debug(LD_DIRSERV,"Finished writing server response. Closing."); - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); return 0; 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(); return -1; } @@ -1802,16 +1803,16 @@ connection_dir_finished_flushing(connection_t *conn) /** Connected handler for directory connections: begin sending data to the * server */ int -connection_dir_finished_connecting(connection_t *conn) +connection_dir_finished_connecting(dir_connection_t *conn) { tor_assert(conn); - tor_assert(conn->type == CONN_TYPE_DIR); - tor_assert(conn->state == DIR_CONN_STATE_CONNECTING); + tor_assert(conn->_base.type == CONN_TYPE_DIR); + tor_assert(conn->_base.state == DIR_CONN_STATE_CONNECTING); 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; } diff --git a/src/or/dirserv.c b/src/or/dirserv.c index c17bbafe80..6a07d3ca54 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1825,7 +1825,7 @@ dirserv_test_reachability(int try_all) #define DIRSERV_BUFFER_MIN 16384 static int -connection_dirserv_finish_spooling(connection_t *conn) +connection_dirserv_finish_spooling(dir_connection_t *conn) { if (conn->zlib_state) { connection_write_to_buf_zlib(conn, conn->zlib_state, "", 0, 1); @@ -1838,12 +1838,12 @@ connection_dirserv_finish_spooling(connection_t *conn) /** DOCDOC */ 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; while (smartlist_len(conn->fingerprint_stack) && - buf_datalen(conn->outbuf) < DIRSERV_BUFFER_MIN) { + buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) { const char *body; char *fp = smartlist_pop_last(conn->fingerprint_stack); signed_descriptor_t *sd = NULL; @@ -1875,7 +1875,7 @@ connection_dirserv_add_servers_to_outbuf(connection_t *conn) } else { connection_write_to_buf(body, sd->signed_descriptor_len, - conn); + TO_CONN(conn)); } } @@ -1890,11 +1890,11 @@ connection_dirserv_add_servers_to_outbuf(connection_t *conn) /** DOCDOC */ 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; - bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->outbuf); + bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->_base.outbuf); tor_assert(bytes > 0); tor_assert(conn->cached_dir); if (bytes < 8192) @@ -1909,7 +1909,7 @@ connection_dirserv_add_dir_bytes_to_outbuf(connection_t *conn) bytes, bytes == remaining); } else { connection_write_to_buf(conn->cached_dir->dir_z + conn->cached_dir_offset, - bytes, conn); + bytes, TO_CONN(conn)); } conn->cached_dir_offset += bytes; 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 */ 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) { int uncompressing = (conn->zlib_state != NULL); 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 * SERVER_WRITING. */ 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->state == DIR_CONN_STATE_SERVER_WRITING); + tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING); 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; switch (conn->dir_spool_src) { diff --git a/src/or/dns.c b/src/or/dns.c index 3844741ee0..ee38480aca 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -53,7 +53,7 @@ static time_t last_rotation_time=0; /** Linked list of connections waiting for a DNS answer. */ typedef struct pending_connection_t { - connection_t *conn; + edge_connection_t *conn; struct pending_connection_t *next; } 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_found_answer(const char *address, uint32_t addr, char outcome, uint32_t ttl); -static void send_resolved_cell(connection_t *conn, uint8_t answer_type); -static int assign_to_dnsworker(connection_t *exitconn); +static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type); +static int assign_to_dnsworker(edge_connection_t *exitconn); #ifndef USE_EVENTDNS static int dnsworker_main(void *data); static int spawn_dnsworker(void); @@ -226,7 +226,7 @@ purge_expired_resolves(uint32_t now) { cached_resolve_t *resolve; pending_connection_t *pend; - connection_t *pendconn; + edge_connection_t *pendconn; /* this is fast because the linked list * oldest_cached_resolve is ordered by when they came in. @@ -251,12 +251,12 @@ purge_expired_resolves(uint32_t now) pend = resolve->pending_connections; resolve->pending_connections = pend->next; /* 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; connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT, pendconn->cpath_layer); circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); - connection_free(pendconn); + connection_free(TO_CONN(pendconn)); 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 * be one of RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT) */ 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]; size_t buflen; @@ -286,7 +286,7 @@ send_resolved_cell(connection_t *conn, uint8_t answer_type) { case RESOLVED_TYPE_IPV4: buf[1] = 4; - set_uint32(buf+2, htonl(conn->addr)); + set_uint32(buf+2, htonl(conn->_base.addr)); set_uint32(buf+6, htonl(ttl)); buflen = 10; break; @@ -337,7 +337,7 @@ insert_resolve(cached_resolve_t *r) * dns farm, and return 0. */ int -dns_resolve(connection_t *exitconn) +dns_resolve(edge_connection_t *exitconn) { cached_resolve_t *resolve; cached_resolve_t search; @@ -345,17 +345,17 @@ dns_resolve(connection_t *exitconn) struct in_addr in; circuit_t *circ; uint32_t now = time(NULL); - assert_connection_ok(exitconn, 0); - tor_assert(exitconn->s == -1); + assert_connection_ok(TO_CONN(exitconn), 0); + tor_assert(exitconn->_base.s == -1); 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. */ - if (tor_inet_aton(exitconn->address, &in) != 0) { - exitconn->addr = ntohl(in.s_addr); + if (tor_inet_aton(exitconn->_base.address, &in) != 0) { + exitconn->_base.addr = ntohl(in.s_addr); 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); return 1; } @@ -364,11 +364,11 @@ dns_resolve(connection_t *exitconn) * resolves in the hash table. */ purge_expired_resolves(now); - /* lower-case exitconn->address, so it's in canonical form */ - tor_strlower(exitconn->address); + /* lower-case exitconn->_base.address, so it's in canonical form */ + tor_strlower(exitconn->_base.address); /* 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); if (resolve && resolve->expire > now) { /* already there */ switch (resolve->state) { @@ -381,27 +381,27 @@ dns_resolve(connection_t *exitconn) resolve->pending_connections = pending_connection; log_debug(LD_EXIT,"Connection (fd %d) waiting for pending DNS " "resolve of %s", - exitconn->s, escaped_safe_str(exitconn->address)); - exitconn->state = EXIT_CONN_STATE_RESOLVING; + exitconn->_base.s, escaped_safe_str(exitconn->_base.address)); + exitconn->_base.state = EXIT_CONN_STATE_RESOLVING; return 0; case CACHE_STATE_VALID: - exitconn->addr = resolve->addr; + exitconn->_base.addr = resolve->addr; exitconn->address_ttl = resolve->ttl; log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s", - exitconn->s, escaped_safe_str(exitconn->address)); - if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) + exitconn->_base.s, escaped_safe_str(exitconn->_base.address)); + if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE) send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); return 1; case CACHE_STATE_FAILED: log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s", - exitconn->s, escaped_safe_str(exitconn->address)); - if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) + exitconn->_base.s, escaped_safe_str(exitconn->_base.address)); + if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE) send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); circ = circuit_get_by_edge_conn(exitconn); if (circ) circuit_detach_stream(circ, exitconn); - if (!exitconn->marked_for_close) - connection_free(exitconn); + if (!exitconn->_base.marked_for_close) + connection_free(TO_CONN(exitconn)); return -1; } tor_assert(0); @@ -411,17 +411,17 @@ dns_resolve(connection_t *exitconn) resolve->magic = CACHED_RESOLVE_MAGIC; resolve->state = CACHE_STATE_PENDING; 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 */ pending_connection = tor_malloc_zero(sizeof(pending_connection_t)); pending_connection->conn = exitconn; resolve->pending_connections = pending_connection; - exitconn->state = EXIT_CONN_STATE_RESOLVING; + exitconn->_base.state = EXIT_CONN_STATE_RESOLVING; insert_resolve(resolve); log_debug(LD_EXIT,"Assigning question %s to dnsworker.", - escaped_safe_str(exitconn->address)); + escaped_safe_str(exitconn->_base.address)); assert_cache_ok(); 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. */ void -assert_connection_edge_not_dns_pending(connection_t *conn) +assert_connection_edge_not_dns_pending(edge_connection_t *conn) { pending_connection_t *pend; cached_resolve_t **resolve; @@ -455,9 +455,9 @@ assert_all_pending_dns_resolves_ok(void) for (pend = (*resolve)->pending_connections; pend; pend = pend->next) { - assert_connection_ok(pend->conn, 0); - tor_assert(pend->conn->s == -1); - tor_assert(!connection_in_array(pend->conn)); + assert_connection_ok(TO_CONN(pend->conn), 0); + tor_assert(pend->conn->_base.s == -1); + 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. */ void -connection_dns_remove(connection_t *conn) +connection_dns_remove(edge_connection_t *conn) { pending_connection_t *pend, *victim; cached_resolve_t search; cached_resolve_t *resolve; - tor_assert(conn->type == CONN_TYPE_EXIT); - tor_assert(conn->state == EXIT_CONN_STATE_RESOLVING); + tor_assert(conn->_base.type == CONN_TYPE_EXIT); + 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); if (!resolve) { log_notice(LD_BUG, "Address %s is not pending. Dropping.", - escaped_safe_str(conn->address)); + escaped_safe_str(conn->_base.address)); return; } tor_assert(resolve->pending_connections); - assert_connection_ok(conn,0); + assert_connection_ok(TO_CONN(conn),0); pend = resolve->pending_connections; @@ -493,7 +493,7 @@ connection_dns_remove(connection_t *conn) tor_free(pend); log_debug(LD_EXIT, "First 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; } else { for ( ; pend->next; pend = pend->next) { @@ -503,7 +503,7 @@ connection_dns_remove(connection_t *conn) tor_free(victim); log_debug(LD_EXIT, "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 */ } } @@ -521,7 +521,7 @@ dns_cancel_pending_resolve(char *address) pending_connection_t *pend; cached_resolve_t search; cached_resolve_t *resolve; - connection_t *pendconn; + edge_connection_t *pendconn; circuit_t *circ; strlcpy(search.address, address, sizeof(search.address)); @@ -549,18 +549,18 @@ dns_cancel_pending_resolve(char *address) escaped_safe_str(address)); while (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; - assert_connection_ok(pendconn, 0); - tor_assert(pendconn->s == -1); - if (!pendconn->marked_for_close) { + assert_connection_ok(TO_CONN(pendconn), 0); + tor_assert(pendconn->_base.s == -1); + if (!pendconn->_base.marked_for_close) { connection_edge_end(pendconn, END_STREAM_REASON_RESOURCELIMIT, pendconn->cpath_layer); } circ = circuit_get_by_edge_conn(pendconn); if (circ) circuit_detach_stream(circ, pendconn); - connection_free(pendconn); + connection_free(TO_CONN(pendconn)); resolve->pending_connections = pend->next; tor_free(pend); } @@ -612,7 +612,7 @@ dns_found_answer(const char *address, uint32_t addr, char outcome, pending_connection_t *pend; cached_resolve_t search; cached_resolve_t *resolve; - connection_t *pendconn; + edge_connection_t *pendconn; circuit_t *circ; assert_cache_ok(); @@ -659,16 +659,16 @@ dns_found_answer(const char *address, uint32_t addr, char outcome, while (resolve->pending_connections) { pend = resolve->pending_connections; - assert_connection_ok(pend->conn,time(NULL)); - pend->conn->addr = resolve->addr; + assert_connection_ok(TO_CONN(pend->conn),time(NULL)); + pend->conn->_base.addr = resolve->addr; pend->conn->address_ttl = resolve->ttl; pendconn = pend->conn; /* don't pass complex things to the connection_mark_for_close macro */ if (resolve->state == CACHE_STATE_FAILED) { /* prevent double-remove. */ - pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED; - if (pendconn->purpose == EXIT_PURPOSE_CONNECT) { + pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; + if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) { connection_edge_end(pendconn, END_STREAM_REASON_RESOLVEFAILED, pendconn->cpath_layer); /* 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. */ circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); } - connection_free(pendconn); + connection_free(TO_CONN(pendconn)); } else { - if (pendconn->purpose == EXIT_PURPOSE_CONNECT) { + if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) { /* 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); tor_assert(circ); @@ -698,12 +698,12 @@ dns_found_answer(const char *address, uint32_t addr, char outcome, } else { /* prevent double-remove. This isn't really an accurate state, * 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); circ = circuit_get_by_edge_conn(pendconn); tor_assert(circ); circuit_detach_stream(circ, pendconn); - connection_free(pendconn); + connection_free(TO_CONN(pendconn)); } } 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. */ static int -assign_to_dnsworker(connection_t *exitconn) +assign_to_dnsworker(edge_connection_t *exitconn) { connection_t *dnsconn; unsigned char len; - tor_assert(exitconn->state == EXIT_CONN_STATE_RESOLVING); - assert_connection_ok(exitconn, 0); - tor_assert(exitconn->s == -1); + tor_assert(exitconn->_base.state == EXIT_CONN_STATE_RESOLVING); + assert_connection_ok(TO_CONN(exitconn), 0); + tor_assert(exitconn->_base.s == -1); /* respawn here, to be sure there are enough */ if (spawn_enough_dnsworkers() < 0) { @@ -741,18 +741,18 @@ assign_to_dnsworker(connection_t *exitconn) if (!dnsconn) { 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); goto err; } log_debug(LD_EXIT, "Connection (fd %d) needs to resolve %s; assigning " - "to DNSWorker (fd %d)", exitconn->s, - escaped_safe_str(exitconn->address), dnsconn->s); + "to DNSWorker (fd %d)", exitconn->_base.s, + escaped_safe_str(exitconn->_base.address), dnsconn->s); tor_free(dnsconn->address); - dnsconn->address = tor_strdup(exitconn->address); + dnsconn->address = tor_strdup(exitconn->_base.address); dnsconn->state = DNSWORKER_STATE_BUSY; /* touch the lastwritten timestamp, since that's how we check to * 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; 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; } @@ -1172,11 +1172,11 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses, static int assign_to_dnsworker(connection_t *exitconn) { - char *addr = tor_strdup(exitconn->address); + char *addr = tor_strdup(exitconn->_base.address); int r; log_info(LD_EXIT, "Launching eventdns request for %s", - escaped_safe_str(exitconn->address)); - r = eventdns_resolve(exitconn->address, DNS_QUERY_NO_SEARCH, + escaped_safe_str(exitconn->_base.address)); + r = eventdns_resolve(exitconn->_base.address, DNS_QUERY_NO_SEARCH, eventdns_callback, addr); if (r) { log_warn(LD_EXIT, "eventdns rejected address %s: error %d.", diff --git a/src/or/hibernate.c b/src/or/hibernate.c index 5f1131da71..a1aca0327a 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -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_EXIT))) { if (CONN_IS_EDGE(conn)) - connection_edge_end(conn, END_STREAM_REASON_HIBERNATING, - conn->cpath_layer); + connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING, + TO_EDGE_CONN(conn)->cpath_layer); log_info(LD_NET,"Closing conn type %d", conn->type); 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 connection_mark_for_close(conn); } diff --git a/src/or/main.c b/src/or/main.c index 180b15030f..80516d34e8 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -212,11 +212,11 @@ connection_unlink(connection_t *conn, int remove) } smartlist_remove(closeable_connection_lst, conn); 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 && - !tor_digest_is_zero(conn->identity_digest)) { - connection_or_remove_from_identity_map(conn); + if (conn->type == CONN_TYPE_OR) { + if (!tor_digest_is_zero(TO_OR_CONN(conn)->identity_digest)) + connection_or_remove_from_identity_map(TO_OR_CONN(conn)); } connection_free(conn); } @@ -413,7 +413,8 @@ conn_read_callback(int fd, short event, void *_conn) tor_fragile_assert(); #endif 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); } } @@ -443,7 +444,8 @@ conn_write_callback(int fd, short events, void *_conn) "Bug: unhandled error on write for %s connection (fd %d); removing", conn_type_to_string(conn->type), conn->s); 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? */ connection_mark_for_close(conn); } @@ -489,7 +491,7 @@ conn_close_if_marked(int i) conn->marked_for_close_file, conn->marked_for_close); if (connection_speaks_cells(conn)) { 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); } else 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, AP_CONN_STATE_CIRCUIT_WAIT))) { + edge_connection_t *edge_conn = TO_EDGE_CONN(conn); log_notice(LD_NET, "Is your network connection down? " "Failing connection to '%s:%d'.", - safe_str(conn->socks_request->address), - conn->socks_request->port); - connection_mark_unattached_ap(conn, END_STREAM_REASON_NET_UNREACHABLE); + safe_str(edge_conn->socks_request->address), + edge_conn->socks_request->port); + 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; connection_t *conn = connection_array[i]; or_options_t *options = get_options(); + or_connection_t *or_conn; if (conn->outbuf && !buf_datalen(conn->outbuf)) conn->timestamp_lastempty = now; @@ -602,7 +606,7 @@ run_connection_housekeeping(int i, time_t now) buf_datalen(conn->inbuf)>=1024) { log_info(LD_DIR,"Trying to extract information from wedged server desc " "download."); - connection_dir_reached_eof(conn); + connection_dir_reached_eof(TO_DIR_CONN(conn)); } else { connection_mark_for_close(conn); } @@ -612,17 +616,19 @@ run_connection_housekeeping(int i, time_t now) if (!connection_speaks_cells(conn)) 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) { log_info(LD_OR, "Marking OR conn to %s:%d obsolete (fd %d, %d secs old).", conn->address, conn->port, conn->s, (int)(now - conn->timestamp_created)); - conn->is_obsolete = 1; + conn->or_is_obsolete = 1; } else { - connection_t *best = - connection_or_get_by_identity_digest(conn->identity_digest); - if (best && best != conn && + or_connection_t *best = + connection_or_get_by_identity_digest(or_conn->identity_digest); + if (best && best != or_conn && (conn->state == OR_CONN_STATE_OPEN || now > conn->timestamp_created + TLS_HANDSHAKE_TIMEOUT)) { /* 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).", conn->address, conn->port, conn->s, (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 */ log_info(LD_OR, "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); conn->hold_open_until_flushed = 1; 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 the connection or send a keepalive, depending. */ 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)) { log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).", conn->s,conn->address, conn->port); connection_mark_for_close(conn); 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)) { log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " "[Hibernating or exiting].", conn->s,conn->address, conn->port); connection_mark_for_close(conn); 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_is_clique_mode(router))) { 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); memset(&cell,0,sizeof(cell_t)); cell.command = CELL_PADDING; - connection_or_write_cell_to_buf(&cell, conn); + connection_or_write_cell_to_buf(&cell, or_conn); } } } diff --git a/src/or/or.h b/src/or/or.h index 8ce5d8692d..0db44e5898 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -576,7 +576,11 @@ typedef struct { typedef struct buf_t buf_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 * data. @@ -609,14 +613,15 @@ struct connection_t { unsigned hold_open_until_flushed:1; /**< Despite this connection's being * marked for close, do we flush 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(). */ /** For control connections only. If set, we send extended info with control * events as appropriate. */ unsigned int control_events_are_extended:1; /** 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 poll_index; /* XXXX rename. */ @@ -648,22 +653,23 @@ struct connection_t { * we marked for close? */ char *address; /**< FQDN (or IP) of the guy on the other end. * 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 * the other side's signing key. */ 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.) */ /* bandwidth* and receiver_bucket only used by ORs in OPEN state: */ @@ -677,16 +683,19 @@ struct connection_t { * we use? */ int n_circuits; /**< How many circuits use this connection as p_conn or * 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. */ uint16_t next_circ_id; /**< Which circ_id do we try to use next on * this connection? This is always in the * 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; - struct connection_t *next_stream; /**< Points to the next stream at this - * edge, if any (Edge only). */ + struct edge_connection_t *next_stream; /**< Points to the next stream at this + * edge, if any (Edge only). */ struct crypt_path_t *cpath_layer; /**< A pointer to which node in the circ * this conn exits at. (Edge only.) */ 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 * 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 */ char *requested_resource; /**< Which 'resource' did we ask the directory * for? */ @@ -708,31 +747,55 @@ struct connection_t { off_t cached_dir_offset; tor_zlib_state_t *zlib_state; -/* Used only by AP connections */ - socks_request_t *socks_request; /**< SOCKS structure describing request (AP - * 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) */ - /** 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; + char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for + * the directory server's signing key. */ +} dir_connection_t; + +typedef struct control_connection_t { + connection_t _base; /* Used only by control connections */ uint32_t event_mask; uint32_t incoming_cmd_len; uint32_t incoming_cmd_cur_len; 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 */ 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 { ADDR_POLICY_ACCEPT=1, @@ -1072,7 +1135,7 @@ typedef struct circuit_t { * ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */ /** The OR connection that is next in this circuit. */ - connection_t *n_conn; + or_connection_t *n_conn; /** The identity hash of n_conn. */ char n_conn_id_digest[DIGEST_LEN]; /** The circuit_id used in the next (forward) hop of this circuit. */ @@ -1121,7 +1184,7 @@ typedef struct origin_circuit_t { circuit_t _base; /** 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 * 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. */ circid_t p_circ_id; /** 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. */ - connection_t *n_streams; + edge_connection_t *n_streams; /** Linked list of Exit streams associated with this circuit that are * still being resolved. */ - connection_t *resolving_streams; + edge_connection_t *resolving_streams; /** The cipher used by intermediate hops for cells heading toward the * OP. */ 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) { 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); extern INLINE origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x) { tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC); - return (origin_circuit_t*) - (((char*)x) - STRUCT_OFFSET(origin_circuit_t, _base)); + //return (origin_circuit_t*) + // (((char*)x) - STRUCT_OFFSET(origin_circuit_t, _base)); + return DOWNCAST(circuit_t, origin_circuit_t, x); } #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 internal); 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 circuit_send_next_onion_skin(origin_circuit_t *circ); 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); void circuit_dump_by_conn(connection_t *conn, int severity); 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, - connection_t *conn); + or_connection_t *conn); void circuit_set_state(circuit_t *circ, int state); void circuit_close_all_marked(void); origin_circuit_t *origin_circuit_new(void); -or_circuit_t *or_circuit_new(uint16_t p_circ_id, connection_t *p_conn); -circuit_t *circuit_get_by_circid_orconn(uint16_t circ_id, connection_t *conn); -int circuit_id_used_on_conn(uint16_t circ_id, connection_t *conn); -circuit_t *circuit_get_by_edge_conn(connection_t *conn); -void circuit_unlink_all_from_or_conn(connection_t *conn, int reason); +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, + or_connection_t *conn); +int circuit_id_used_on_conn(uint16_t circ_id, or_connection_t *conn); +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); origin_circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose); @@ -1631,10 +1697,10 @@ void circuit_free_all(void); void circuit_expire_building(time_t now); 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); 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_has_opened(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 is_internal); 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); -int connection_ap_handshake_attach_circuit(connection_t *conn); +int connection_ap_handshake_attach_circuit(edge_connection_t *conn); /********************************* 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_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_outbuf_too_full(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, 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, const char *data, size_t data_len, 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); 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); 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 *************************/ #define connection_mark_unattached_ap(conn, endreason) \ _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 connection_edge_reached_eof(connection_t *conn); -int connection_edge_process_inbuf(connection_t *conn, int package_partial); -int connection_edge_destroy(uint16_t circ_id, connection_t *conn); -int connection_edge_end(connection_t *conn, char reason, +int connection_edge_reached_eof(edge_connection_t *conn); +int connection_edge_process_inbuf(edge_connection_t *conn, int package_partial); +int connection_edge_destroy(uint16_t circ_id, edge_connection_t *conn); +int connection_edge_end(edge_connection_t *conn, char reason, crypt_path_t *cpath_layer); -int connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer); -int connection_edge_finished_flushing(connection_t *conn); -int connection_edge_finished_connecting(connection_t *conn); +int connection_edge_end_errno(edge_connection_t *conn, crypt_path_t *cpath_layer); +int connection_edge_finished_flushing(edge_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); -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); 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, 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, size_t answer_len, 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_resolve(cell_t *cell, or_circuit_t *circ); -void connection_exit_connect(connection_t *conn); -int connection_edge_is_rendezvous_stream(connection_t *conn); -int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit); +void connection_exit_connect(edge_connection_t *conn); +int connection_edge_is_rendezvous_stream(edge_connection_t *conn); +int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit); void connection_ap_expire_beginning(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_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); void addressmap_get_mappings(smartlist_t *sl, time_t min_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); void set_exit_redirects(smartlist_t *lst); @@ -1831,23 +1897,23 @@ hostname_type_t parse_extended_hostname(char *address); /********************************* 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); -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_process_inbuf(connection_t *conn); -int connection_or_finished_flushing(connection_t *conn); -int connection_or_finished_connecting(connection_t *conn); +int connection_or_reached_eof(or_connection_t *conn); +int connection_or_process_inbuf(or_connection_t *conn); +int connection_or_finished_flushing(or_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); -int connection_tls_start_handshake(connection_t *conn, int receiving); -int connection_tls_continue_handshake(connection_t *conn); +int connection_tls_start_handshake(or_connection_t *conn, int receiving); +int connection_tls_continue_handshake(or_connection_t *conn); -void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn); -int connection_or_send_destroy(uint16_t circ_id, 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, or_connection_t *conn, int reason); /********************************* control.c ***************************/ @@ -1906,14 +1972,14 @@ void control_adjust_event_log_severity(void); #define LOG_FN_CONN(conn, args) \ CONN_LOG_PROTECT(conn, log_fn args) -int connection_control_finished_flushing(connection_t *conn); -int connection_control_reached_eof(connection_t *conn); -int connection_control_process_inbuf(connection_t *conn); +int connection_control_finished_flushing(control_connection_t *conn); +int connection_control_reached_eof(control_connection_t *conn); +int connection_control_process_inbuf(control_connection_t *conn); int control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t e); -int control_event_stream_status(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_stream_status(edge_connection_t *conn, stream_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); void control_event_logmsg(int severity, unsigned int domain, const char *msg); 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 *compression, char **response); -int connection_dir_reached_eof(connection_t *conn); -int connection_dir_process_inbuf(connection_t *conn); -int connection_dir_finished_flushing(connection_t *conn); -int connection_dir_finished_connecting(connection_t *conn); -void connection_dir_request_failed(connection_t *conn); +int connection_dir_reached_eof(dir_connection_t *conn); +int connection_dir_process_inbuf(dir_connection_t *conn); +int connection_dir_finished_flushing(dir_connection_t *conn); +int connection_dir_finished_connecting(dir_connection_t *conn); +void connection_dir_request_failed(dir_connection_t *conn); int dir_split_resource_into_fingerprints(const char *resource, smartlist_t *fp_out, int *compresseed_out, int decode_hex, int sort_uniq); @@ -1971,7 +2037,7 @@ char *directory_dump_request_log(void); /********************************* 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_parse_fingerprint_file(const char *fname); 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_process_inbuf(connection_t *conn); void dnsworkers_rotate(void); -void connection_dns_remove(connection_t *conn); -void assert_connection_edge_not_dns_pending(connection_t *conn); +void connection_dns_remove(edge_connection_t *conn); +void assert_connection_edge_not_dns_pending(edge_connection_t *conn); void assert_all_pending_dns_resolves_ok(void); void dns_cancel_pending_resolve(char *question); -int dns_resolve(connection_t *exitconn); +int dns_resolve(edge_connection_t *exitconn); /********************************* 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_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, size_t payload_len, crypt_path_t *cpath_layer); -int connection_edge_package_raw_inbuf(connection_t *conn, int package_partial); -void connection_edge_consider_sending_sendme(connection_t *conn); +int connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial); +void connection_edge_consider_sending_sendme(edge_connection_t *conn); socks5_reply_status_t connection_edge_end_reason_socks5_response(int reason); 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, size_t request_len); 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); void rend_service_dump_stats(int severity); 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_ipaddress_changed(time_t now); 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); const char *router_get_my_descriptor(void); int router_digest_is_me(const char *digest); diff --git a/src/or/relay.c b/src/or/relay.c index 997035fe22..35154f1af2 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -16,19 +16,19 @@ const char relay_c_id[] = static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction, 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); static int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, - connection_t *conn, + edge_connection_t *conn, crypt_path_t *layer_hint); static void circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint); static void circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint); static int -circuit_resume_edge_reading_helper(connection_t *conn, +circuit_resume_edge_reading_helper(edge_connection_t *conn, circuit_t *circ, crypt_path_t *layer_hint); static int @@ -144,7 +144,7 @@ relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in, int 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; char recognized=0; int reason; @@ -162,7 +162,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) } 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) { ++stats_n_relay_cells_delivered; 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. */ if (cell_direction == CELL_DIRECTION_OUT) { cell->circ_id = circ->n_circ_id; /* switch it */ - conn = circ->n_conn; + or_conn = circ->n_conn; } else if (! CIRCUIT_IS_ORIGIN(circ)) { 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 { // XXXX NM WARN. return 0; } - if (!conn) { + if (!or_conn) { // XXXX Can this splice stuff be done more cleanly? if (! CIRCUIT_IS_ORIGIN(circ) && 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."); ++stats_n_relay_cells_relayed; - connection_or_write_cell_to_buf(cell, conn); + connection_or_write_cell_to_buf(cell, or_conn); return 0; } @@ -323,7 +323,7 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, 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) { 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 * 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) { - connection_t *tmpconn; + edge_connection_t *tmpconn; relay_header_t rh; 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)) { for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn; 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); return tmpconn; } @@ -395,7 +396,7 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction) } else { for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn; 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); if (cell_direction == CELL_DIRECTION_OUT || 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; 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); return tmpconn; } @@ -452,7 +453,7 @@ relay_header_unpack(relay_header_t *dest, const char *src) * return -1. Else return 0. */ 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, 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; /* 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, "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; } if (!circ) { tor_assert(fromconn); - if (fromconn->type == CONN_TYPE_AP) { + if (fromconn->_base.type == CONN_TYPE_AP) { log_info(LD_APP,"no circ. Closing conn."); connection_mark_unattached_ap(fromconn, END_STREAM_REASON_INTERNAL); } else { log_info(LD_EXIT,"no circ. Closing conn."); - fromconn->has_sent_end = 1; /* no circ to send to */ - connection_mark_for_close(fromconn); + fromconn->_base.edge_has_sent_end = 1; /* no circ to send to */ + connection_mark_for_close(TO_CONN(fromconn)); } return -1; } @@ -665,7 +666,7 @@ edge_reason_is_retriable(int reason) static int connection_edge_process_end_not_open( 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; routerinfo_t *exitrouter; @@ -673,7 +674,7 @@ connection_edge_process_end_not_open( (void) layer_hint; /* unused */ 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.", safe_str(conn->socks_request->address), connection_edge_end_reason_str(reason)); @@ -775,12 +776,12 @@ connection_edge_process_end_not_open( log_info(LD_APP, "Edge got end (%s) before we're connected. Marking for close.", 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); connection_mark_unattached_ap(conn, reason); } else { - conn->has_sent_end = 1; /* we just got an 'end', don't need to send one */ - connection_mark_for_close(conn); + conn->_base.edge_has_sent_end = 1; /* we just got an 'end', don't need to send one */ + connection_mark_for_close(TO_CONN(conn)); } return 0; } @@ -795,7 +796,7 @@ connection_edge_process_end_not_open( static int connection_edge_process_relay_cell_not_open( 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 (CIRCUIT_IS_ORIGIN(circ)) @@ -806,17 +807,17 @@ connection_edge_process_relay_cell_not_open( 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)); - 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. " "Dropping."); return 0; } // 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.", - (int)(time(NULL) - conn->timestamp_lastread)); + (int)(time(NULL) - conn->_base.timestamp_lastread)); if (rh->length >= 4) { uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE)); int ttl; @@ -840,15 +841,15 @@ connection_edge_process_relay_cell_not_open( /* handle anything that might have queued */ if (connection_edge_package_raw_inbuf(conn, 1) < 0) { /* (We already sent an end cell if possible) */ - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); 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 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. " "Dropping."); return 0; @@ -877,8 +878,8 @@ connection_edge_process_relay_cell_not_open( log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Got an unexpected relay command %d, in state %d (%s). Dropping.", - rh->command, conn->state, - conn_state_to_string(conn->type, conn->state)); + rh->command, conn->_base.state, + conn_state_to_string(conn->_base.type, conn->_base.state)); return 0; /* for forward compatibility, don't kill the circuit */ // connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL, // conn->cpath_layer); @@ -897,7 +898,7 @@ connection_edge_process_relay_cell_not_open( */ static int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, - connection_t *conn, + edge_connection_t *conn, crypt_path_t *layer_hint) { 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 * 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( &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."); connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL, conn->cpath_layer); - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); return -END_CIRC_REASON_TORPROTOCOL; } 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; connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE, - rh.length, conn); + rh.length, TO_CONN(conn)); connection_edge_consider_sending_sendme(conn); return 0; 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? */ 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 ? *(char *)(cell->payload+RELAY_HEADER_SIZE) : -1), conn->stream_id); @@ -991,12 +992,12 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, log_warn(LD_BUG, "Bug: open stream hasn't sent socks answer yet? Closing."); /* We just *got* an end; no reason to send one. */ - conn->has_sent_end = 1; - if (!conn->marked_for_close) { + conn->_base.edge_has_sent_end = 1; + if (!conn->_base.marked_for_close) { /* only mark it if not already marked. it's possible to * get the 'end' right around when the client hangs up on us. */ - connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; + connection_mark_for_close(TO_CONN(conn)); + conn->_base.hold_open_until_flushed = 1; } return 0; case RELAY_COMMAND_EXTEND: @@ -1076,11 +1077,11 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, conn->package_window += STREAMWINDOW_INCREMENT; log_debug(domain,"stream-level sendme, packagewindow now %d.", conn->package_window); - connection_start_reading(conn); + connection_start_reading(TO_CONN(conn)); /* handle whatever might still be on the inbuf */ if (connection_edge_package_raw_inbuf(conn, 1) < 0) { /* (We already sent an end cell if possible) */ - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); return 0; } return 0; @@ -1139,7 +1140,7 @@ uint64_t stats_n_data_bytes_received = 0; * be marked for close, else return 0. */ 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; 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; tor_assert(conn); - tor_assert(!connection_speaks_cells(conn)); - if (conn->marked_for_close) { + + if (conn->_base.marked_for_close) { log_warn(LD_BUG, "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; } @@ -1169,11 +1170,11 @@ repeat_connection_edge_package_raw_inbuf: if (conn->package_window <= 0) { log_info(domain,"called with package_window %d. Skipping.", conn->package_window); - connection_stop_reading(conn); + connection_stop_reading(TO_CONN(conn)); return 0; } - amount_to_process = buf_datalen(conn->inbuf); + amount_to_process = buf_datalen(conn->_base.inbuf); if (!amount_to_process) return 0; @@ -1189,10 +1190,10 @@ repeat_connection_edge_package_raw_inbuf: stats_n_data_bytes_packaged += length; 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, - (int)length, (int)buf_datalen(conn->inbuf)); + log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->_base.s, + (int)length, (int)buf_datalen(conn->_base.inbuf)); if (connection_edge_send_command(conn, circ, RELAY_COMMAND_DATA, 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? */ - connection_stop_reading(conn); + connection_stop_reading(TO_CONN(conn)); log_debug(domain,"conn->package_window reached 0."); circuit_consider_stop_edge_reading(circ, conn->cpath_layer); 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. */ void -connection_edge_consider_sending_sendme(connection_t *conn) +connection_edge_consider_sending_sendme(edge_connection_t *conn) { circuit_t *circ; - if (connection_outbuf_too_full(conn)) + if (connection_outbuf_too_full(TO_CONN(conn))) return; 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) { log_debug(conn->cpath_layer?LD_APP:LD_EXIT, "Outbuf %d, Queueing stream sendme.", - (int)conn->outbuf_flushlen); + (int)conn->_base.outbuf_flushlen); conn->deliver_window += STREAMWINDOW_INCREMENT; if (connection_edge_send_command(conn, circ, RELAY_COMMAND_SENDME, 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. */ static int -circuit_resume_edge_reading_helper(connection_t *conn, +circuit_resume_edge_reading_helper(edge_connection_t *conn, circuit_t *circ, crypt_path_t *layer_hint) { for ( ; conn; conn=conn->next_stream) { - if (conn->marked_for_close) + if (conn->_base.marked_for_close) continue; if ((!layer_hint && conn->package_window > 0) || (layer_hint && conn->package_window > 0 && conn->cpath_layer == layer_hint)) { - connection_start_reading(conn); + connection_start_reading(TO_CONN(conn)); /* handle whatever might still be on the inbuf */ if (connection_edge_package_raw_inbuf(conn, 1)<0) { /* (We already sent an end cell if possible) */ - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); continue; } @@ -1315,7 +1316,7 @@ circuit_resume_edge_reading_helper(connection_t *conn, static int 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; 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) { log_debug(domain,"yes, not-at-origin. stopped."); for (conn = or_circ->n_streams; conn; conn=conn->next_stream) - connection_stop_reading(conn); + connection_stop_reading(TO_CONN(conn)); return 1; } 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; conn=conn->next_stream) if (conn->cpath_layer == layer_hint) - connection_stop_reading(conn); + connection_stop_reading(TO_CONN(conn)); return 1; } return 0; diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 3445bd5c88..00471bbc23 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -430,7 +430,7 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request, void rend_client_desc_here(const char *query) { - connection_t *conn; + edge_connection_t *conn; rend_cache_entry_t *entry; time_t now = time(NULL); int i, n_conns; @@ -439,25 +439,26 @@ rend_client_desc_here(const char *query) get_connection_array(&carray, &n_conns); for (i = 0; i < n_conns; ++i) { - conn = carray[i]; - if (conn->type != CONN_TYPE_AP || - conn->state != AP_CONN_STATE_RENDDESC_WAIT || - conn->marked_for_close || - rend_cmp_service_ids(query, conn->rend_query)) + if (carray[i]->type != CONN_TYPE_AP || + carray[i]->state != AP_CONN_STATE_RENDDESC_WAIT || + carray[i]->marked_for_close) + continue; + conn = TO_EDGE_CONN(carray[i]); + if (rend_cmp_service_ids(query, conn->rend_query)) continue; - assert_connection_ok(conn, now); + assert_connection_ok(TO_CONN(conn), now); if (rend_cache_lookup_entry(conn->rend_query, -1, &entry) == 1 && entry->parsed->n_intro_points > 0) { /* either this fetch worked, or it failed but there was a * valid entry from before which we should reuse */ 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 * connecting to the hidden service. */ - conn->timestamp_created = now; - conn->timestamp_lastread = now; - conn->timestamp_lastwritten = now; + conn->_base.timestamp_created = now; + conn->_base.timestamp_lastread = now; + conn->_base.timestamp_lastwritten = now; if (connection_ap_handshake_attach_circuit(conn) < 0) { /* it will never work */ diff --git a/src/or/rendservice.c b/src/or/rendservice.c index d0bb33d138..0cda1d95c0 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -1121,7 +1121,7 @@ rend_service_dump_stats(int severity) * or 0 for success. */ int -rend_service_set_connection_addr_port(connection_t *conn, +rend_service_set_connection_addr_port(edge_connection_t *conn, origin_circuit_t *circ) { 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) { p = smartlist_get(service->ports, i); - if (conn->port == p->virtual_port) { - conn->addr = p->real_addr; - conn->port = p->real_port; + if (conn->_base.port == p->virtual_port) { + conn->_base.addr = p->real_addr; + conn->_base.port = p->real_port; return 0; } } log_info(LD_REND, "No virtual port mapping exists for port %d on service %s", - conn->port,serviceid); + conn->_base.port,serviceid); return -1; } diff --git a/src/or/router.c b/src/or/router.c index 3ae6d1a24a..63262c483c 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -650,16 +650,16 @@ router_upload_dir_desc_to_dirservers(int force) * conn. Return 0 if we accept; non-0 if we reject. */ int -router_compare_to_my_exit_policy(connection_t *conn) +router_compare_to_my_exit_policy(edge_connection_t *conn) { tor_assert(desc_routerinfo); /* make sure it's resolved to something. this way we can't get a 'maybe' below. */ - if (!conn->addr) + if (!conn->_base.addr) 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; } diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 46cb160918..5eb804477d 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -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 * make new ones with the new key. */ - connection_t *conn; + or_connection_t *conn; while ((conn = connection_or_get_by_identity_digest( old_router->cache_info.identity_digest))) { log_info(LD_DIR,"Closing conn to router '%s'; there is now a named " "router with that name.", old_router->nickname); - connection_mark_for_close(conn); + connection_mark_for_close(TO_CONN(conn)); } routerlist_remove(routerlist, old_router, i--, 0); } else if (old_router->is_named) { @@ -3317,8 +3317,9 @@ list_pending_descriptor_downloads(digestmap_t *result) if (conn->type == CONN_TYPE_DIR && conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC && !conn->marked_for_close) { - if (!strcmpstart(conn->requested_resource, prefix)) - dir_split_resource_into_fingerprints(conn->requested_resource+p_len, + dir_connection_t *dir_conn = TO_DIR_CONN(conn); + if (!strcmpstart(dir_conn->requested_resource, prefix)) + dir_split_resource_into_fingerprints(dir_conn->requested_resource+p_len, tmp, NULL, 1, 0); } } |