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

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


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

View File

@ -60,14 +60,13 @@ static void entry_guards_changed(void);
* Return it, or 0 if can't get a unique circ_id.
*/
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]);

View File

@ -33,7 +33,7 @@ static void circuit_free_cpath_node(crypt_path_t *victim);
* very important here, since we need to do it every time a cell arrives.) */
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);

View File

@ -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.",

View File

@ -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);

View File

@ -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);
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
}
if (conn->zlib_state)
tor_zlib_free(conn->zlib_state);
if (conn->fingerprint_stack) {
SMARTLIST_FOREACH(conn->fingerprint_stack, char *, cp, tor_free(cp));
smartlist_free(conn->fingerprint_stack);
}
if (conn->cached_dir)
cached_dir_decref(conn->cached_dir);
memset(conn, 0xAA, sizeof(connection_t)); /* poison memory */
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);

View File

@ -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);

View File

@ -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(TO_CONN(conn),0);
assert_connection_ok(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;

View File

@ -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;

View File

@ -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

View File

@ -38,16 +38,16 @@ directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
const char *payload, size_t payload_len);
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;
}

View File

@ -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) {

View File

@ -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.",

View File

@ -786,11 +786,12 @@ hibernate_go_dormant(time_t now)
(conn = connection_get_by_type(CONN_TYPE_AP)) ||
(conn = connection_get_by_type(CONN_TYPE_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);
}

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
assert_connection_ok(conn, now);
conn = TO_EDGE_CONN(carray[i]);
if (rend_cmp_service_ids(query, conn->rend_query))
continue;
assert_connection_ok(TO_CONN(conn), now);
if (rend_cache_lookup_entry(conn->rend_query, -1, &entry) == 1 &&
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 */

View File

@ -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;
}

View File

@ -650,16 +650,16 @@ router_upload_dir_desc_to_dirservers(int force)
* conn. Return 0 if we accept; non-0 if we reject.
*/
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;
}

View File

@ -1705,13 +1705,13 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
/* mark-for-close connections using the old key, so we can
* 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);
}
}