mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
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:
parent
18771e851f
commit
4ff4577beb
@ -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]);
|
||||
|
@ -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);
|
||||
|
@ -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.",
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
322
src/or/control.c
322
src/or/control.c
@ -131,57 +131,57 @@ static int disable_log_messages = 0;
|
||||
static int authentication_cookie_is_set = 0;
|
||||
static char authentication_cookie[AUTHENTICATION_COOKIE_LEN];
|
||||
|
||||
static void connection_printf_to_buf(connection_t *conn,
|
||||
static void connection_printf_to_buf(control_connection_t *conn,
|
||||
const char *format, ...)
|
||||
CHECK_PRINTF(2,3);
|
||||
/*static*/ size_t write_escaped_data(const char *data, size_t len,
|
||||
int translate_newlines, char **out);
|
||||
/*static*/ size_t read_escaped_data(const char *data, size_t len,
|
||||
int translate_newlines, char **out);
|
||||
static void send_control0_message(connection_t *conn, uint16_t type,
|
||||
static void send_control0_message(control_connection_t *conn, uint16_t type,
|
||||
uint32_t len, const char *body);
|
||||
static void send_control_done(connection_t *conn);
|
||||
static void send_control_done2(connection_t *conn, const char *msg,
|
||||
static void send_control_done(control_connection_t *conn);
|
||||
static void send_control_done2(control_connection_t *conn, const char *msg,
|
||||
size_t len);
|
||||
static void send_control0_error(connection_t *conn, uint16_t error,
|
||||
static void send_control0_error(control_connection_t *conn, uint16_t error,
|
||||
const char *message);
|
||||
static void send_control0_event(uint16_t event, uint32_t len,
|
||||
const char *body);
|
||||
static void send_control1_event(uint16_t event, const char *format, ...)
|
||||
CHECK_PRINTF(2,3);
|
||||
static int handle_control_setconf(connection_t *conn, uint32_t len,
|
||||
static int handle_control_setconf(control_connection_t *conn, uint32_t len,
|
||||
char *body);
|
||||
static int handle_control_resetconf(connection_t *conn, uint32_t len,
|
||||
static int handle_control_resetconf(control_connection_t *conn, uint32_t len,
|
||||
char *body);
|
||||
static int handle_control_getconf(connection_t *conn, uint32_t len,
|
||||
static int handle_control_getconf(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_setevents(connection_t *conn, uint32_t len,
|
||||
static int handle_control_setevents(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_authenticate(connection_t *conn, uint32_t len,
|
||||
static int handle_control_authenticate(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_saveconf(connection_t *conn, uint32_t len,
|
||||
static int handle_control_saveconf(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_signal(connection_t *conn, uint32_t len,
|
||||
static int handle_control_signal(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_mapaddress(connection_t *conn, uint32_t len,
|
||||
static int handle_control_mapaddress(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_getinfo(connection_t *conn, uint32_t len,
|
||||
static int handle_control_getinfo(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_extendcircuit(connection_t *conn, uint32_t len,
|
||||
static int handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_setpurpose(connection_t *conn, int for_circuits,
|
||||
static int handle_control_setpurpose(control_connection_t *conn, int for_circuits,
|
||||
uint32_t len, const char *body);
|
||||
static int handle_control_attachstream(connection_t *conn, uint32_t len,
|
||||
static int handle_control_attachstream(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_postdescriptor(connection_t *conn, uint32_t len,
|
||||
static int handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_redirectstream(connection_t *conn, uint32_t len,
|
||||
static int handle_control_redirectstream(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_closestream(connection_t *conn, uint32_t len,
|
||||
static int handle_control_closestream(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int handle_control_closecircuit(connection_t *conn, uint32_t len,
|
||||
static int handle_control_closecircuit(control_connection_t *conn, uint32_t len,
|
||||
const char *body);
|
||||
static int write_stream_target_to_buf(connection_t *conn, char *buf,
|
||||
static int write_stream_target_to_buf(edge_connection_t *conn, char *buf,
|
||||
size_t len);
|
||||
|
||||
/** Given a possibly invalid message type code <b>cmd</b>, return a
|
||||
@ -235,10 +235,11 @@ control_update_global_event_mask(void)
|
||||
for (i = 0; i < n_conns; ++i) {
|
||||
if (conns[i]->type == CONN_TYPE_CONTROL &&
|
||||
STATE_IS_OPEN(conns[i]->state)) {
|
||||
if (STATE_IS_V0(conns[i]->state))
|
||||
global_event_mask0 |= conns[i]->event_mask;
|
||||
control_connection_t *conn = TO_CONTROL_CONN(conns[i]);
|
||||
if (STATE_IS_V0(conn->_base.state))
|
||||
global_event_mask0 |= conn->event_mask;
|
||||
else
|
||||
global_event_mask1 |= conns[i]->event_mask;
|
||||
global_event_mask1 |= conn->event_mask;
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,10 +282,10 @@ control_adjust_event_log_severity(void)
|
||||
* <b>conn</b>-\>outbuf
|
||||
*/
|
||||
static INLINE void
|
||||
connection_write_str_to_buf(const char *s, connection_t *conn)
|
||||
connection_write_str_to_buf(const char *s, control_connection_t *conn)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
connection_write_to_buf(s, len, conn);
|
||||
connection_write_to_buf(s, len, TO_CONN(conn));
|
||||
}
|
||||
|
||||
/** Given a <b>len</b>-character string in <b>data</b>, made of lines
|
||||
@ -446,7 +447,7 @@ get_escaped_string(const char *start, size_t in_len_max,
|
||||
* Currently the length of the message is limited to 1024 (including the
|
||||
* ending \n\r\0. */
|
||||
static void
|
||||
connection_printf_to_buf(connection_t *conn, const char *format, ...)
|
||||
connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
|
||||
{
|
||||
#define CONNECTION_PRINTF_TO_BUF_BUFFERSIZE 1024
|
||||
va_list ap;
|
||||
@ -462,41 +463,41 @@ connection_printf_to_buf(connection_t *conn, const char *format, ...)
|
||||
buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-2] = '\n';
|
||||
buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-3] = '\r';
|
||||
}
|
||||
connection_write_to_buf(buf, len, conn);
|
||||
connection_write_to_buf(buf, len, TO_CONN(conn));
|
||||
}
|
||||
|
||||
/** Send a message of type <b>type</b> containing <b>len</b> bytes
|
||||
* from <b>body</b> along the control connection <b>conn</b> */
|
||||
static void
|
||||
send_control0_message(connection_t *conn, uint16_t type, uint32_t len,
|
||||
const char *body)
|
||||
send_control0_message(control_connection_t *conn, uint16_t type, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
char buf[10];
|
||||
tor_assert(conn);
|
||||
tor_assert(STATE_IS_V0(conn->state));
|
||||
tor_assert(STATE_IS_V0(conn->_base.state));
|
||||
tor_assert(len || !body);
|
||||
tor_assert(type <= _CONTROL0_CMD_MAX_RECOGNIZED);
|
||||
if (len < 65536) {
|
||||
set_uint16(buf, htons(len));
|
||||
set_uint16(buf+2, htons(type));
|
||||
connection_write_to_buf(buf, 4, conn);
|
||||
connection_write_to_buf(buf, 4, TO_CONN(conn));
|
||||
if (len)
|
||||
connection_write_to_buf(body, len, conn);
|
||||
connection_write_to_buf(body, len, TO_CONN(conn));
|
||||
} else {
|
||||
set_uint16(buf, htons(65535));
|
||||
set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENTHEADER));
|
||||
set_uint16(buf+4, htons(type));
|
||||
set_uint32(buf+6, htonl(len));
|
||||
connection_write_to_buf(buf, 10, conn);
|
||||
connection_write_to_buf(body, 65535-6, conn);
|
||||
connection_write_to_buf(buf, 10, TO_CONN(conn));
|
||||
connection_write_to_buf(body, 65535-6, TO_CONN(conn));
|
||||
len -= (65535-6);
|
||||
body += (65535-6);
|
||||
while (len) {
|
||||
size_t chunklen = (len<65535)?len:65535;
|
||||
set_uint16(buf, htons((uint16_t)chunklen));
|
||||
set_uint16(buf+2, htons(CONTROL0_CMD_FRAGMENT));
|
||||
connection_write_to_buf(buf, 4, conn);
|
||||
connection_write_to_buf(body, chunklen, conn);
|
||||
connection_write_to_buf(buf, 4, TO_CONN(conn));
|
||||
connection_write_to_buf(body, chunklen, TO_CONN(conn));
|
||||
len -= chunklen;
|
||||
body += chunklen;
|
||||
}
|
||||
@ -505,9 +506,9 @@ send_control0_message(connection_t *conn, uint16_t type, uint32_t len,
|
||||
|
||||
/** Send a "DONE" message down the control connection <b>conn</b> */
|
||||
static void
|
||||
send_control_done(connection_t *conn)
|
||||
send_control_done(control_connection_t *conn)
|
||||
{
|
||||
if (STATE_IS_V0(conn->state)) {
|
||||
if (STATE_IS_V0(conn->_base.state)) {
|
||||
send_control0_message(conn, CONTROL0_CMD_DONE, 0, NULL);
|
||||
} else {
|
||||
connection_write_str_to_buf("250 OK\r\n", conn);
|
||||
@ -518,7 +519,7 @@ send_control_done(connection_t *conn)
|
||||
* as provided in the <b>len</b> bytes at <b>msg</b>.
|
||||
*/
|
||||
static void
|
||||
send_control_done2(connection_t *conn, const char *msg, size_t len)
|
||||
send_control_done2(control_connection_t *conn, const char *msg, size_t len)
|
||||
{
|
||||
if (len==0)
|
||||
len = strlen(msg);
|
||||
@ -528,7 +529,7 @@ send_control_done2(connection_t *conn, const char *msg, size_t len)
|
||||
/** Send an error message with error code <b>error</b> and body
|
||||
* <b>message</b> down the connection <b>conn</b> */
|
||||
static void
|
||||
send_control0_error(connection_t *conn, uint16_t error, const char *message)
|
||||
send_control0_error(control_connection_t *conn, uint16_t error, const char *message)
|
||||
{
|
||||
char buf[256];
|
||||
size_t len;
|
||||
@ -561,11 +562,13 @@ send_control0_event(uint16_t event, uint32_t len, const char *body)
|
||||
for (i = 0; i < n_conns; ++i) {
|
||||
if (conns[i]->type == CONN_TYPE_CONTROL &&
|
||||
!conns[i]->marked_for_close &&
|
||||
conns[i]->state == CONTROL_CONN_STATE_OPEN_V0 &&
|
||||
conns[i]->event_mask & (1<<event)) {
|
||||
send_control0_message(conns[i], CONTROL0_CMD_EVENT, buflen, buf);
|
||||
if (event == EVENT_ERR_MSG)
|
||||
_connection_controller_force_write(conns[i]);
|
||||
conns[i]->state == CONTROL_CONN_STATE_OPEN_V0) {
|
||||
control_connection_t *control_conn = TO_CONTROL_CONN(conns[i]);
|
||||
if (control_conn->event_mask & (1<<event)) {
|
||||
send_control0_message(control_conn, CONTROL0_CMD_EVENT, buflen, buf);
|
||||
if (event == EVENT_ERR_MSG)
|
||||
_connection_controller_force_write(control_conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -586,11 +589,13 @@ send_control1_event_string(uint16_t event, const char *msg)
|
||||
for (i = 0; i < n_conns; ++i) {
|
||||
if (conns[i]->type == CONN_TYPE_CONTROL &&
|
||||
!conns[i]->marked_for_close &&
|
||||
conns[i]->state == CONTROL_CONN_STATE_OPEN_V1 &&
|
||||
conns[i]->event_mask & (1<<event)) {
|
||||
connection_write_to_buf(msg, strlen(msg), conns[i]);
|
||||
if (event == EVENT_ERR_MSG)
|
||||
_connection_controller_force_write(conns[i]);
|
||||
conns[i]->state == CONTROL_CONN_STATE_OPEN_V1) {
|
||||
control_connection_t *control_conn = TO_CONTROL_CONN(conns[i]);
|
||||
if (control_conn->event_mask & (1<<event)) {
|
||||
connection_write_to_buf(msg, strlen(msg), TO_CONN(control_conn));
|
||||
if (event == EVENT_ERR_MSG)
|
||||
_connection_controller_force_write(control_conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -657,14 +662,14 @@ get_stream(const char *id)
|
||||
* it passes <b>use_defaults</b> on to options_trial_assign().
|
||||
*/
|
||||
static int
|
||||
control_setconf_helper(connection_t *conn, uint32_t len, char *body,
|
||||
control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
|
||||
int use_defaults, int clear_first)
|
||||
{
|
||||
int r;
|
||||
config_line_t *lines=NULL;
|
||||
char *start = body;
|
||||
char *errstring = NULL;
|
||||
int v0 = STATE_IS_V0(conn->state);
|
||||
int v0 = STATE_IS_V0(conn->_base.state);
|
||||
|
||||
if (!v0) {
|
||||
char *config = tor_malloc(len+1);
|
||||
@ -761,7 +766,7 @@ control_setconf_helper(connection_t *conn, uint32_t len, char *body,
|
||||
/** Called when we receive a SETCONF message: parse the body and try
|
||||
* to update our configuration. Reply with a DONE or ERROR message. */
|
||||
static int
|
||||
handle_control_setconf(connection_t *conn, uint32_t len, char *body)
|
||||
handle_control_setconf(control_connection_t *conn, uint32_t len, char *body)
|
||||
{
|
||||
return control_setconf_helper(conn, len, body, 0, 1);
|
||||
}
|
||||
@ -769,9 +774,9 @@ handle_control_setconf(connection_t *conn, uint32_t len, char *body)
|
||||
/** Called when we receive a RESETCONF message: parse the body and try
|
||||
* to update our configuration. Reply with a DONE or ERROR message. */
|
||||
static int
|
||||
handle_control_resetconf(connection_t *conn, uint32_t len, char *body)
|
||||
handle_control_resetconf(control_connection_t *conn, uint32_t len, char *body)
|
||||
{
|
||||
int v0 = STATE_IS_V0(conn->state);
|
||||
int v0 = STATE_IS_V0(conn->_base.state);
|
||||
tor_assert(!v0);
|
||||
return control_setconf_helper(conn, len, body, 1, 1);
|
||||
}
|
||||
@ -779,7 +784,7 @@ handle_control_resetconf(connection_t *conn, uint32_t len, char *body)
|
||||
/** Called when we receive a GETCONF message. Parse the request, and
|
||||
* reply with a CONFVALUE or an ERROR message */
|
||||
static int
|
||||
handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body)
|
||||
handle_control_getconf(control_connection_t *conn, uint32_t body_len, const char *body)
|
||||
{
|
||||
smartlist_t *questions = NULL;
|
||||
smartlist_t *answers = NULL;
|
||||
@ -787,7 +792,7 @@ handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body)
|
||||
char *msg = NULL;
|
||||
size_t msg_len;
|
||||
or_options_t *options = get_options();
|
||||
int v0 = STATE_IS_V0(conn->state);
|
||||
int v0 = STATE_IS_V0(conn->_base.state);
|
||||
|
||||
questions = smartlist_create();
|
||||
(void) body_len; /* body is nul-terminated; so we can ignore len. */
|
||||
@ -858,7 +863,7 @@ handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body)
|
||||
tor_assert(strlen(tmp)>4);
|
||||
tmp[3] = ' ';
|
||||
msg = smartlist_join_strings(answers, "", 0, &msg_len);
|
||||
connection_write_to_buf(msg, msg_len, conn);
|
||||
connection_write_to_buf(msg, msg_len, TO_CONN(conn));
|
||||
} else {
|
||||
connection_write_str_to_buf("250 OK\r\n", conn);
|
||||
}
|
||||
@ -882,13 +887,13 @@ handle_control_getconf(connection_t *conn, uint32_t body_len, const char *body)
|
||||
/** Called when we get a SETEVENTS message: update conn->event_mask,
|
||||
* and reply with DONE or ERROR. */
|
||||
static int
|
||||
handle_control_setevents(connection_t *conn, uint32_t len, const char *body)
|
||||
handle_control_setevents(control_connection_t *conn, uint32_t len, const char *body)
|
||||
{
|
||||
uint16_t event_code;
|
||||
uint32_t event_mask = 0;
|
||||
unsigned int extended = 0;
|
||||
|
||||
if (STATE_IS_V0(conn->state)) {
|
||||
if (STATE_IS_V0(conn->_base.state)) {
|
||||
if (len % 2) {
|
||||
send_control0_error(conn, ERR_SYNTAX,
|
||||
"Odd number of bytes in setevents message");
|
||||
@ -950,7 +955,7 @@ handle_control_setevents(connection_t *conn, uint32_t len, const char *body)
|
||||
smartlist_free(events);
|
||||
}
|
||||
conn->event_mask = event_mask;
|
||||
conn->control_events_are_extended = extended;
|
||||
conn->_base.control_events_are_extended = extended;
|
||||
|
||||
control_update_global_event_mask();
|
||||
send_control_done(conn);
|
||||
@ -987,13 +992,13 @@ decode_hashed_password(char *buf, const char *hashed)
|
||||
* OPEN. Reply with DONE or ERROR.
|
||||
*/
|
||||
static int
|
||||
handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
|
||||
handle_control_authenticate(control_connection_t *conn, uint32_t len, const char *body)
|
||||
{
|
||||
int used_quoted_string = 0;
|
||||
or_options_t *options = get_options();
|
||||
char *password;
|
||||
size_t password_len;
|
||||
if (STATE_IS_V0(conn->state)) {
|
||||
if (STATE_IS_V0(conn->_base.state)) {
|
||||
password = (char*)body;
|
||||
password_len = len;
|
||||
} else {
|
||||
@ -1047,7 +1052,7 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
|
||||
}
|
||||
|
||||
err:
|
||||
if (STATE_IS_V0(conn->state))
|
||||
if (STATE_IS_V0(conn->_base.state))
|
||||
send_control0_error(conn,ERR_REJECTED_AUTHENTICATION,
|
||||
"Authentication failed");
|
||||
else {
|
||||
@ -1061,12 +1066,12 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
|
||||
}
|
||||
return 0;
|
||||
ok:
|
||||
log_info(LD_CONTROL, "Authenticated control connection (%d)", conn->s);
|
||||
log_info(LD_CONTROL, "Authenticated control connection (%d)", conn->_base.s);
|
||||
send_control_done(conn);
|
||||
if (STATE_IS_V0(conn->state))
|
||||
conn->state = CONTROL_CONN_STATE_OPEN_V0;
|
||||
if (STATE_IS_V0(conn->_base.state))
|
||||
conn->_base.state = CONTROL_CONN_STATE_OPEN_V0;
|
||||
else {
|
||||
conn->state = CONTROL_CONN_STATE_OPEN_V1;
|
||||
conn->_base.state = CONTROL_CONN_STATE_OPEN_V1;
|
||||
tor_free(password);
|
||||
}
|
||||
return 0;
|
||||
@ -1075,13 +1080,13 @@ handle_control_authenticate(connection_t *conn, uint32_t len, const char *body)
|
||||
/** Called when we get a SAVECONF command. Try to flush the current options to
|
||||
* disk, and report success or failure. */
|
||||
static int
|
||||
handle_control_saveconf(connection_t *conn, uint32_t len,
|
||||
handle_control_saveconf(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
(void) len;
|
||||
(void) body;
|
||||
if (options_save_current()<0) {
|
||||
if (STATE_IS_V0(conn->state))
|
||||
if (STATE_IS_V0(conn->_base.state))
|
||||
send_control0_error(conn, ERR_INTERNAL,
|
||||
"Unable to write configuration to disk.");
|
||||
else
|
||||
@ -1097,11 +1102,11 @@ handle_control_saveconf(connection_t *conn, uint32_t len,
|
||||
* report success or failure. (If the signal results in a shutdown, success
|
||||
* may not be reported.) */
|
||||
static int
|
||||
handle_control_signal(connection_t *conn, uint32_t len,
|
||||
handle_control_signal(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
int sig;
|
||||
if (STATE_IS_V0(conn->state)) {
|
||||
if (STATE_IS_V0(conn->_base.state)) {
|
||||
if (len != 1) {
|
||||
send_control0_error(conn, ERR_SYNTAX,
|
||||
"Body of SIGNAL command too long or too short.");
|
||||
@ -1138,7 +1143,7 @@ handle_control_signal(connection_t *conn, uint32_t len,
|
||||
}
|
||||
|
||||
if (control_signal_act(sig) < 0) {
|
||||
if (STATE_IS_V0(conn->state))
|
||||
if (STATE_IS_V0(conn->_base.state))
|
||||
send_control0_error(conn, ERR_SYNTAX, "Unrecognized signal number.");
|
||||
else
|
||||
connection_write_str_to_buf("551 Internal error acting on signal\r\n",
|
||||
@ -1152,14 +1157,14 @@ handle_control_signal(connection_t *conn, uint32_t len,
|
||||
/** Called when we get a MAPADDRESS command; try to bind all listed addresses,
|
||||
* and report success or failrue. */
|
||||
static int
|
||||
handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body)
|
||||
handle_control_mapaddress(control_connection_t *conn, uint32_t len, const char *body)
|
||||
{
|
||||
smartlist_t *elts;
|
||||
smartlist_t *lines;
|
||||
smartlist_t *reply;
|
||||
char *r;
|
||||
size_t sz;
|
||||
int v0 = STATE_IS_V0(conn->state);
|
||||
int v0 = STATE_IS_V0(conn->_base.state);
|
||||
(void) len; /* body is nul-terminated, so it's safe to ignore the length. */
|
||||
|
||||
lines = smartlist_create();
|
||||
@ -1257,12 +1262,12 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body)
|
||||
if (smartlist_len(reply)) {
|
||||
((char*)smartlist_get(reply,smartlist_len(reply)-1))[3] = ' ';
|
||||
r = smartlist_join_strings(reply, "\r\n", 1, &sz);
|
||||
connection_write_to_buf(r, sz, conn);
|
||||
connection_write_to_buf(r, sz, TO_CONN(conn));
|
||||
tor_free(r);
|
||||
} else {
|
||||
const char *response =
|
||||
"512 syntax error: not enough arguments to mapaddress.\r\n";
|
||||
connection_write_to_buf(response, strlen(response), conn);
|
||||
connection_write_to_buf(response, strlen(response), TO_CONN(conn));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1399,6 +1404,7 @@ handle_getinfo_helper(const char *question, char **answer)
|
||||
get_connection_array(&conns, &n_conns);
|
||||
for (i=0; i < n_conns; ++i) {
|
||||
const char *state;
|
||||
edge_connection_t *conn;
|
||||
char *s;
|
||||
size_t slen;
|
||||
circuit_t *circ;
|
||||
@ -1406,12 +1412,13 @@ handle_getinfo_helper(const char *question, char **answer)
|
||||
conns[i]->marked_for_close ||
|
||||
conns[i]->state == AP_CONN_STATE_SOCKS_WAIT)
|
||||
continue;
|
||||
switch (conns[i]->state)
|
||||
conn = TO_EDGE_CONN(conns[i]);
|
||||
switch (conn->_base.state)
|
||||
{
|
||||
case AP_CONN_STATE_CONTROLLER_WAIT:
|
||||
case AP_CONN_STATE_CIRCUIT_WAIT:
|
||||
if (conns[i]->socks_request &&
|
||||
conns[i]->socks_request->command == SOCKS_COMMAND_RESOLVE)
|
||||
if (conn->socks_request &&
|
||||
conn->socks_request->command == SOCKS_COMMAND_RESOLVE)
|
||||
state = "NEWRESOLVE";
|
||||
else
|
||||
state = "NEW";
|
||||
@ -1425,15 +1432,15 @@ handle_getinfo_helper(const char *question, char **answer)
|
||||
state = "SUCCEEDED"; break;
|
||||
default:
|
||||
log_warn(LD_BUG, "Asked for stream in unknown state %d",
|
||||
conns[i]->state);
|
||||
conn->_base.state);
|
||||
continue;
|
||||
}
|
||||
circ = circuit_get_by_edge_conn(conns[i]);
|
||||
write_stream_target_to_buf(conns[i], buf, sizeof(buf));
|
||||
circ = circuit_get_by_edge_conn(conn);
|
||||
write_stream_target_to_buf(conn, buf, sizeof(buf));
|
||||
slen = strlen(buf)+strlen(state)+32;
|
||||
s = tor_malloc(slen+1);
|
||||
tor_snprintf(s, slen, "%lu %s %lu %s",
|
||||
(unsigned long) conns[i]->global_identifier,state,
|
||||
(unsigned long) conn->_base.global_identifier,state,
|
||||
circ?(unsigned long)circ->global_identifier : 0ul,
|
||||
buf);
|
||||
smartlist_add(status, s);
|
||||
@ -1451,10 +1458,11 @@ handle_getinfo_helper(const char *question, char **answer)
|
||||
char *s;
|
||||
char name[128];
|
||||
size_t slen;
|
||||
connection_t *conn = conns[i];
|
||||
if (conn->type != CONN_TYPE_OR || conn->marked_for_close)
|
||||
or_connection_t *conn;
|
||||
if (conns[i]->type != CONN_TYPE_OR || conns[i]->marked_for_close)
|
||||
continue;
|
||||
if (conn->state == OR_CONN_STATE_OPEN)
|
||||
conn = TO_OR_CONN(conns[i]);
|
||||
if (conn->_base.state == OR_CONN_STATE_OPEN)
|
||||
state = "CONNECTED";
|
||||
else if (conn->nickname)
|
||||
state = "LAUNCHED";
|
||||
@ -1464,7 +1472,7 @@ handle_getinfo_helper(const char *question, char **answer)
|
||||
strlcpy(name, conn->nickname, sizeof(name));
|
||||
else
|
||||
tor_snprintf(name, sizeof(name), "%s:%d",
|
||||
conn->address, conn->port);
|
||||
conn->_base.address, conn->_base.port);
|
||||
|
||||
slen = strlen(name)+strlen(state)+2;
|
||||
s = tor_malloc(slen+1);
|
||||
@ -1544,14 +1552,14 @@ handle_getinfo_helper(const char *question, char **answer)
|
||||
/** Called when we receive a GETINFO command. Try to fetch all requested
|
||||
* information, and reply with information or error message. */
|
||||
static int
|
||||
handle_control_getinfo(connection_t *conn, uint32_t len, const char *body)
|
||||
handle_control_getinfo(control_connection_t *conn, uint32_t len, const char *body)
|
||||
{
|
||||
smartlist_t *questions = NULL;
|
||||
smartlist_t *answers = NULL;
|
||||
smartlist_t *unrecognized = NULL;
|
||||
char *msg = NULL, *ans = NULL;
|
||||
size_t msg_len;
|
||||
int v0 = STATE_IS_V0(conn->state);
|
||||
int v0 = STATE_IS_V0(conn->_base.state);
|
||||
(void) len; /* body is nul-terminated, so it's safe to ignore the length. */
|
||||
|
||||
questions = smartlist_create();
|
||||
@ -1615,7 +1623,7 @@ handle_control_getinfo(connection_t *conn, uint32_t len, const char *body)
|
||||
size_t len;
|
||||
len = write_escaped_data(v, strlen(v), 1, &esc);
|
||||
connection_printf_to_buf(conn, "250+%s=\r\n", k);
|
||||
connection_write_to_buf(esc, len, conn);
|
||||
connection_write_to_buf(esc, len, TO_CONN(conn));
|
||||
tor_free(esc);
|
||||
}
|
||||
}
|
||||
@ -1662,7 +1670,7 @@ get_purpose(char *string, int for_circuits, uint8_t *purpose)
|
||||
/** Called when we get an EXTENDCIRCUIT message. Try to extend the listed
|
||||
* circuit, and report success or failure. */
|
||||
static int
|
||||
handle_control_extendcircuit(connection_t *conn, uint32_t len,
|
||||
handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
smartlist_t *router_nicknames=NULL, *routers=NULL;
|
||||
@ -1672,7 +1680,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
|
||||
char reply[4];
|
||||
uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
|
||||
|
||||
v0 = STATE_IS_V0(conn->state);
|
||||
v0 = STATE_IS_V0(conn->_base.state);
|
||||
router_nicknames = smartlist_create();
|
||||
|
||||
if (v0) {
|
||||
@ -1816,7 +1824,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
|
||||
* is 1) or SETROUTERPURPOSE message. If we can find
|
||||
* the circuit/router and it's a valid purpose, change it. */
|
||||
static int
|
||||
handle_control_setpurpose(connection_t *conn, int for_circuits,
|
||||
handle_control_setpurpose(control_connection_t *conn, int for_circuits,
|
||||
uint32_t len, const char *body)
|
||||
{
|
||||
circuit_t *circ = NULL;
|
||||
@ -1868,14 +1876,15 @@ done:
|
||||
/** Called when we get an ATTACHSTREAM message. Try to attach the requested
|
||||
* stream, and report success or failure. */
|
||||
static int
|
||||
handle_control_attachstream(connection_t *conn, uint32_t len,
|
||||
handle_control_attachstream(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
connection_t *ap_conn = NULL;
|
||||
circuit_t *circ = NULL;
|
||||
int zero_circ;
|
||||
edge_connection_t *edge_conn;
|
||||
|
||||
if (STATE_IS_V0(conn->state)) {
|
||||
if (STATE_IS_V0(conn->_base.state)) {
|
||||
uint32_t conn_id;
|
||||
uint32_t circ_id;
|
||||
if (len < 8) {
|
||||
@ -1927,7 +1936,7 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
|
||||
if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT &&
|
||||
ap_conn->state != AP_CONN_STATE_CONNECT_WAIT &&
|
||||
ap_conn->state != AP_CONN_STATE_RESOLVE_WAIT) {
|
||||
if (STATE_IS_V0(conn->state)) {
|
||||
if (STATE_IS_V0(conn->_base.state)) {
|
||||
send_control0_error(conn, ERR_NO_STREAM,
|
||||
"Connection is not managed by controller.");
|
||||
} else {
|
||||
@ -1938,20 +1947,23 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
edge_conn = TO_EDGE_CONN(ap_conn);
|
||||
|
||||
/* Do we need to detach it first? */
|
||||
if (ap_conn->state != AP_CONN_STATE_CONTROLLER_WAIT) {
|
||||
circuit_t *tmpcirc = circuit_get_by_edge_conn(ap_conn);
|
||||
connection_edge_end(ap_conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer);
|
||||
circuit_t *tmpcirc = circuit_get_by_edge_conn(edge_conn);
|
||||
connection_edge_end(edge_conn, END_STREAM_REASON_TIMEOUT,
|
||||
edge_conn->cpath_layer);
|
||||
/* Un-mark it as ending, since we're going to reuse it. */
|
||||
ap_conn->has_sent_end = 0;
|
||||
ap_conn->edge_has_sent_end = 0;
|
||||
if (tmpcirc)
|
||||
circuit_detach_stream(tmpcirc,ap_conn);
|
||||
circuit_detach_stream(tmpcirc,edge_conn);
|
||||
ap_conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
|
||||
}
|
||||
|
||||
if (circ &&
|
||||
(circ->state != CIRCUIT_STATE_OPEN || ! CIRCUIT_IS_ORIGIN(circ))) {
|
||||
if (STATE_IS_V0(conn->state))
|
||||
if (STATE_IS_V0(conn->_base.state))
|
||||
send_control0_error(conn, ERR_INTERNAL,
|
||||
"Refuse to attach stream to non-open, origin circ.");
|
||||
else
|
||||
@ -1960,9 +1972,9 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
|
||||
conn);
|
||||
return 0;
|
||||
}
|
||||
if (connection_ap_handshake_rewrite_and_attach(ap_conn,
|
||||
if (connection_ap_handshake_rewrite_and_attach(edge_conn,
|
||||
circ ? TO_ORIGIN_CIRCUIT(circ) : NULL) < 0) {
|
||||
if (STATE_IS_V0(conn->state))
|
||||
if (STATE_IS_V0(conn->_base.state))
|
||||
send_control0_error(conn, ERR_INTERNAL, "Unable to attach stream.");
|
||||
else
|
||||
connection_write_str_to_buf("551 Unable to attach stream\r\n", conn);
|
||||
@ -1975,11 +1987,11 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
|
||||
/** Called when we get a POSTDESCRIPTOR message. Try to learn the provided
|
||||
* descriptor, and report success or failure. */
|
||||
static int
|
||||
handle_control_postdescriptor(connection_t *conn, uint32_t len,
|
||||
handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
char *desc;
|
||||
int v0 = STATE_IS_V0(conn->state);
|
||||
int v0 = STATE_IS_V0(conn->_base.state);
|
||||
const char *msg=NULL;
|
||||
uint8_t purpose = ROUTER_PURPOSE_GENERAL;
|
||||
|
||||
@ -2034,14 +2046,14 @@ handle_control_postdescriptor(connection_t *conn, uint32_t len,
|
||||
/** Called when we receive a REDIRECTSTERAM command. Try to change the target
|
||||
* address of the named AP stream, and report success or failure. */
|
||||
static int
|
||||
handle_control_redirectstream(connection_t *conn, uint32_t len,
|
||||
handle_control_redirectstream(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
connection_t *ap_conn = NULL;
|
||||
uint32_t conn_id;
|
||||
char *new_addr = NULL;
|
||||
uint16_t new_port = 0;
|
||||
if (STATE_IS_V0(conn->state)) {
|
||||
if (STATE_IS_V0(conn->_base.state)) {
|
||||
if (len < 6) {
|
||||
send_control0_error(conn, ERR_SYNTAX,
|
||||
"redirectstream message too short");
|
||||
@ -2051,7 +2063,7 @@ handle_control_redirectstream(connection_t *conn, uint32_t len,
|
||||
|
||||
if (!(ap_conn = connection_get_by_global_id(conn_id))
|
||||
|| ap_conn->state != CONN_TYPE_AP
|
||||
|| !ap_conn->socks_request) {
|
||||
|| !TO_EDGE_CONN(ap_conn)->socks_request) {
|
||||
send_control0_error(conn, ERR_NO_STREAM,
|
||||
"No AP connection found with given ID");
|
||||
return 0;
|
||||
@ -2066,7 +2078,7 @@ handle_control_redirectstream(connection_t *conn, uint32_t len,
|
||||
connection_printf_to_buf(conn,
|
||||
"512 Missing argument to REDIRECTSTREAM\r\n");
|
||||
else if (!(ap_conn = get_stream(smartlist_get(args, 0)))
|
||||
|| !ap_conn->socks_request) {
|
||||
|| !TO_EDGE_CONN(ap_conn)->socks_request) {
|
||||
connection_printf_to_buf(conn, "552 Unknown stream \"%s\"\r\n",
|
||||
(char*)smartlist_get(args, 0));
|
||||
} else {
|
||||
@ -2089,25 +2101,28 @@ handle_control_redirectstream(connection_t *conn, uint32_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
strlcpy(ap_conn->socks_request->address, new_addr,
|
||||
sizeof(ap_conn->socks_request->address));
|
||||
if (new_port)
|
||||
ap_conn->socks_request->port = new_port;
|
||||
tor_free(new_addr);
|
||||
send_control_done(conn);
|
||||
return 0;
|
||||
{
|
||||
edge_connection_t *ap = TO_EDGE_CONN(ap_conn);
|
||||
strlcpy(ap->socks_request->address, new_addr,
|
||||
sizeof(ap->socks_request->address));
|
||||
if (new_port)
|
||||
ap->socks_request->port = new_port;
|
||||
tor_free(new_addr);
|
||||
send_control_done(conn);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when we get a CLOSESTREAM command; try to close the named stream
|
||||
* and report success or failure. */
|
||||
static int
|
||||
handle_control_closestream(connection_t *conn, uint32_t len,
|
||||
handle_control_closestream(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
connection_t *ap_conn=NULL;
|
||||
uint8_t reason=0;
|
||||
|
||||
if (STATE_IS_V0(conn->state)) {
|
||||
if (STATE_IS_V0(conn->_base.state)) {
|
||||
uint32_t conn_id;
|
||||
if (len < 6) {
|
||||
send_control0_error(conn, ERR_SYNTAX, "closestream message too short");
|
||||
@ -2119,7 +2134,7 @@ handle_control_closestream(connection_t *conn, uint32_t len,
|
||||
|
||||
if (!(ap_conn = connection_get_by_global_id(conn_id))
|
||||
|| ap_conn->state != CONN_TYPE_AP
|
||||
|| !ap_conn->socks_request) {
|
||||
|| !TO_EDGE_CONN(ap_conn)->socks_request) {
|
||||
send_control0_error(conn, ERR_NO_STREAM,
|
||||
"No AP connection found with given ID");
|
||||
return 0;
|
||||
@ -2151,7 +2166,7 @@ handle_control_closestream(connection_t *conn, uint32_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
connection_mark_unattached_ap(ap_conn, reason);
|
||||
connection_mark_unattached_ap(TO_EDGE_CONN(ap_conn), reason);
|
||||
send_control_done(conn);
|
||||
return 0;
|
||||
}
|
||||
@ -2159,13 +2174,13 @@ handle_control_closestream(connection_t *conn, uint32_t len,
|
||||
/** Called when we get a CLOSECIRCUIT command; try to close the named circuit
|
||||
* and report success or failure. */
|
||||
static int
|
||||
handle_control_closecircuit(connection_t *conn, uint32_t len,
|
||||
handle_control_closecircuit(control_connection_t *conn, uint32_t len,
|
||||
const char *body)
|
||||
{
|
||||
circuit_t *circ = NULL;
|
||||
int safe = 0;
|
||||
|
||||
if (STATE_IS_V0(conn->state)) {
|
||||
if (STATE_IS_V0(conn->_base.state)) {
|
||||
uint32_t circ_id;
|
||||
if (len < 5) {
|
||||
send_control0_error(conn, ERR_SYNTAX, "closecircuit message too short");
|
||||
@ -2221,7 +2236,7 @@ handle_control_closecircuit(connection_t *conn, uint32_t len,
|
||||
* fragments and report failure.
|
||||
*/
|
||||
static int
|
||||
handle_control_fragments(connection_t *conn, uint16_t command_type,
|
||||
handle_control_fragments(control_connection_t *conn, uint16_t command_type,
|
||||
uint32_t body_len, char *body)
|
||||
{
|
||||
if (command_type == CONTROL0_CMD_FRAGMENTHEADER) {
|
||||
@ -2262,24 +2277,22 @@ handle_control_fragments(connection_t *conn, uint16_t command_type,
|
||||
|
||||
/** Called when <b>conn</b> has no more bytes left on its outbuf. */
|
||||
int
|
||||
connection_control_finished_flushing(connection_t *conn)
|
||||
connection_control_finished_flushing(control_connection_t *conn)
|
||||
{
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->type == CONN_TYPE_CONTROL);
|
||||
|
||||
connection_stop_writing(conn);
|
||||
connection_stop_writing(TO_CONN(conn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Called when <b>conn</b> has gotten its socket closed. */
|
||||
int
|
||||
connection_control_reached_eof(connection_t *conn)
|
||||
connection_control_reached_eof(control_connection_t *conn)
|
||||
{
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->type == CONN_TYPE_CONTROL);
|
||||
|
||||
log_info(LD_CONTROL,"Control connection reached EOF. Closing.");
|
||||
connection_mark_for_close(conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2287,16 +2300,15 @@ connection_control_reached_eof(connection_t *conn)
|
||||
* commands from conn->inbuf, and execute them.
|
||||
*/
|
||||
static int
|
||||
connection_control_process_inbuf_v1(connection_t *conn)
|
||||
connection_control_process_inbuf_v1(control_connection_t *conn)
|
||||
{
|
||||
size_t data_len;
|
||||
int cmd_len;
|
||||
char *args;
|
||||
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->type == CONN_TYPE_CONTROL);
|
||||
tor_assert(conn->state == CONTROL_CONN_STATE_OPEN_V1 ||
|
||||
conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1);
|
||||
tor_assert(conn->_base.state == CONTROL_CONN_STATE_OPEN_V1 ||
|
||||
conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1);
|
||||
|
||||
if (!conn->incoming_cmd) {
|
||||
conn->incoming_cmd = tor_malloc(1024);
|
||||
@ -2311,7 +2323,7 @@ connection_control_process_inbuf_v1(connection_t *conn)
|
||||
/* First, fetch a line. */
|
||||
do {
|
||||
data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
|
||||
r = fetch_from_buf_line(conn->inbuf,
|
||||
r = fetch_from_buf_line(conn->_base.inbuf,
|
||||
conn->incoming_cmd+conn->incoming_cmd_cur_len,
|
||||
&data_len);
|
||||
if (r == 0)
|
||||
@ -2361,11 +2373,11 @@ connection_control_process_inbuf_v1(connection_t *conn)
|
||||
|
||||
if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
|
||||
connection_write_str_to_buf("250 closing connection\r\n", conn);
|
||||
connection_mark_for_close(conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (conn->state == CONTROL_CONN_STATE_NEEDAUTH_V1 &&
|
||||
if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V1 &&
|
||||
strcasecmp(conn->incoming_cmd, "AUTHENTICATE")) {
|
||||
connection_write_str_to_buf("514 Authentication required.\r\n", conn);
|
||||
conn->incoming_cmd_cur_len = 0;
|
||||
@ -2436,7 +2448,7 @@ connection_control_process_inbuf_v1(connection_t *conn)
|
||||
* commands from conn->inbuf, and execute them.
|
||||
*/
|
||||
static int
|
||||
connection_control_process_inbuf_v0(connection_t *conn)
|
||||
connection_control_process_inbuf_v0(control_connection_t *conn)
|
||||
{
|
||||
uint32_t body_len;
|
||||
uint16_t command_type;
|
||||
@ -2444,15 +2456,15 @@ connection_control_process_inbuf_v0(connection_t *conn)
|
||||
|
||||
again:
|
||||
/* Try to suck a control message from the buffer. */
|
||||
switch (fetch_from_buf_control0(conn->inbuf, &body_len, &command_type, &body,
|
||||
conn->state == CONTROL_CONN_STATE_NEEDAUTH_V0))
|
||||
switch (fetch_from_buf_control0(conn->_base.inbuf, &body_len, &command_type, &body,
|
||||
conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V0))
|
||||
{
|
||||
case -2:
|
||||
tor_free(body);
|
||||
log_info(LD_CONTROL,
|
||||
"Detected v1 control protocol on connection (fd %d)",
|
||||
conn->s);
|
||||
conn->state = CONTROL_CONN_STATE_NEEDAUTH_V1;
|
||||
conn->_base.s);
|
||||
conn->_base.state = CONTROL_CONN_STATE_NEEDAUTH_V1;
|
||||
return connection_control_process_inbuf_v1(conn);
|
||||
case -1:
|
||||
tor_free(body);
|
||||
@ -2470,7 +2482,7 @@ connection_control_process_inbuf_v0(connection_t *conn)
|
||||
|
||||
/* We got a command. If we need authentication, only authentication
|
||||
* commands will be considered. */
|
||||
if (conn->state == CONTROL_CONN_STATE_NEEDAUTH_V0 &&
|
||||
if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH_V0 &&
|
||||
command_type != CONTROL0_CMD_AUTHENTICATE) {
|
||||
log_info(LD_CONTROL, "Rejecting '%s' command; authentication needed.",
|
||||
control_cmd_to_string(command_type));
|
||||
@ -2584,12 +2596,11 @@ connection_control_process_inbuf_v0(connection_t *conn)
|
||||
/** Called when <b>conn</b> has received more bytes on its inbuf.
|
||||
*/
|
||||
int
|
||||
connection_control_process_inbuf(connection_t *conn)
|
||||
connection_control_process_inbuf(control_connection_t *conn)
|
||||
{
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->type == CONN_TYPE_CONTROL);
|
||||
|
||||
if (STATE_IS_V0(conn->state))
|
||||
if (STATE_IS_V0(conn->_base.state))
|
||||
return connection_control_process_inbuf_v0(conn);
|
||||
else
|
||||
return connection_control_process_inbuf_v1(conn);
|
||||
@ -2644,7 +2655,7 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp)
|
||||
* <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on
|
||||
* failure. */
|
||||
static int
|
||||
write_stream_target_to_buf(connection_t *conn, char *buf, size_t len)
|
||||
write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
|
||||
{
|
||||
char buf2[256];
|
||||
if (conn->chosen_exit_name)
|
||||
@ -2663,12 +2674,11 @@ write_stream_target_to_buf(connection_t *conn, char *buf, size_t len)
|
||||
/** Something has happened to the stream associated with AP connection
|
||||
* <b>conn</b>: tell any interested control connections. */
|
||||
int
|
||||
control_event_stream_status(connection_t *conn, stream_status_event_t tp)
|
||||
control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp)
|
||||
{
|
||||
char *msg;
|
||||
size_t len;
|
||||
char buf[256];
|
||||
tor_assert(conn->type == CONN_TYPE_AP);
|
||||
tor_assert(conn->socks_request);
|
||||
|
||||
if (!EVENT_IS_INTERESTING(EVENT_STREAM_STATUS))
|
||||
@ -2679,7 +2689,7 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp)
|
||||
len = strlen(buf);
|
||||
msg = tor_malloc(5+len+1);
|
||||
msg[0] = (uint8_t) tp;
|
||||
set_uint32(msg+1, htonl(conn->global_identifier));
|
||||
set_uint32(msg+1, htonl(conn->_base.global_identifier));
|
||||
strlcpy(msg+5, buf, len+1);
|
||||
|
||||
send_control0_event(EVENT_STREAM_STATUS, (uint32_t)(5+len+1), msg);
|
||||
@ -2705,7 +2715,7 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp)
|
||||
circ = circuit_get_by_edge_conn(conn);
|
||||
send_control1_event(EVENT_STREAM_STATUS,
|
||||
"650 STREAM %lu %s %lu %s\r\n",
|
||||
(unsigned long)conn->global_identifier, status,
|
||||
(unsigned long)conn->_base.global_identifier, status,
|
||||
circ?(unsigned long)circ->global_identifier : 0ul,
|
||||
buf);
|
||||
/* XXX need to specify its intended exit, etc? */
|
||||
@ -2716,13 +2726,11 @@ control_event_stream_status(connection_t *conn, stream_status_event_t tp)
|
||||
/** Something has happened to the OR connection <b>conn</b>: tell any
|
||||
* interested control connections. */
|
||||
int
|
||||
control_event_or_conn_status(connection_t *conn,or_conn_status_event_t tp)
|
||||
control_event_or_conn_status(or_connection_t *conn,or_conn_status_event_t tp)
|
||||
{
|
||||
char buf[HEX_DIGEST_LEN+3]; /* status, dollar, identity, NUL */
|
||||
size_t len;
|
||||
|
||||
tor_assert(conn->type == CONN_TYPE_OR);
|
||||
|
||||
if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS))
|
||||
return 0;
|
||||
|
||||
@ -2739,7 +2747,7 @@ control_event_or_conn_status(connection_t *conn,or_conn_status_event_t tp)
|
||||
strlcpy(name, conn->nickname, sizeof(name));
|
||||
else
|
||||
tor_snprintf(name, sizeof(name), "%s:%d",
|
||||
conn->address, conn->port);
|
||||
conn->_base.address, conn->_base.port);
|
||||
switch (tp)
|
||||
{
|
||||
case OR_CONN_EVENT_LAUNCHED: status = "LAUNCHED"; break;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
140
src/or/dns.c
140
src/or/dns.c
@ -53,7 +53,7 @@ static time_t last_rotation_time=0;
|
||||
|
||||
/** Linked list of connections waiting for a DNS answer. */
|
||||
typedef struct pending_connection_t {
|
||||
connection_t *conn;
|
||||
edge_connection_t *conn;
|
||||
struct pending_connection_t *next;
|
||||
} pending_connection_t;
|
||||
|
||||
@ -83,8 +83,8 @@ static void purge_expired_resolves(uint32_t now);
|
||||
static void dns_purge_resolve(cached_resolve_t *resolve);
|
||||
static void dns_found_answer(const char *address, uint32_t addr, char outcome,
|
||||
uint32_t ttl);
|
||||
static void send_resolved_cell(connection_t *conn, uint8_t answer_type);
|
||||
static int assign_to_dnsworker(connection_t *exitconn);
|
||||
static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type);
|
||||
static int assign_to_dnsworker(edge_connection_t *exitconn);
|
||||
#ifndef USE_EVENTDNS
|
||||
static int dnsworker_main(void *data);
|
||||
static int spawn_dnsworker(void);
|
||||
@ -226,7 +226,7 @@ purge_expired_resolves(uint32_t now)
|
||||
{
|
||||
cached_resolve_t *resolve;
|
||||
pending_connection_t *pend;
|
||||
connection_t *pendconn;
|
||||
edge_connection_t *pendconn;
|
||||
|
||||
/* this is fast because the linked list
|
||||
* oldest_cached_resolve is ordered by when they came in.
|
||||
@ -251,12 +251,12 @@ purge_expired_resolves(uint32_t now)
|
||||
pend = resolve->pending_connections;
|
||||
resolve->pending_connections = pend->next;
|
||||
/* Connections should only be pending if they have no socket. */
|
||||
tor_assert(pend->conn->s == -1);
|
||||
tor_assert(pend->conn->_base.s == -1);
|
||||
pendconn = pend->conn;
|
||||
connection_edge_end(pendconn, END_STREAM_REASON_TIMEOUT,
|
||||
pendconn->cpath_layer);
|
||||
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
|
||||
connection_free(pendconn);
|
||||
connection_free(TO_CONN(pendconn));
|
||||
tor_free(pend);
|
||||
}
|
||||
}
|
||||
@ -273,7 +273,7 @@ purge_expired_resolves(uint32_t now)
|
||||
/** Send a response to the RESOVLE request of a connection. answer_type must
|
||||
* be one of RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT) */
|
||||
static void
|
||||
send_resolved_cell(connection_t *conn, uint8_t answer_type)
|
||||
send_resolved_cell(edge_connection_t *conn, uint8_t answer_type)
|
||||
{
|
||||
char buf[RELAY_PAYLOAD_SIZE];
|
||||
size_t buflen;
|
||||
@ -286,7 +286,7 @@ send_resolved_cell(connection_t *conn, uint8_t answer_type)
|
||||
{
|
||||
case RESOLVED_TYPE_IPV4:
|
||||
buf[1] = 4;
|
||||
set_uint32(buf+2, htonl(conn->addr));
|
||||
set_uint32(buf+2, htonl(conn->_base.addr));
|
||||
set_uint32(buf+6, htonl(ttl));
|
||||
buflen = 10;
|
||||
break;
|
||||
@ -337,7 +337,7 @@ insert_resolve(cached_resolve_t *r)
|
||||
* dns farm, and return 0.
|
||||
*/
|
||||
int
|
||||
dns_resolve(connection_t *exitconn)
|
||||
dns_resolve(edge_connection_t *exitconn)
|
||||
{
|
||||
cached_resolve_t *resolve;
|
||||
cached_resolve_t search;
|
||||
@ -345,17 +345,17 @@ dns_resolve(connection_t *exitconn)
|
||||
struct in_addr in;
|
||||
circuit_t *circ;
|
||||
uint32_t now = time(NULL);
|
||||
assert_connection_ok(exitconn, 0);
|
||||
tor_assert(exitconn->s == -1);
|
||||
assert_connection_ok(TO_CONN(exitconn), 0);
|
||||
tor_assert(exitconn->_base.s == -1);
|
||||
|
||||
assert_cache_ok();
|
||||
|
||||
/* first check if exitconn->address is an IP. If so, we already
|
||||
/* first check if exitconn->_base.address is an IP. If so, we already
|
||||
* know the answer. */
|
||||
if (tor_inet_aton(exitconn->address, &in) != 0) {
|
||||
exitconn->addr = ntohl(in.s_addr);
|
||||
if (tor_inet_aton(exitconn->_base.address, &in) != 0) {
|
||||
exitconn->_base.addr = ntohl(in.s_addr);
|
||||
exitconn->address_ttl = DEFAULT_DNS_TTL;
|
||||
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
||||
if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
|
||||
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
|
||||
return 1;
|
||||
}
|
||||
@ -364,11 +364,11 @@ dns_resolve(connection_t *exitconn)
|
||||
* resolves in the hash table. */
|
||||
purge_expired_resolves(now);
|
||||
|
||||
/* lower-case exitconn->address, so it's in canonical form */
|
||||
tor_strlower(exitconn->address);
|
||||
/* lower-case exitconn->_base.address, so it's in canonical form */
|
||||
tor_strlower(exitconn->_base.address);
|
||||
|
||||
/* now check the hash table to see if 'address' is already there. */
|
||||
strlcpy(search.address, exitconn->address, sizeof(search.address));
|
||||
strlcpy(search.address, exitconn->_base.address, sizeof(search.address));
|
||||
resolve = HT_FIND(cache_map, &cache_root, &search);
|
||||
if (resolve && resolve->expire > now) { /* already there */
|
||||
switch (resolve->state) {
|
||||
@ -381,27 +381,27 @@ dns_resolve(connection_t *exitconn)
|
||||
resolve->pending_connections = pending_connection;
|
||||
log_debug(LD_EXIT,"Connection (fd %d) waiting for pending DNS "
|
||||
"resolve of %s",
|
||||
exitconn->s, escaped_safe_str(exitconn->address));
|
||||
exitconn->state = EXIT_CONN_STATE_RESOLVING;
|
||||
exitconn->_base.s, escaped_safe_str(exitconn->_base.address));
|
||||
exitconn->_base.state = EXIT_CONN_STATE_RESOLVING;
|
||||
return 0;
|
||||
case CACHE_STATE_VALID:
|
||||
exitconn->addr = resolve->addr;
|
||||
exitconn->_base.addr = resolve->addr;
|
||||
exitconn->address_ttl = resolve->ttl;
|
||||
log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s",
|
||||
exitconn->s, escaped_safe_str(exitconn->address));
|
||||
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
||||
exitconn->_base.s, escaped_safe_str(exitconn->_base.address));
|
||||
if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
|
||||
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
|
||||
return 1;
|
||||
case CACHE_STATE_FAILED:
|
||||
log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s",
|
||||
exitconn->s, escaped_safe_str(exitconn->address));
|
||||
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
||||
exitconn->_base.s, escaped_safe_str(exitconn->_base.address));
|
||||
if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
|
||||
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
|
||||
circ = circuit_get_by_edge_conn(exitconn);
|
||||
if (circ)
|
||||
circuit_detach_stream(circ, exitconn);
|
||||
if (!exitconn->marked_for_close)
|
||||
connection_free(exitconn);
|
||||
if (!exitconn->_base.marked_for_close)
|
||||
connection_free(TO_CONN(exitconn));
|
||||
return -1;
|
||||
}
|
||||
tor_assert(0);
|
||||
@ -411,17 +411,17 @@ dns_resolve(connection_t *exitconn)
|
||||
resolve->magic = CACHED_RESOLVE_MAGIC;
|
||||
resolve->state = CACHE_STATE_PENDING;
|
||||
resolve->expire = now + DEFAULT_DNS_TTL; /* this will get replaced. */
|
||||
strlcpy(resolve->address, exitconn->address, sizeof(resolve->address));
|
||||
strlcpy(resolve->address, exitconn->_base.address, sizeof(resolve->address));
|
||||
|
||||
/* add us to the pending list */
|
||||
pending_connection = tor_malloc_zero(sizeof(pending_connection_t));
|
||||
pending_connection->conn = exitconn;
|
||||
resolve->pending_connections = pending_connection;
|
||||
exitconn->state = EXIT_CONN_STATE_RESOLVING;
|
||||
exitconn->_base.state = EXIT_CONN_STATE_RESOLVING;
|
||||
|
||||
insert_resolve(resolve);
|
||||
log_debug(LD_EXIT,"Assigning question %s to dnsworker.",
|
||||
escaped_safe_str(exitconn->address));
|
||||
escaped_safe_str(exitconn->_base.address));
|
||||
assert_cache_ok();
|
||||
return assign_to_dnsworker(exitconn);
|
||||
}
|
||||
@ -429,7 +429,7 @@ dns_resolve(connection_t *exitconn)
|
||||
/** Log an error and abort if conn is waiting for a DNS resolve.
|
||||
*/
|
||||
void
|
||||
assert_connection_edge_not_dns_pending(connection_t *conn)
|
||||
assert_connection_edge_not_dns_pending(edge_connection_t *conn)
|
||||
{
|
||||
pending_connection_t *pend;
|
||||
cached_resolve_t **resolve;
|
||||
@ -455,9 +455,9 @@ assert_all_pending_dns_resolves_ok(void)
|
||||
for (pend = (*resolve)->pending_connections;
|
||||
pend;
|
||||
pend = pend->next) {
|
||||
assert_connection_ok(pend->conn, 0);
|
||||
tor_assert(pend->conn->s == -1);
|
||||
tor_assert(!connection_in_array(pend->conn));
|
||||
assert_connection_ok(TO_CONN(pend->conn), 0);
|
||||
tor_assert(pend->conn->_base.s == -1);
|
||||
tor_assert(!connection_in_array(TO_CONN(pend->conn)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -465,26 +465,26 @@ assert_all_pending_dns_resolves_ok(void)
|
||||
/** Remove <b>conn</b> from the list of connections waiting for conn-\>address.
|
||||
*/
|
||||
void
|
||||
connection_dns_remove(connection_t *conn)
|
||||
connection_dns_remove(edge_connection_t *conn)
|
||||
{
|
||||
pending_connection_t *pend, *victim;
|
||||
cached_resolve_t search;
|
||||
cached_resolve_t *resolve;
|
||||
|
||||
tor_assert(conn->type == CONN_TYPE_EXIT);
|
||||
tor_assert(conn->state == EXIT_CONN_STATE_RESOLVING);
|
||||
tor_assert(conn->_base.type == CONN_TYPE_EXIT);
|
||||
tor_assert(conn->_base.state == EXIT_CONN_STATE_RESOLVING);
|
||||
|
||||
strlcpy(search.address, conn->address, sizeof(search.address));
|
||||
strlcpy(search.address, conn->_base.address, sizeof(search.address));
|
||||
|
||||
resolve = HT_FIND(cache_map, &cache_root, &search);
|
||||
if (!resolve) {
|
||||
log_notice(LD_BUG, "Address %s is not pending. Dropping.",
|
||||
escaped_safe_str(conn->address));
|
||||
escaped_safe_str(conn->_base.address));
|
||||
return;
|
||||
}
|
||||
|
||||
tor_assert(resolve->pending_connections);
|
||||
assert_connection_ok(conn,0);
|
||||
assert_connection_ok(TO_CONN(conn),0);
|
||||
|
||||
pend = resolve->pending_connections;
|
||||
|
||||
@ -493,7 +493,7 @@ connection_dns_remove(connection_t *conn)
|
||||
tor_free(pend);
|
||||
log_debug(LD_EXIT, "First connection (fd %d) no longer waiting "
|
||||
"for resolve of %s",
|
||||
conn->s, escaped_safe_str(conn->address));
|
||||
conn->_base.s, escaped_safe_str(conn->_base.address));
|
||||
return;
|
||||
} else {
|
||||
for ( ; pend->next; pend = pend->next) {
|
||||
@ -503,7 +503,7 @@ connection_dns_remove(connection_t *conn)
|
||||
tor_free(victim);
|
||||
log_debug(LD_EXIT,
|
||||
"Connection (fd %d) no longer waiting for resolve of %s",
|
||||
conn->s, escaped_safe_str(conn->address));
|
||||
conn->_base.s, escaped_safe_str(conn->_base.address));
|
||||
return; /* more are pending */
|
||||
}
|
||||
}
|
||||
@ -521,7 +521,7 @@ dns_cancel_pending_resolve(char *address)
|
||||
pending_connection_t *pend;
|
||||
cached_resolve_t search;
|
||||
cached_resolve_t *resolve;
|
||||
connection_t *pendconn;
|
||||
edge_connection_t *pendconn;
|
||||
circuit_t *circ;
|
||||
|
||||
strlcpy(search.address, address, sizeof(search.address));
|
||||
@ -549,18 +549,18 @@ dns_cancel_pending_resolve(char *address)
|
||||
escaped_safe_str(address));
|
||||
while (resolve->pending_connections) {
|
||||
pend = resolve->pending_connections;
|
||||
pend->conn->state = EXIT_CONN_STATE_RESOLVEFAILED;
|
||||
pend->conn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
|
||||
pendconn = pend->conn;
|
||||
assert_connection_ok(pendconn, 0);
|
||||
tor_assert(pendconn->s == -1);
|
||||
if (!pendconn->marked_for_close) {
|
||||
assert_connection_ok(TO_CONN(pendconn), 0);
|
||||
tor_assert(pendconn->_base.s == -1);
|
||||
if (!pendconn->_base.marked_for_close) {
|
||||
connection_edge_end(pendconn, END_STREAM_REASON_RESOURCELIMIT,
|
||||
pendconn->cpath_layer);
|
||||
}
|
||||
circ = circuit_get_by_edge_conn(pendconn);
|
||||
if (circ)
|
||||
circuit_detach_stream(circ, pendconn);
|
||||
connection_free(pendconn);
|
||||
connection_free(TO_CONN(pendconn));
|
||||
resolve->pending_connections = pend->next;
|
||||
tor_free(pend);
|
||||
}
|
||||
@ -612,7 +612,7 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
|
||||
pending_connection_t *pend;
|
||||
cached_resolve_t search;
|
||||
cached_resolve_t *resolve;
|
||||
connection_t *pendconn;
|
||||
edge_connection_t *pendconn;
|
||||
circuit_t *circ;
|
||||
|
||||
assert_cache_ok();
|
||||
@ -659,16 +659,16 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
|
||||
|
||||
while (resolve->pending_connections) {
|
||||
pend = resolve->pending_connections;
|
||||
assert_connection_ok(pend->conn,time(NULL));
|
||||
pend->conn->addr = resolve->addr;
|
||||
assert_connection_ok(TO_CONN(pend->conn),time(NULL));
|
||||
pend->conn->_base.addr = resolve->addr;
|
||||
pend->conn->address_ttl = resolve->ttl;
|
||||
pendconn = pend->conn; /* don't pass complex things to the
|
||||
connection_mark_for_close macro */
|
||||
|
||||
if (resolve->state == CACHE_STATE_FAILED) {
|
||||
/* prevent double-remove. */
|
||||
pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED;
|
||||
if (pendconn->purpose == EXIT_PURPOSE_CONNECT) {
|
||||
pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
|
||||
if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) {
|
||||
connection_edge_end(pendconn, END_STREAM_REASON_RESOLVEFAILED,
|
||||
pendconn->cpath_layer);
|
||||
/* This detach must happen after we send the end cell. */
|
||||
@ -678,11 +678,11 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
|
||||
/* This detach must happen after we send the resolved cell. */
|
||||
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
|
||||
}
|
||||
connection_free(pendconn);
|
||||
connection_free(TO_CONN(pendconn));
|
||||
} else {
|
||||
if (pendconn->purpose == EXIT_PURPOSE_CONNECT) {
|
||||
if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) {
|
||||
/* prevent double-remove. */
|
||||
pend->conn->state = EXIT_CONN_STATE_CONNECTING;
|
||||
pend->conn->_base.state = EXIT_CONN_STATE_CONNECTING;
|
||||
|
||||
circ = circuit_get_by_edge_conn(pend->conn);
|
||||
tor_assert(circ);
|
||||
@ -698,12 +698,12 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
|
||||
} else {
|
||||
/* prevent double-remove. This isn't really an accurate state,
|
||||
* but it does the right thing. */
|
||||
pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED;
|
||||
pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
|
||||
send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4);
|
||||
circ = circuit_get_by_edge_conn(pendconn);
|
||||
tor_assert(circ);
|
||||
circuit_detach_stream(circ, pendconn);
|
||||
connection_free(pendconn);
|
||||
connection_free(TO_CONN(pendconn));
|
||||
}
|
||||
}
|
||||
resolve->pending_connections = pend->next;
|
||||
@ -722,14 +722,14 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
|
||||
* <b>exitconn</b>-\>address; tell that dns worker to begin resolving.
|
||||
*/
|
||||
static int
|
||||
assign_to_dnsworker(connection_t *exitconn)
|
||||
assign_to_dnsworker(edge_connection_t *exitconn)
|
||||
{
|
||||
connection_t *dnsconn;
|
||||
unsigned char len;
|
||||
|
||||
tor_assert(exitconn->state == EXIT_CONN_STATE_RESOLVING);
|
||||
assert_connection_ok(exitconn, 0);
|
||||
tor_assert(exitconn->s == -1);
|
||||
tor_assert(exitconn->_base.state == EXIT_CONN_STATE_RESOLVING);
|
||||
assert_connection_ok(TO_CONN(exitconn), 0);
|
||||
tor_assert(exitconn->_base.s == -1);
|
||||
|
||||
/* respawn here, to be sure there are enough */
|
||||
if (spawn_enough_dnsworkers() < 0) {
|
||||
@ -741,18 +741,18 @@ assign_to_dnsworker(connection_t *exitconn)
|
||||
|
||||
if (!dnsconn) {
|
||||
log_warn(LD_EXIT,"no idle dns workers. Failing.");
|
||||
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
||||
if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
|
||||
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
log_debug(LD_EXIT,
|
||||
"Connection (fd %d) needs to resolve %s; assigning "
|
||||
"to DNSWorker (fd %d)", exitconn->s,
|
||||
escaped_safe_str(exitconn->address), dnsconn->s);
|
||||
"to DNSWorker (fd %d)", exitconn->_base.s,
|
||||
escaped_safe_str(exitconn->_base.address), dnsconn->s);
|
||||
|
||||
tor_free(dnsconn->address);
|
||||
dnsconn->address = tor_strdup(exitconn->address);
|
||||
dnsconn->address = tor_strdup(exitconn->_base.address);
|
||||
dnsconn->state = DNSWORKER_STATE_BUSY;
|
||||
/* touch the lastwritten timestamp, since that's how we check to
|
||||
* see how long it's been since we asked the question, and sometimes
|
||||
@ -766,7 +766,7 @@ assign_to_dnsworker(connection_t *exitconn)
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dns_cancel_pending_resolve(exitconn->address); /* also sends end and frees */
|
||||
dns_cancel_pending_resolve(exitconn->_base.address); /* also sends end and frees */
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1172,11 +1172,11 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses,
|
||||
static int
|
||||
assign_to_dnsworker(connection_t *exitconn)
|
||||
{
|
||||
char *addr = tor_strdup(exitconn->address);
|
||||
char *addr = tor_strdup(exitconn->_base.address);
|
||||
int r;
|
||||
log_info(LD_EXIT, "Launching eventdns request for %s",
|
||||
escaped_safe_str(exitconn->address));
|
||||
r = eventdns_resolve(exitconn->address, DNS_QUERY_NO_SEARCH,
|
||||
escaped_safe_str(exitconn->_base.address));
|
||||
r = eventdns_resolve(exitconn->_base.address, DNS_QUERY_NO_SEARCH,
|
||||
eventdns_callback, addr);
|
||||
if (r) {
|
||||
log_warn(LD_EXIT, "eventdns rejected address %s: error %d.",
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
280
src/or/or.h
280
src/or/or.h
@ -576,7 +576,11 @@ typedef struct {
|
||||
typedef struct buf_t buf_t;
|
||||
typedef struct socks_request_t socks_request_t;
|
||||
|
||||
#define CONNECTION_MAGIC 0x7C3C304Eu
|
||||
#define BASE_CONNECTION_MAGIC 0x7C3C304Eu
|
||||
#define OR_CONNECTION_MAGIC 0x7D31FF03u
|
||||
#define EDGE_CONNECTION_MAGIC 0xF0374013u
|
||||
#define DIR_CONNECTION_MAGIC 0x9988ffeeu
|
||||
#define CONTROL_CONNECTION_MAGIC 0x8abc765du
|
||||
|
||||
/** Description of a connection to another host or process, and associated
|
||||
* data.
|
||||
@ -609,14 +613,15 @@ struct connection_t {
|
||||
unsigned hold_open_until_flushed:1; /**< Despite this connection's being
|
||||
* marked for close, do we flush it
|
||||
* before closing it? */
|
||||
unsigned has_sent_end:1; /**< For debugging; only used on edge connections.
|
||||
* Set once we've set the stream end,
|
||||
|
||||
unsigned edge_has_sent_end:1; /**< For debugging; only used on edge
|
||||
* connections. Set once we've set the stream end,
|
||||
* and check in circuit_about_to_close_connection(). */
|
||||
/** For control connections only. If set, we send extended info with control
|
||||
* events as appropriate. */
|
||||
unsigned int control_events_are_extended:1;
|
||||
/** Used for OR conns that shouldn't get any new circs attached to them. */
|
||||
unsigned int is_obsolete:1;
|
||||
unsigned int or_is_obsolete:1;
|
||||
|
||||
int s; /**< Our socket; -1 if this connection is closed. */
|
||||
int poll_index; /* XXXX rename. */
|
||||
@ -648,22 +653,23 @@ struct connection_t {
|
||||
* we marked for close? */
|
||||
char *address; /**< FQDN (or IP) of the guy on the other end.
|
||||
* strdup into this, because free_connection frees it. */
|
||||
uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
|
||||
* connection. Exit connections only. */
|
||||
|
||||
/** Quasi-global identifier for this connection; used for control.c */
|
||||
/* XXXX NM This can get re-used after 2**32 circuits. */
|
||||
uint32_t global_identifier;
|
||||
|
||||
};
|
||||
|
||||
typedef struct connection_t connection_t;
|
||||
|
||||
/** DOCDOC */
|
||||
typedef struct or_connection_t {
|
||||
connection_t _base;
|
||||
|
||||
char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for
|
||||
* the other side's signing key. */
|
||||
char *nickname; /**< Nickname of OR on other side (if any). */
|
||||
|
||||
/** Nickname of planned exit node -- used with .exit support. */
|
||||
char *chosen_exit_name;
|
||||
/** If 1, and we fail to reach the chosen exit, stop requiring it. */
|
||||
unsigned int chosen_exit_optional:1;
|
||||
/** Number of times we've reassigned this application connection to
|
||||
* a new circuit. We keep track because the timeout is longer if we've
|
||||
* already retried several times. */
|
||||
int num_socks_retries;
|
||||
|
||||
/* Used only by OR connections: */
|
||||
tor_tls_t *tls; /**< TLS connection state (OR only.) */
|
||||
|
||||
/* bandwidth* and receiver_bucket only used by ORs in OPEN state: */
|
||||
@ -677,16 +683,19 @@ struct connection_t {
|
||||
* we use? */
|
||||
int n_circuits; /**< How many circuits use this connection as p_conn or
|
||||
* n_conn ? */
|
||||
struct connection_t *next_with_same_id; /**< Next connection with same
|
||||
struct or_connection_t *next_with_same_id; /**< Next connection with same
|
||||
* identity digest as this one. */
|
||||
uint16_t next_circ_id; /**< Which circ_id do we try to use next on
|
||||
* this connection? This is always in the
|
||||
* range 0..1<<15-1. (OR only.)*/
|
||||
} or_connection_t;
|
||||
|
||||
typedef struct edge_connection_t {
|
||||
connection_t _base;
|
||||
|
||||
/* Used only by edge connections: */
|
||||
uint16_t stream_id;
|
||||
struct connection_t *next_stream; /**< Points to the next stream at this
|
||||
* edge, if any (Edge only). */
|
||||
struct edge_connection_t *next_stream; /**< Points to the next stream at this
|
||||
* edge, if any (Edge only). */
|
||||
struct crypt_path_t *cpath_layer; /**< A pointer to which node in the circ
|
||||
* this conn exits at. (Edge only.) */
|
||||
int package_window; /**< How many more relay cells can i send into the
|
||||
@ -694,6 +703,36 @@ struct connection_t {
|
||||
int deliver_window; /**< How many more relay cells can end at me? (Edge
|
||||
* only.) */
|
||||
|
||||
/** Number of times we've reassigned this application connection to
|
||||
* a new circuit. We keep track because the timeout is longer if we've
|
||||
* already retried several times. */
|
||||
int num_socks_retries;
|
||||
|
||||
/** Nickname of planned exit node -- used with .exit support. */
|
||||
char *chosen_exit_name;
|
||||
/** If 1, and we fail to reach the chosen exit, stop requiring it. */
|
||||
unsigned int chosen_exit_optional:1;
|
||||
|
||||
/* Used only by AP connections */
|
||||
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
|
||||
* only.) */
|
||||
|
||||
struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
|
||||
* connection is using. */
|
||||
|
||||
uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
|
||||
* connection. Exit connections only. */
|
||||
|
||||
/* Used only by DIR and AP connections: */
|
||||
char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we
|
||||
* querying for? (DIR/AP only) */
|
||||
|
||||
|
||||
} edge_connection_t;
|
||||
|
||||
typedef struct dir_connection_t {
|
||||
connection_t _base;
|
||||
|
||||
/* Used only by Dir connections */
|
||||
char *requested_resource; /**< Which 'resource' did we ask the directory
|
||||
* for? */
|
||||
@ -708,31 +747,55 @@ struct connection_t {
|
||||
off_t cached_dir_offset;
|
||||
tor_zlib_state_t *zlib_state;
|
||||
|
||||
/* Used only by AP connections */
|
||||
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
|
||||
* only.) */
|
||||
/* Used only by DIR and AP connections: */
|
||||
char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we
|
||||
* querying for? (DIR/AP only) */
|
||||
|
||||
/** Quasi-global identifier for this connection; used for control.c */
|
||||
/* XXXX NM This can get re-used after 2**32 circuits. */
|
||||
uint32_t global_identifier;
|
||||
char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for
|
||||
* the directory server's signing key. */
|
||||
} dir_connection_t;
|
||||
|
||||
typedef struct control_connection_t {
|
||||
connection_t _base;
|
||||
|
||||
/* Used only by control connections */
|
||||
uint32_t event_mask;
|
||||
uint32_t incoming_cmd_len;
|
||||
uint32_t incoming_cmd_cur_len;
|
||||
char *incoming_cmd;
|
||||
|
||||
/* Used only by DIR and AP connections: */
|
||||
struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
|
||||
* connection is using. */
|
||||
char rend_query[REND_SERVICE_ID_LEN+1]; /**< What rendezvous service are we
|
||||
* querying for? (DIR/AP only) */
|
||||
|
||||
/* Used only by control v0 connections */
|
||||
uint16_t incoming_cmd_type;
|
||||
};
|
||||
} control_connection_t;
|
||||
|
||||
typedef struct connection_t connection_t;
|
||||
#define TO_CONN(c) &(((c)->_base))
|
||||
#define DOWNCAST(from, to, ptr) \
|
||||
(to*) (((from*)(ptr)) - STRUCT_OFFSET(to, _base))
|
||||
|
||||
or_connection_t *TO_OR_CONN(connection_t *);
|
||||
dir_connection_t *TO_DIR_CONN(connection_t *);
|
||||
edge_connection_t *TO_EDGE_CONN(connection_t *);
|
||||
control_connection_t *TO_CONTROL_CONN(connection_t *);
|
||||
|
||||
extern INLINE or_connection_t *TO_OR_CONN(connection_t *c)
|
||||
{
|
||||
tor_assert(c->magic == OR_CONNECTION_MAGIC);
|
||||
return DOWNCAST(connection_t, or_connection_t, c);
|
||||
}
|
||||
extern INLINE dir_connection_t *TO_DIR_CONN(connection_t *c)
|
||||
{
|
||||
tor_assert(c->magic == DIR_CONNECTION_MAGIC);
|
||||
return DOWNCAST(connection_t, dir_connection_t, c);
|
||||
}
|
||||
extern INLINE edge_connection_t *TO_EDGE_CONN(connection_t *c)
|
||||
{
|
||||
tor_assert(c->magic == EDGE_CONNECTION_MAGIC);
|
||||
return DOWNCAST(connection_t, edge_connection_t, c);
|
||||
}
|
||||
extern INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c)
|
||||
{
|
||||
tor_assert(c->magic == CONTROL_CONNECTION_MAGIC);
|
||||
return DOWNCAST(connection_t, control_connection_t, c);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
ADDR_POLICY_ACCEPT=1,
|
||||
@ -1072,7 +1135,7 @@ typedef struct circuit_t {
|
||||
* ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
|
||||
|
||||
/** The OR connection that is next in this circuit. */
|
||||
connection_t *n_conn;
|
||||
or_connection_t *n_conn;
|
||||
/** The identity hash of n_conn. */
|
||||
char n_conn_id_digest[DIGEST_LEN];
|
||||
/** The circuit_id used in the next (forward) hop of this circuit. */
|
||||
@ -1121,7 +1184,7 @@ typedef struct origin_circuit_t {
|
||||
circuit_t _base;
|
||||
|
||||
/** Linked list of AP streams associated with this circuit. */
|
||||
connection_t *p_streams;
|
||||
edge_connection_t *p_streams;
|
||||
/** Build state for this circuit. It includes the intended path
|
||||
* length, the chosen exit router, rendezvous information, etc.
|
||||
*/
|
||||
@ -1164,12 +1227,12 @@ typedef struct or_circuit_t {
|
||||
/** The circuit_id used in the previous (backward) hop of this circuit. */
|
||||
circid_t p_circ_id;
|
||||
/** The OR connection that is previous in this circuit. */
|
||||
connection_t *p_conn;
|
||||
or_connection_t *p_conn;
|
||||
/** Linked list of Exit streams associated with this circuit. */
|
||||
connection_t *n_streams;
|
||||
edge_connection_t *n_streams;
|
||||
/** Linked list of Exit streams associated with this circuit that are
|
||||
* still being resolved. */
|
||||
connection_t *resolving_streams;
|
||||
edge_connection_t *resolving_streams;
|
||||
/** The cipher used by intermediate hops for cells heading toward the
|
||||
* OP. */
|
||||
crypto_cipher_env_t *p_crypto;
|
||||
@ -1210,14 +1273,16 @@ or_circuit_t *TO_OR_CIRCUIT(circuit_t *x);
|
||||
extern INLINE or_circuit_t *TO_OR_CIRCUIT(circuit_t *x)
|
||||
{
|
||||
tor_assert(x->magic == OR_CIRCUIT_MAGIC);
|
||||
return (or_circuit_t*) (((char*)x) - STRUCT_OFFSET(or_circuit_t, _base));
|
||||
//return (or_circuit_t*) (((char*)x) - STRUCT_OFFSET(or_circuit_t, _base));
|
||||
return DOWNCAST(circuit_t, or_circuit_t, x);
|
||||
}
|
||||
origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x);
|
||||
extern INLINE origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x)
|
||||
{
|
||||
tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
|
||||
return (origin_circuit_t*)
|
||||
(((char*)x) - STRUCT_OFFSET(origin_circuit_t, _base));
|
||||
//return (origin_circuit_t*)
|
||||
// (((char*)x) - STRUCT_OFFSET(origin_circuit_t, _base));
|
||||
return DOWNCAST(circuit_t, origin_circuit_t, x);
|
||||
}
|
||||
|
||||
#define ALLOW_INVALID_ENTRY 1
|
||||
@ -1554,7 +1619,7 @@ origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
|
||||
int need_uptime, int need_capacity,
|
||||
int internal);
|
||||
int circuit_handle_first_hop(origin_circuit_t *circ);
|
||||
void circuit_n_conn_done(connection_t *or_conn, int status);
|
||||
void circuit_n_conn_done(or_connection_t *or_conn, int status);
|
||||
int inform_testing_reachability(void);
|
||||
int circuit_send_next_onion_skin(origin_circuit_t *circ);
|
||||
void circuit_note_clock_jumped(int seconds_elapsed);
|
||||
@ -1593,17 +1658,18 @@ circuit_t * _circuit_get_global_list(void);
|
||||
const char *circuit_state_to_string(int state);
|
||||
void circuit_dump_by_conn(connection_t *conn, int severity);
|
||||
void circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
|
||||
connection_t *conn);
|
||||
or_connection_t *conn);
|
||||
void circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
|
||||
connection_t *conn);
|
||||
or_connection_t *conn);
|
||||
void circuit_set_state(circuit_t *circ, int state);
|
||||
void circuit_close_all_marked(void);
|
||||
origin_circuit_t *origin_circuit_new(void);
|
||||
or_circuit_t *or_circuit_new(uint16_t p_circ_id, connection_t *p_conn);
|
||||
circuit_t *circuit_get_by_circid_orconn(uint16_t circ_id, connection_t *conn);
|
||||
int circuit_id_used_on_conn(uint16_t circ_id, connection_t *conn);
|
||||
circuit_t *circuit_get_by_edge_conn(connection_t *conn);
|
||||
void circuit_unlink_all_from_or_conn(connection_t *conn, int reason);
|
||||
or_circuit_t *or_circuit_new(uint16_t p_circ_id, or_connection_t *p_conn);
|
||||
circuit_t *circuit_get_by_circid_orconn(uint16_t circ_id,
|
||||
or_connection_t *conn);
|
||||
int circuit_id_used_on_conn(uint16_t circ_id, or_connection_t *conn);
|
||||
circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn);
|
||||
void circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason);
|
||||
circuit_t *circuit_get_by_global_id(uint32_t id);
|
||||
origin_circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query,
|
||||
uint8_t purpose);
|
||||
@ -1631,10 +1697,10 @@ void circuit_free_all(void);
|
||||
|
||||
void circuit_expire_building(time_t now);
|
||||
void circuit_remove_handled_ports(smartlist_t *needed_ports);
|
||||
int circuit_stream_is_being_handled(connection_t *conn, uint16_t port,
|
||||
int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port,
|
||||
int min);
|
||||
void circuit_build_needed_circs(time_t now);
|
||||
void circuit_detach_stream(circuit_t *circ, connection_t *conn);
|
||||
void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn);
|
||||
void circuit_about_to_close_connection(connection_t *conn);
|
||||
void circuit_has_opened(origin_circuit_t *circ);
|
||||
void circuit_build_failed(origin_circuit_t *circ);
|
||||
@ -1650,13 +1716,13 @@ origin_circuit_t *circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
|
||||
int need_uptime, int need_capacity,
|
||||
int is_internal);
|
||||
void circuit_reset_failure_count(int timeout);
|
||||
int connection_ap_handshake_attach_chosen_circuit(connection_t *conn,
|
||||
int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
|
||||
origin_circuit_t *circ);
|
||||
int connection_ap_handshake_attach_circuit(connection_t *conn);
|
||||
int connection_ap_handshake_attach_circuit(edge_connection_t *conn);
|
||||
|
||||
/********************************* command.c ***************************/
|
||||
|
||||
void command_process_cell(cell_t *cell, connection_t *conn);
|
||||
void command_process_cell(cell_t *cell, or_connection_t *conn);
|
||||
|
||||
extern uint64_t stats_n_padding_cells_processed;
|
||||
extern uint64_t stats_n_create_cells_processed;
|
||||
@ -1730,15 +1796,15 @@ int connection_fetch_from_buf(char *string, size_t len, connection_t *conn);
|
||||
int connection_wants_to_flush(connection_t *conn);
|
||||
int connection_outbuf_too_full(connection_t *conn);
|
||||
int connection_handle_write(connection_t *conn);
|
||||
void _connection_controller_force_write(connection_t *conn);
|
||||
void _connection_controller_force_write(control_connection_t *conn);
|
||||
void connection_write_to_buf(const char *string, size_t len,
|
||||
connection_t *conn);
|
||||
void connection_write_to_buf_zlib(connection_t *conn,
|
||||
void connection_write_to_buf_zlib(dir_connection_t *conn,
|
||||
tor_zlib_state_t *state,
|
||||
const char *data, size_t data_len,
|
||||
int done);
|
||||
|
||||
connection_t *connection_or_exact_get_by_addr_port(uint32_t addr,
|
||||
or_connection_t *connection_or_exact_get_by_addr_port(uint32_t addr,
|
||||
uint16_t port);
|
||||
connection_t *connection_get_by_global_id(uint32_t id);
|
||||
|
||||
@ -1759,34 +1825,34 @@ int connection_state_is_connecting(connection_t *conn);
|
||||
char *alloc_http_authenticator(const char *authenticator);
|
||||
|
||||
void assert_connection_ok(connection_t *conn, time_t now);
|
||||
int connection_or_nonopen_was_started_here(connection_t *conn);
|
||||
int connection_or_nonopen_was_started_here(or_connection_t *conn);
|
||||
|
||||
/********************************* connection_edge.c *************************/
|
||||
|
||||
#define connection_mark_unattached_ap(conn, endreason) \
|
||||
_connection_mark_unattached_ap((conn), (endreason), __LINE__, _SHORT_FILE_)
|
||||
|
||||
void _connection_mark_unattached_ap(connection_t *conn, int endreason,
|
||||
void _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
|
||||
int line, const char *file);
|
||||
int connection_edge_reached_eof(connection_t *conn);
|
||||
int connection_edge_process_inbuf(connection_t *conn, int package_partial);
|
||||
int connection_edge_destroy(uint16_t circ_id, connection_t *conn);
|
||||
int connection_edge_end(connection_t *conn, char reason,
|
||||
int connection_edge_reached_eof(edge_connection_t *conn);
|
||||
int connection_edge_process_inbuf(edge_connection_t *conn, int package_partial);
|
||||
int connection_edge_destroy(uint16_t circ_id, edge_connection_t *conn);
|
||||
int connection_edge_end(edge_connection_t *conn, char reason,
|
||||
crypt_path_t *cpath_layer);
|
||||
int connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer);
|
||||
int connection_edge_finished_flushing(connection_t *conn);
|
||||
int connection_edge_finished_connecting(connection_t *conn);
|
||||
int connection_edge_end_errno(edge_connection_t *conn, crypt_path_t *cpath_layer);
|
||||
int connection_edge_finished_flushing(edge_connection_t *conn);
|
||||
int connection_edge_finished_connecting(edge_connection_t *conn);
|
||||
|
||||
int connection_ap_handshake_send_begin(connection_t *ap_conn,
|
||||
int connection_ap_handshake_send_begin(edge_connection_t *ap_conn,
|
||||
origin_circuit_t *circ);
|
||||
int connection_ap_handshake_send_resolve(connection_t *ap_conn,
|
||||
int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn,
|
||||
origin_circuit_t *circ);
|
||||
|
||||
int connection_ap_make_bridge(char *address, uint16_t port);
|
||||
void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
|
||||
void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
|
||||
size_t replylen,
|
||||
socks5_reply_status_t status);
|
||||
void connection_ap_handshake_socks_resolved(connection_t *conn,
|
||||
void connection_ap_handshake_socks_resolved(edge_connection_t *conn,
|
||||
int answer_type,
|
||||
size_t answer_len,
|
||||
const char *answer,
|
||||
@ -1794,12 +1860,12 @@ void connection_ap_handshake_socks_resolved(connection_t *conn,
|
||||
|
||||
int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
|
||||
int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
|
||||
void connection_exit_connect(connection_t *conn);
|
||||
int connection_edge_is_rendezvous_stream(connection_t *conn);
|
||||
int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit);
|
||||
void connection_exit_connect(edge_connection_t *conn);
|
||||
int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
|
||||
int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit);
|
||||
void connection_ap_expire_beginning(void);
|
||||
void connection_ap_attach_pending(void);
|
||||
int connection_ap_detach_retriable(connection_t *conn, origin_circuit_t *circ);
|
||||
int connection_ap_detach_retriable(edge_connection_t *conn, origin_circuit_t *circ);
|
||||
|
||||
void addressmap_init(void);
|
||||
void addressmap_clean(time_t now);
|
||||
@ -1820,7 +1886,7 @@ int address_is_in_virtual_range(const char *addr);
|
||||
const char *addressmap_register_virtual_address(int type, char *new_address);
|
||||
void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
|
||||
time_t max_expires);
|
||||
int connection_ap_handshake_rewrite_and_attach(connection_t *conn,
|
||||
int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
|
||||
origin_circuit_t *circ);
|
||||
|
||||
void set_exit_redirects(smartlist_t *lst);
|
||||
@ -1831,23 +1897,23 @@ hostname_type_t parse_extended_hostname(char *address);
|
||||
|
||||
/********************************* connection_or.c ***************************/
|
||||
|
||||
void connection_or_remove_from_identity_map(connection_t *conn);
|
||||
void connection_or_remove_from_identity_map(or_connection_t *conn);
|
||||
void connection_or_clear_identity_map(void);
|
||||
connection_t *connection_or_get_by_identity_digest(const char *digest);
|
||||
or_connection_t *connection_or_get_by_identity_digest(const char *digest);
|
||||
|
||||
int connection_or_reached_eof(connection_t *conn);
|
||||
int connection_or_process_inbuf(connection_t *conn);
|
||||
int connection_or_finished_flushing(connection_t *conn);
|
||||
int connection_or_finished_connecting(connection_t *conn);
|
||||
int connection_or_reached_eof(or_connection_t *conn);
|
||||
int connection_or_process_inbuf(or_connection_t *conn);
|
||||
int connection_or_finished_flushing(or_connection_t *conn);
|
||||
int connection_or_finished_connecting(or_connection_t *conn);
|
||||
|
||||
connection_t *connection_or_connect(uint32_t addr, uint16_t port,
|
||||
or_connection_t *connection_or_connect(uint32_t addr, uint16_t port,
|
||||
const char *id_digest);
|
||||
|
||||
int connection_tls_start_handshake(connection_t *conn, int receiving);
|
||||
int connection_tls_continue_handshake(connection_t *conn);
|
||||
int connection_tls_start_handshake(or_connection_t *conn, int receiving);
|
||||
int connection_tls_continue_handshake(or_connection_t *conn);
|
||||
|
||||
void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn);
|
||||
int connection_or_send_destroy(uint16_t circ_id, connection_t *conn,
|
||||
void connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn);
|
||||
int connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn,
|
||||
int reason);
|
||||
|
||||
/********************************* control.c ***************************/
|
||||
@ -1906,14 +1972,14 @@ void control_adjust_event_log_severity(void);
|
||||
#define LOG_FN_CONN(conn, args) \
|
||||
CONN_LOG_PROTECT(conn, log_fn args)
|
||||
|
||||
int connection_control_finished_flushing(connection_t *conn);
|
||||
int connection_control_reached_eof(connection_t *conn);
|
||||
int connection_control_process_inbuf(connection_t *conn);
|
||||
int connection_control_finished_flushing(control_connection_t *conn);
|
||||
int connection_control_reached_eof(control_connection_t *conn);
|
||||
int connection_control_process_inbuf(control_connection_t *conn);
|
||||
|
||||
int control_event_circuit_status(origin_circuit_t *circ,
|
||||
circuit_status_event_t e);
|
||||
int control_event_stream_status(connection_t *conn, stream_status_event_t e);
|
||||
int control_event_or_conn_status(connection_t *conn, or_conn_status_event_t e);
|
||||
int control_event_stream_status(edge_connection_t *conn, stream_status_event_t e);
|
||||
int control_event_or_conn_status(or_connection_t *conn, or_conn_status_event_t e);
|
||||
int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written);
|
||||
void control_event_logmsg(int severity, unsigned int domain, const char *msg);
|
||||
int control_event_descriptors_changed(smartlist_t *routers);
|
||||
@ -1959,11 +2025,11 @@ void directory_initiate_command_routerstatus(routerstatus_t *status,
|
||||
int parse_http_response(const char *headers, int *code, time_t *date,
|
||||
int *compression, char **response);
|
||||
|
||||
int connection_dir_reached_eof(connection_t *conn);
|
||||
int connection_dir_process_inbuf(connection_t *conn);
|
||||
int connection_dir_finished_flushing(connection_t *conn);
|
||||
int connection_dir_finished_connecting(connection_t *conn);
|
||||
void connection_dir_request_failed(connection_t *conn);
|
||||
int connection_dir_reached_eof(dir_connection_t *conn);
|
||||
int connection_dir_process_inbuf(dir_connection_t *conn);
|
||||
int connection_dir_finished_flushing(dir_connection_t *conn);
|
||||
int connection_dir_finished_connecting(dir_connection_t *conn);
|
||||
void connection_dir_request_failed(dir_connection_t *conn);
|
||||
int dir_split_resource_into_fingerprints(const char *resource,
|
||||
smartlist_t *fp_out, int *compresseed_out,
|
||||
int decode_hex, int sort_uniq);
|
||||
@ -1971,7 +2037,7 @@ char *directory_dump_request_log(void);
|
||||
|
||||
/********************************* dirserv.c ***************************/
|
||||
|
||||
int connection_dirserv_flushed_some(connection_t *conn);
|
||||
int connection_dirserv_flushed_some(dir_connection_t *conn);
|
||||
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
|
||||
int dirserv_parse_fingerprint_file(const char *fname);
|
||||
void dirserv_free_fingerprint_list(void);
|
||||
@ -2021,11 +2087,11 @@ int connection_dns_finished_flushing(connection_t *conn);
|
||||
int connection_dns_reached_eof(connection_t *conn);
|
||||
int connection_dns_process_inbuf(connection_t *conn);
|
||||
void dnsworkers_rotate(void);
|
||||
void connection_dns_remove(connection_t *conn);
|
||||
void assert_connection_edge_not_dns_pending(connection_t *conn);
|
||||
void connection_dns_remove(edge_connection_t *conn);
|
||||
void assert_connection_edge_not_dns_pending(edge_connection_t *conn);
|
||||
void assert_all_pending_dns_resolves_ok(void);
|
||||
void dns_cancel_pending_resolve(char *question);
|
||||
int dns_resolve(connection_t *exitconn);
|
||||
int dns_resolve(edge_connection_t *exitconn);
|
||||
|
||||
/********************************* hibernate.c **********************/
|
||||
|
||||
@ -2146,12 +2212,12 @@ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
|
||||
void relay_header_pack(char *dest, const relay_header_t *src);
|
||||
void relay_header_unpack(relay_header_t *dest, const char *src);
|
||||
int connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
|
||||
int connection_edge_send_command(edge_connection_t *fromconn, circuit_t *circ,
|
||||
int relay_command, const char *payload,
|
||||
size_t payload_len,
|
||||
crypt_path_t *cpath_layer);
|
||||
int connection_edge_package_raw_inbuf(connection_t *conn, int package_partial);
|
||||
void connection_edge_consider_sending_sendme(connection_t *conn);
|
||||
int connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial);
|
||||
void connection_edge_consider_sending_sendme(edge_connection_t *conn);
|
||||
socks5_reply_status_t connection_edge_end_reason_socks5_response(int reason);
|
||||
int errno_to_end_reason(int e);
|
||||
|
||||
@ -2283,7 +2349,7 @@ void rend_service_rendezvous_has_opened(origin_circuit_t *circuit);
|
||||
int rend_service_introduce(origin_circuit_t *circuit, const char *request,
|
||||
size_t request_len);
|
||||
void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc);
|
||||
int rend_service_set_connection_addr_port(connection_t *conn,
|
||||
int rend_service_set_connection_addr_port(edge_connection_t *conn,
|
||||
origin_circuit_t *circ);
|
||||
void rend_service_dump_stats(int severity);
|
||||
void rend_service_free_all(void);
|
||||
@ -2332,7 +2398,7 @@ void mark_my_descriptor_dirty(void);
|
||||
void check_descriptor_bandwidth_changed(time_t now);
|
||||
void check_descriptor_ipaddress_changed(time_t now);
|
||||
void router_new_address_suggestion(const char *suggestion);
|
||||
int router_compare_to_my_exit_policy(connection_t *conn);
|
||||
int router_compare_to_my_exit_policy(edge_connection_t *conn);
|
||||
routerinfo_t *router_get_my_routerinfo(void);
|
||||
const char *router_get_my_descriptor(void);
|
||||
int router_digest_is_me(const char *digest);
|
||||
|
135
src/or/relay.c
135
src/or/relay.c
@ -16,19 +16,19 @@ const char relay_c_id[] =
|
||||
|
||||
static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
|
||||
crypt_path_t **layer_hint, char *recognized);
|
||||
static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
|
||||
static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell,
|
||||
int cell_direction);
|
||||
|
||||
static int
|
||||
connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
connection_t *conn,
|
||||
edge_connection_t *conn,
|
||||
crypt_path_t *layer_hint);
|
||||
static void
|
||||
circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint);
|
||||
static void
|
||||
circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint);
|
||||
static int
|
||||
circuit_resume_edge_reading_helper(connection_t *conn,
|
||||
circuit_resume_edge_reading_helper(edge_connection_t *conn,
|
||||
circuit_t *circ,
|
||||
crypt_path_t *layer_hint);
|
||||
static int
|
||||
@ -144,7 +144,7 @@ relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
|
||||
int
|
||||
circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
|
||||
{
|
||||
connection_t *conn=NULL;
|
||||
or_connection_t *or_conn=NULL;
|
||||
crypt_path_t *layer_hint=NULL;
|
||||
char recognized=0;
|
||||
int reason;
|
||||
@ -162,7 +162,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
|
||||
}
|
||||
|
||||
if (recognized) {
|
||||
conn = relay_lookup_conn(circ, cell, cell_direction);
|
||||
edge_connection_t *conn = relay_lookup_conn(circ, cell, cell_direction);
|
||||
if (cell_direction == CELL_DIRECTION_OUT) {
|
||||
++stats_n_relay_cells_delivered;
|
||||
log_debug(LD_OR,"Sending away from origin.");
|
||||
@ -190,16 +190,16 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
|
||||
/* not recognized. pass it on. */
|
||||
if (cell_direction == CELL_DIRECTION_OUT) {
|
||||
cell->circ_id = circ->n_circ_id; /* switch it */
|
||||
conn = circ->n_conn;
|
||||
or_conn = circ->n_conn;
|
||||
} else if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||
cell->circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; /* switch it */
|
||||
conn = TO_OR_CIRCUIT(circ)->p_conn;
|
||||
or_conn = TO_OR_CIRCUIT(circ)->p_conn;
|
||||
} else {
|
||||
// XXXX NM WARN.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!conn) {
|
||||
if (!or_conn) {
|
||||
// XXXX Can this splice stuff be done more cleanly?
|
||||
if (! CIRCUIT_IS_ORIGIN(circ) &&
|
||||
TO_OR_CIRCUIT(circ)->rend_splice &&
|
||||
@ -225,7 +225,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
|
||||
|
||||
log_debug(LD_OR,"Passing on unrecognized cell.");
|
||||
++stats_n_relay_cells_relayed;
|
||||
connection_or_write_cell_to_buf(cell, conn);
|
||||
connection_or_write_cell_to_buf(cell, or_conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -323,7 +323,7 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
int cell_direction,
|
||||
crypt_path_t *layer_hint)
|
||||
{
|
||||
connection_t *conn; /* where to send the cell */
|
||||
or_connection_t *conn; /* where to send the cell */
|
||||
|
||||
if (cell_direction == CELL_DIRECTION_OUT) {
|
||||
crypt_path_t *thishop; /* counter for repeated crypts */
|
||||
@ -369,10 +369,10 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
/** If cell's stream_id matches the stream_id of any conn that's
|
||||
* attached to circ, return that conn, else return NULL.
|
||||
*/
|
||||
static connection_t *
|
||||
static edge_connection_t *
|
||||
relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
|
||||
{
|
||||
connection_t *tmpconn;
|
||||
edge_connection_t *tmpconn;
|
||||
relay_header_t rh;
|
||||
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
@ -387,7 +387,8 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
|
||||
tmpconn=tmpconn->next_stream) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
|
||||
if (rh.stream_id == tmpconn->stream_id &&
|
||||
!tmpconn->_base.marked_for_close) {
|
||||
log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
}
|
||||
@ -395,7 +396,7 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
|
||||
} else {
|
||||
for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
|
||||
tmpconn=tmpconn->next_stream) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->_base.marked_for_close) {
|
||||
log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
|
||||
if (cell_direction == CELL_DIRECTION_OUT ||
|
||||
connection_edge_is_rendezvous_stream(tmpconn))
|
||||
@ -404,7 +405,7 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
|
||||
}
|
||||
for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn;
|
||||
tmpconn=tmpconn->next_stream) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->_base.marked_for_close) {
|
||||
log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
}
|
||||
@ -452,7 +453,7 @@ relay_header_unpack(relay_header_t *dest, const char *src)
|
||||
* return -1. Else return 0.
|
||||
*/
|
||||
int
|
||||
connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
|
||||
connection_edge_send_command(edge_connection_t *fromconn, circuit_t *circ,
|
||||
int relay_command, const char *payload,
|
||||
size_t payload_len, crypt_path_t *cpath_layer)
|
||||
{
|
||||
@ -461,22 +462,22 @@ connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
|
||||
int cell_direction;
|
||||
/* XXXX NM Split this function into a separate versions per circuit type? */
|
||||
|
||||
if (fromconn && fromconn->marked_for_close) {
|
||||
if (fromconn && fromconn->_base.marked_for_close) {
|
||||
log_warn(LD_BUG,
|
||||
"Bug: called on conn that's already marked for close at %s:%d.",
|
||||
fromconn->marked_for_close_file, fromconn->marked_for_close);
|
||||
fromconn->_base.marked_for_close_file, fromconn->_base.marked_for_close);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!circ) {
|
||||
tor_assert(fromconn);
|
||||
if (fromconn->type == CONN_TYPE_AP) {
|
||||
if (fromconn->_base.type == CONN_TYPE_AP) {
|
||||
log_info(LD_APP,"no circ. Closing conn.");
|
||||
connection_mark_unattached_ap(fromconn, END_STREAM_REASON_INTERNAL);
|
||||
} else {
|
||||
log_info(LD_EXIT,"no circ. Closing conn.");
|
||||
fromconn->has_sent_end = 1; /* no circ to send to */
|
||||
connection_mark_for_close(fromconn);
|
||||
fromconn->_base.edge_has_sent_end = 1; /* no circ to send to */
|
||||
connection_mark_for_close(TO_CONN(fromconn));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -665,7 +666,7 @@ edge_reason_is_retriable(int reason)
|
||||
static int
|
||||
connection_edge_process_end_not_open(
|
||||
relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
|
||||
connection_t *conn, crypt_path_t *layer_hint)
|
||||
edge_connection_t *conn, crypt_path_t *layer_hint)
|
||||
{
|
||||
struct in_addr in;
|
||||
routerinfo_t *exitrouter;
|
||||
@ -673,7 +674,7 @@ connection_edge_process_end_not_open(
|
||||
(void) layer_hint; /* unused */
|
||||
|
||||
if (rh->length > 0 && edge_reason_is_retriable(reason) &&
|
||||
conn->type == CONN_TYPE_AP) {
|
||||
conn->_base.type == CONN_TYPE_AP) {
|
||||
log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
|
||||
safe_str(conn->socks_request->address),
|
||||
connection_edge_end_reason_str(reason));
|
||||
@ -775,12 +776,12 @@ connection_edge_process_end_not_open(
|
||||
log_info(LD_APP,
|
||||
"Edge got end (%s) before we're connected. Marking for close.",
|
||||
connection_edge_end_reason_str(rh->length > 0 ? reason : -1));
|
||||
if (conn->type == CONN_TYPE_AP) {
|
||||
if (conn->_base.type == CONN_TYPE_AP) {
|
||||
circuit_log_path(LOG_INFO,LD_APP,circ);
|
||||
connection_mark_unattached_ap(conn, reason);
|
||||
} else {
|
||||
conn->has_sent_end = 1; /* we just got an 'end', don't need to send one */
|
||||
connection_mark_for_close(conn);
|
||||
conn->_base.edge_has_sent_end = 1; /* we just got an 'end', don't need to send one */
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -795,7 +796,7 @@ connection_edge_process_end_not_open(
|
||||
static int
|
||||
connection_edge_process_relay_cell_not_open(
|
||||
relay_header_t *rh, cell_t *cell, circuit_t *circ,
|
||||
connection_t *conn, crypt_path_t *layer_hint)
|
||||
edge_connection_t *conn, crypt_path_t *layer_hint)
|
||||
{
|
||||
if (rh->command == RELAY_COMMAND_END) {
|
||||
if (CIRCUIT_IS_ORIGIN(circ))
|
||||
@ -806,17 +807,17 @@ connection_edge_process_relay_cell_not_open(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) {
|
||||
if (conn->_base.type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) {
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
if (conn->state != AP_CONN_STATE_CONNECT_WAIT) {
|
||||
if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) {
|
||||
log_warn(LD_APP,"Got 'connected' while not in state connect_wait. "
|
||||
"Dropping.");
|
||||
return 0;
|
||||
}
|
||||
// log_fn(LOG_INFO,"Connected! Notifying application.");
|
||||
conn->state = AP_CONN_STATE_OPEN;
|
||||
conn->_base.state = AP_CONN_STATE_OPEN;
|
||||
log_info(LD_APP,"'connected' received after %d seconds.",
|
||||
(int)(time(NULL) - conn->timestamp_lastread));
|
||||
(int)(time(NULL) - conn->_base.timestamp_lastread));
|
||||
if (rh->length >= 4) {
|
||||
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE));
|
||||
int ttl;
|
||||
@ -840,15 +841,15 @@ connection_edge_process_relay_cell_not_open(
|
||||
/* handle anything that might have queued */
|
||||
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
|
||||
/* (We already sent an end cell if possible) */
|
||||
connection_mark_for_close(conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_RESOLVED) {
|
||||
if (conn->_base.type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_RESOLVED) {
|
||||
int ttl;
|
||||
int answer_len;
|
||||
if (conn->state != AP_CONN_STATE_RESOLVE_WAIT) {
|
||||
if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
|
||||
log_warn(LD_APP,"Got a 'resolved' cell while not in state resolve_wait. "
|
||||
"Dropping.");
|
||||
return 0;
|
||||
@ -877,8 +878,8 @@ connection_edge_process_relay_cell_not_open(
|
||||
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Got an unexpected relay command %d, in state %d (%s). Dropping.",
|
||||
rh->command, conn->state,
|
||||
conn_state_to_string(conn->type, conn->state));
|
||||
rh->command, conn->_base.state,
|
||||
conn_state_to_string(conn->_base.type, conn->_base.state));
|
||||
return 0; /* for forward compatibility, don't kill the circuit */
|
||||
// connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL,
|
||||
// conn->cpath_layer);
|
||||
@ -897,7 +898,7 @@ connection_edge_process_relay_cell_not_open(
|
||||
*/
|
||||
static int
|
||||
connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
connection_t *conn,
|
||||
edge_connection_t *conn,
|
||||
crypt_path_t *layer_hint)
|
||||
{
|
||||
static int num_seen=0;
|
||||
@ -922,7 +923,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
/* either conn is NULL, in which case we've got a control cell, or else
|
||||
* conn points to the recognized stream. */
|
||||
|
||||
if (conn && !connection_state_is_open(conn))
|
||||
if (conn && !connection_state_is_open(TO_CONN(conn)))
|
||||
return connection_edge_process_relay_cell_not_open(
|
||||
&rh, cell, circ, conn, layer_hint);
|
||||
|
||||
@ -950,7 +951,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
"(relay data) circ deliver_window below 0. Killing.");
|
||||
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL,
|
||||
conn->cpath_layer);
|
||||
connection_mark_for_close(conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return -END_CIRC_REASON_TORPROTOCOL;
|
||||
}
|
||||
log_debug(domain,"circ deliver_window now %d.", layer_hint ?
|
||||
@ -971,7 +972,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
|
||||
stats_n_data_bytes_received += rh.length;
|
||||
connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE,
|
||||
rh.length, conn);
|
||||
rh.length, TO_CONN(conn));
|
||||
connection_edge_consider_sending_sendme(conn);
|
||||
return 0;
|
||||
case RELAY_COMMAND_END:
|
||||
@ -983,7 +984,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
}
|
||||
/* XXX add to this log_fn the exit node's nickname? */
|
||||
log_info(domain,"%d: end cell (%s) for stream %d. Removing stream.",
|
||||
conn->s,
|
||||
conn->_base.s,
|
||||
connection_edge_end_reason_str(rh.length > 0 ?
|
||||
*(char *)(cell->payload+RELAY_HEADER_SIZE) : -1),
|
||||
conn->stream_id);
|
||||
@ -991,12 +992,12 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
log_warn(LD_BUG,
|
||||
"Bug: open stream hasn't sent socks answer yet? Closing.");
|
||||
/* We just *got* an end; no reason to send one. */
|
||||
conn->has_sent_end = 1;
|
||||
if (!conn->marked_for_close) {
|
||||
conn->_base.edge_has_sent_end = 1;
|
||||
if (!conn->_base.marked_for_close) {
|
||||
/* only mark it if not already marked. it's possible to
|
||||
* get the 'end' right around when the client hangs up on us. */
|
||||
connection_mark_for_close(conn);
|
||||
conn->hold_open_until_flushed = 1;
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
conn->_base.hold_open_until_flushed = 1;
|
||||
}
|
||||
return 0;
|
||||
case RELAY_COMMAND_EXTEND:
|
||||
@ -1076,11 +1077,11 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
conn->package_window += STREAMWINDOW_INCREMENT;
|
||||
log_debug(domain,"stream-level sendme, packagewindow now %d.",
|
||||
conn->package_window);
|
||||
connection_start_reading(conn);
|
||||
connection_start_reading(TO_CONN(conn));
|
||||
/* handle whatever might still be on the inbuf */
|
||||
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
|
||||
/* (We already sent an end cell if possible) */
|
||||
connection_mark_for_close(conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
@ -1139,7 +1140,7 @@ uint64_t stats_n_data_bytes_received = 0;
|
||||
* be marked for close, else return 0.
|
||||
*/
|
||||
int
|
||||
connection_edge_package_raw_inbuf(connection_t *conn, int package_partial)
|
||||
connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial)
|
||||
{
|
||||
size_t amount_to_process, length;
|
||||
char payload[CELL_PAYLOAD_SIZE];
|
||||
@ -1147,11 +1148,11 @@ connection_edge_package_raw_inbuf(connection_t *conn, int package_partial)
|
||||
unsigned domain = conn->cpath_layer ? LD_APP : LD_EXIT;
|
||||
|
||||
tor_assert(conn);
|
||||
tor_assert(!connection_speaks_cells(conn));
|
||||
if (conn->marked_for_close) {
|
||||
|
||||
if (conn->_base.marked_for_close) {
|
||||
log_warn(LD_BUG,
|
||||
"Bug: called on conn that's already marked for close at %s:%d.",
|
||||
conn->marked_for_close_file, conn->marked_for_close);
|
||||
conn->_base.marked_for_close_file, conn->_base.marked_for_close);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1169,11 +1170,11 @@ repeat_connection_edge_package_raw_inbuf:
|
||||
if (conn->package_window <= 0) {
|
||||
log_info(domain,"called with package_window %d. Skipping.",
|
||||
conn->package_window);
|
||||
connection_stop_reading(conn);
|
||||
connection_stop_reading(TO_CONN(conn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
amount_to_process = buf_datalen(conn->inbuf);
|
||||
amount_to_process = buf_datalen(conn->_base.inbuf);
|
||||
|
||||
if (!amount_to_process)
|
||||
return 0;
|
||||
@ -1189,10 +1190,10 @@ repeat_connection_edge_package_raw_inbuf:
|
||||
stats_n_data_bytes_packaged += length;
|
||||
stats_n_data_cells_packaged += 1;
|
||||
|
||||
connection_fetch_from_buf(payload, length, conn);
|
||||
connection_fetch_from_buf(payload, length, TO_CONN(conn));
|
||||
|
||||
log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->s,
|
||||
(int)length, (int)buf_datalen(conn->inbuf));
|
||||
log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->_base.s,
|
||||
(int)length, (int)buf_datalen(conn->_base.inbuf));
|
||||
|
||||
if (connection_edge_send_command(conn, circ, RELAY_COMMAND_DATA,
|
||||
payload, length, conn->cpath_layer) < 0)
|
||||
@ -1208,7 +1209,7 @@ repeat_connection_edge_package_raw_inbuf:
|
||||
}
|
||||
|
||||
if (--conn->package_window <= 0) { /* is it 0 after decrement? */
|
||||
connection_stop_reading(conn);
|
||||
connection_stop_reading(TO_CONN(conn));
|
||||
log_debug(domain,"conn->package_window reached 0.");
|
||||
circuit_consider_stop_edge_reading(circ, conn->cpath_layer);
|
||||
return 0; /* don't process the inbuf any more */
|
||||
@ -1226,11 +1227,11 @@ repeat_connection_edge_package_raw_inbuf:
|
||||
* low, send back a suitable number of stream-level sendme cells.
|
||||
*/
|
||||
void
|
||||
connection_edge_consider_sending_sendme(connection_t *conn)
|
||||
connection_edge_consider_sending_sendme(edge_connection_t *conn)
|
||||
{
|
||||
circuit_t *circ;
|
||||
|
||||
if (connection_outbuf_too_full(conn))
|
||||
if (connection_outbuf_too_full(TO_CONN(conn)))
|
||||
return;
|
||||
|
||||
circ = circuit_get_by_edge_conn(conn);
|
||||
@ -1244,7 +1245,7 @@ connection_edge_consider_sending_sendme(connection_t *conn)
|
||||
while (conn->deliver_window < STREAMWINDOW_START - STREAMWINDOW_INCREMENT) {
|
||||
log_debug(conn->cpath_layer?LD_APP:LD_EXIT,
|
||||
"Outbuf %d, Queueing stream sendme.",
|
||||
(int)conn->outbuf_flushlen);
|
||||
(int)conn->_base.outbuf_flushlen);
|
||||
conn->deliver_window += STREAMWINDOW_INCREMENT;
|
||||
if (connection_edge_send_command(conn, circ, RELAY_COMMAND_SENDME,
|
||||
NULL, 0, conn->cpath_layer) < 0) {
|
||||
@ -1278,21 +1279,21 @@ circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
|
||||
* of a linked list of edge streams that should each be considered.
|
||||
*/
|
||||
static int
|
||||
circuit_resume_edge_reading_helper(connection_t *conn,
|
||||
circuit_resume_edge_reading_helper(edge_connection_t *conn,
|
||||
circuit_t *circ,
|
||||
crypt_path_t *layer_hint)
|
||||
{
|
||||
for ( ; conn; conn=conn->next_stream) {
|
||||
if (conn->marked_for_close)
|
||||
if (conn->_base.marked_for_close)
|
||||
continue;
|
||||
if ((!layer_hint && conn->package_window > 0) ||
|
||||
(layer_hint && conn->package_window > 0 &&
|
||||
conn->cpath_layer == layer_hint)) {
|
||||
connection_start_reading(conn);
|
||||
connection_start_reading(TO_CONN(conn));
|
||||
/* handle whatever might still be on the inbuf */
|
||||
if (connection_edge_package_raw_inbuf(conn, 1)<0) {
|
||||
/* (We already sent an end cell if possible) */
|
||||
connection_mark_for_close(conn);
|
||||
connection_mark_for_close(TO_CONN(conn));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1315,7 +1316,7 @@ circuit_resume_edge_reading_helper(connection_t *conn,
|
||||
static int
|
||||
circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
|
||||
{
|
||||
connection_t *conn = NULL;
|
||||
edge_connection_t *conn = NULL;
|
||||
unsigned domain = layer_hint ? LD_APP : LD_EXIT;
|
||||
|
||||
if (!layer_hint) {
|
||||
@ -1325,7 +1326,7 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
|
||||
if (circ->package_window <= 0) {
|
||||
log_debug(domain,"yes, not-at-origin. stopped.");
|
||||
for (conn = or_circ->n_streams; conn; conn=conn->next_stream)
|
||||
connection_stop_reading(conn);
|
||||
connection_stop_reading(TO_CONN(conn));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -1344,7 +1345,7 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
|
||||
for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn;
|
||||
conn=conn->next_stream)
|
||||
if (conn->cpath_layer == layer_hint)
|
||||
connection_stop_reading(conn);
|
||||
connection_stop_reading(TO_CONN(conn));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user