summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2006-07-23 07:37:35 +0000
committerNick Mathewson <nickm@torproject.org>2006-07-23 07:37:35 +0000
commit7239262f71cfe829ff7c50b1d971534f0cda1dc4 (patch)
tree5d5d5d0aea6b5cc250a421a3a2ad43b3ad609a93
parent6d2eb77555bee021ef27bf40101f8eb3fc931357 (diff)
downloadtor-7239262f71cfe829ff7c50b1d971534f0cda1dc4.tar.gz
tor-7239262f71cfe829ff7c50b1d971534f0cda1dc4.zip
Don't tell anybody, but we're going OO here. This patch splits
circuit_t into origin_circuit_t and or_circuit_t. I fixed some segaults; there may be more. We still need to move more rendezvous stuff into subtypes. This is a trial run for splitting up connection_t; if the approach is insane, please say so soon so we can do something smarter. Also, this discards the old HALF_OPEN code, which nobody seems to want. svn:r6817
-rw-r--r--src/or/circuitbuild.c170
-rw-r--r--src/or/circuitlist.c491
-rw-r--r--src/or/circuituse.c231
-rw-r--r--src/or/command.c39
-rw-r--r--src/or/connection_edge.c79
-rw-r--r--src/or/control.c41
-rw-r--r--src/or/cpuworker.c14
-rw-r--r--src/or/dns.c5
-rw-r--r--src/or/onion.c12
-rw-r--r--src/or/or.h253
-rw-r--r--src/or/relay.c160
-rw-r--r--src/or/rendclient.c99
-rw-r--r--src/or/rendcommon.c25
-rw-r--r--src/or/rendmid.c69
-rw-r--r--src/or/rendservice.c145
15 files changed, 1016 insertions, 817 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 85d2759f83..e58e253f48 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -43,7 +43,7 @@ static int entry_guards_dirty = 0;
static int circuit_deliver_create_cell(circuit_t *circ,
uint8_t cell_type, char *payload);
-static int onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit);
+static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(uint8_t purpose, crypt_path_t **head_ptr,
cpath_build_state_t *state);
@@ -95,14 +95,13 @@ get_unique_circ_id_by_conn(connection_t *conn)
* a more verbose format using spaces.
*/
char *
-circuit_list_path(circuit_t *circ, int verbose)
+circuit_list_path(origin_circuit_t *circ, int verbose)
{
crypt_path_t *hop;
smartlist_t *elements;
const char *states[] = {"closed", "waiting for keys", "open"};
char buf[128];
char *s;
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
elements = smartlist_create();
@@ -112,8 +111,8 @@ circuit_list_path(circuit_t *circ, int verbose)
circ->build_state->is_internal ? "internal" : "exit",
circ->build_state->need_uptime ? " (high-uptime)" : "",
circ->build_state->desired_path_len,
- circ->state == CIRCUIT_STATE_OPEN ? "" : ", exit ",
- circ->state == CIRCUIT_STATE_OPEN ? "" :
+ circ->_base.state == CIRCUIT_STATE_OPEN ? "" : ", exit ",
+ circ->_base.state == CIRCUIT_STATE_OPEN ? "" :
(nickname?nickname:"*unnamed*"));
smartlist_add(elements, tor_strdup(buf));
}
@@ -152,7 +151,7 @@ circuit_list_path(circuit_t *circ, int verbose)
* exit point.
*/
void
-circuit_log_path(int severity, unsigned int domain, circuit_t *circ)
+circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
{
char *s = circuit_list_path(circ,1);
log(severity,domain,"%s",s);
@@ -165,7 +164,7 @@ circuit_log_path(int severity, unsigned int domain, circuit_t *circ)
* unable to extend.
*/
void
-circuit_rep_hist_note_result(circuit_t *circ)
+circuit_rep_hist_note_result(origin_circuit_t *circ)
{
crypt_path_t *hop;
char *prev_digest = NULL;
@@ -206,74 +205,14 @@ circuit_rep_hist_note_result(circuit_t *circ)
} while (hop!=circ->cpath);
}
-/** A helper function for circuit_dump_by_conn() below. Log a bunch
- * of information about circuit <b>circ</b>.
- */
-static void
-circuit_dump_details(int severity, circuit_t *circ, int poll_index,
- const char *type, int this_circid, int other_circid)
-{
- log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), "
- "state %d (%s), born %d:",
- poll_index, type, this_circid, other_circid, circ->state,
- circuit_state_to_string(circ->state), (int)circ->timestamp_created);
- if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
- circuit_log_path(severity, LD_CIRC, circ);
- }
-}
-
-/** Log, at severity <b>severity</b>, information about each circuit
- * that is connected to <b>conn</b>.
- */
-void
-circuit_dump_by_conn(connection_t *conn, int severity)
-{
- circuit_t *circ;
- connection_t *tmpconn;
-
- for (circ=global_circuitlist;circ;circ = circ->next) {
- if (circ->marked_for_close)
- continue;
- if (circ->p_conn == conn)
- circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
- circ->p_circ_id, circ->n_circ_id);
- for (tmpconn=circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
- if (tmpconn == conn) {
- circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
- circ->p_circ_id, circ->n_circ_id);
- }
- }
- if (circ->n_conn == conn)
- circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
- circ->n_circ_id, circ->p_circ_id);
- for (tmpconn=circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
- if (tmpconn == conn) {
- circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
- circ->n_circ_id, circ->p_circ_id);
- }
- }
- 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)) {
- circuit_dump_details(severity, circ, conn->poll_index,
- (circ->state == CIRCUIT_STATE_OPEN &&
- !CIRCUIT_IS_ORIGIN(circ)) ?
- "Endpoint" : "Pending",
- circ->n_circ_id, circ->p_circ_id);
- }
- }
-}
-
/** Pick all the entries in our cpath. Stop and return 0 when we're
* happy, or return -1 if an error occurs. */
static int
-onion_populate_cpath(circuit_t *circ)
+onion_populate_cpath(origin_circuit_t *circ)
{
int r;
again:
- r = onion_extend_cpath(circ->purpose, &circ->cpath, circ->build_state);
-// || !CIRCUIT_IS_ORIGIN(circ)) { // wtf? -rd
+ r = onion_extend_cpath(circ->_base.purpose, &circ->cpath, circ->build_state);
if (r < 0) {
log_info(LD_CIRC,"Generating cpath hop failed.");
return -1;
@@ -283,19 +222,20 @@ again:
return 0; /* if r == 1 */
}
-/** Create and return a new circuit. Initialize its purpose and
+/** Create and return a new origin circuit. Initialize its purpose and
* build-state based on our arguments. */
-circuit_t *
-circuit_init(uint8_t purpose, int need_uptime, int need_capacity, int internal)
+origin_circuit_t *
+origin_circuit_init(uint8_t purpose, int need_uptime, int need_capacity,
+ int internal)
{
/* sets circ->p_circ_id and circ->p_conn */
- circuit_t *circ = circuit_new(0, NULL);
- circuit_set_state(circ, CIRCUIT_STATE_OR_WAIT);
+ origin_circuit_t *circ = origin_circuit_new();
+ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OR_WAIT);
circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
circ->build_state->need_uptime = need_uptime;
circ->build_state->need_capacity = need_capacity;
circ->build_state->is_internal = internal;
- circ->purpose = purpose;
+ circ->_base.purpose = purpose;
return circ;
}
@@ -306,24 +246,24 @@ circuit_init(uint8_t purpose, int need_uptime, int need_capacity, int internal)
* Also launch a connection to the first OR in the chosen path, if
* it's not open already.
*/
-circuit_t *
+origin_circuit_t *
circuit_establish_circuit(uint8_t purpose, extend_info_t *info,
int need_uptime, int need_capacity, int internal)
{
- circuit_t *circ;
+ origin_circuit_t *circ;
- circ = circuit_init(purpose, need_uptime, need_capacity, internal);
+ circ = origin_circuit_init(purpose, need_uptime, need_capacity, internal);
if (onion_pick_cpath_exit(circ, info) < 0 ||
onion_populate_cpath(circ) < 0) {
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return NULL;
}
control_event_circuit_status(circ, CIRC_EVENT_LAUNCHED);
if (circuit_handle_first_hop(circ) < 0) {
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return NULL;
}
return circ;
@@ -334,7 +274,7 @@ circuit_establish_circuit(uint8_t purpose, extend_info_t *info,
* it. If we're already connected, then send the 'create' cell.
* Return 0 for ok, -1 if circ should be marked-for-close. */
int
-circuit_handle_first_hop(circuit_t *circ)
+circuit_handle_first_hop(origin_circuit_t *circ)
{
crypt_path_t *firsthop;
connection_t *n_conn;
@@ -351,7 +291,7 @@ circuit_handle_first_hop(circuit_t *circ)
log_debug(LD_CIRC,"Looking for firsthop '%s:%u'",tmpbuf,
firsthop->extend_info->port);
/* imprint the circuit with its future n_conn->id */
- memcpy(circ->n_conn_id_digest, firsthop->extend_info->identity_digest,
+ memcpy(circ->_base.n_conn_id_digest, firsthop->extend_info->identity_digest,
DIGEST_LEN);
n_conn = connection_or_get_by_identity_digest(
firsthop->extend_info->identity_digest);
@@ -363,8 +303,8 @@ circuit_handle_first_hop(circuit_t *circ)
router_digest_version_as_new_as(firsthop->extend_info->identity_digest,
"0.1.1.9-alpha-cvs"))) {
/* not currently connected */
- circ->n_addr = firsthop->extend_info->addr;
- circ->n_port = firsthop->extend_info->port;
+ 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 */
n_conn = connection_or_connect(firsthop->extend_info->addr,
@@ -383,9 +323,9 @@ circuit_handle_first_hop(circuit_t *circ)
*/
return 0;
} else { /* it's already open. use it. */
- circ->n_addr = n_conn->addr;
- circ->n_port = n_conn->port;
- circ->n_conn = n_conn;
+ circ->_base.n_addr = n_conn->addr;
+ circ->_base.n_port = n_conn->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) {
log_info(LD_CIRC,"circuit_send_next_onion_skin failed.");
@@ -433,7 +373,7 @@ circuit_n_conn_done(connection_t *or_conn, int status)
* set_circid_orconn here. */
circ->n_conn = or_conn;
if (CIRCUIT_IS_ORIGIN(circ)) {
- if (circuit_send_next_onion_skin(circ) < 0) {
+ if (circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)) < 0) {
log_info(LD_CIRC,
"send_next_onion_skin failed; circuit marked for closing.");
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
@@ -471,7 +411,8 @@ circuit_n_conn_done(connection_t *or_conn, int status)
* Return -1 if we failed to find a suitable circid, else return 0.
*/
static int
-circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, char *payload)
+circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
+ char *payload)
{
cell_t cell;
uint16_t id;
@@ -488,7 +429,7 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, char *payload)
return -1;
}
log_debug(LD_CIRC,"Chosen circID %u.", id);
- circuit_set_circid_orconn(circ, id, circ->n_conn, N_CONN_CHANGED);
+ circuit_set_n_circid_orconn(circ, id, circ->n_conn);
memset(&cell, 0, sizeof(cell_t));
cell.command = cell_type;
@@ -552,7 +493,7 @@ extern int has_completed_circuit;
* Return -reason if we want to tear down circ, else return 0.
*/
int
-circuit_send_next_onion_skin(circuit_t *circ)
+circuit_send_next_onion_skin(origin_circuit_t *circ)
{
crypt_path_t *hop;
routerinfo_t *router;
@@ -561,14 +502,13 @@ circuit_send_next_onion_skin(circuit_t *circ)
size_t payload_len;
tor_assert(circ);
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
if (circ->cpath->state == CPATH_STATE_CLOSED) {
int fast;
uint8_t cell_type;
log_debug(LD_CIRC,"First skin; sending create cell.");
- router = router_get_by_digest(circ->n_conn->identity_digest);
+ router = router_get_by_digest(circ->_base.n_conn->identity_digest);
fast = should_use_create_fast_for_router(router);
if (! fast) {
/* We are an OR, or we are connecting to an old Tor: we should
@@ -593,22 +533,22 @@ circuit_send_next_onion_skin(circuit_t *circ)
sizeof(circ->cpath->fast_handshake_state));
}
- if (circuit_deliver_create_cell(circ, cell_type, payload) < 0)
+ if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload) < 0)
return - END_CIRC_REASON_RESOURCELIMIT;
circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
- circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
+ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
log_info(LD_CIRC,"First hop: finished sending %s cell to '%s'",
fast ? "CREATE_FAST" : "CREATE",
router ? router->nickname : "<unnamed>");
} else {
tor_assert(circ->cpath->state == CPATH_STATE_OPEN);
- tor_assert(circ->state == CIRCUIT_STATE_BUILDING);
+ tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING);
log_debug(LD_CIRC,"starting to send subsequent skin.");
hop = onion_next_hop_in_cpath(circ->cpath);
if (!hop) {
/* done building the circuit. whew. */
- circuit_set_state(circ, CIRCUIT_STATE_OPEN);
+ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
log_info(LD_CIRC,"circuit built!");
circuit_reset_failure_count(0);
if (!has_completed_circuit) {
@@ -645,7 +585,8 @@ circuit_send_next_onion_skin(circuit_t *circ)
log_debug(LD_CIRC,"Sending extend relay cell.");
/* send it to hop->prev, because it will transfer
* it to a create cell and then send to hop */
- if (connection_edge_send_command(NULL, circ, RELAY_COMMAND_EXTEND,
+ if (connection_edge_send_command(NULL, TO_CIRCUIT(circ),
+ RELAY_COMMAND_EXTEND,
payload, payload_len, hop->prev) < 0)
return 0; /* circuit is closed */
@@ -820,12 +761,12 @@ circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data, int reverse)
* Return - reason if we want to mark circ for close, else return 0.
*/
int
-circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply)
+circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
+ char *reply)
{
char keys[CPATH_KEY_MATERIAL_LEN];
crypt_path_t *hop;
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS)
hop = circ->cpath;
else {
@@ -883,20 +824,19 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply)
* just give up: for circ to close, and return 0.
*/
int
-circuit_truncated(circuit_t *circ, crypt_path_t *layer)
+circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer)
{
// crypt_path_t *victim;
// connection_t *stream;
tor_assert(circ);
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
tor_assert(layer);
/* XXX Since we don't ask for truncates currently, getting a truncated
* means that a connection broke or an extend failed. For now,
* just give up.
*/
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return 0;
#if 0
@@ -929,7 +869,8 @@ circuit_truncated(circuit_t *circ, crypt_path_t *layer)
* cell back.
*/
int
-onionskin_answer(circuit_t *circ, uint8_t cell_type, char *payload, char *keys)
+onionskin_answer(or_circuit_t *circ, uint8_t cell_type, char *payload,
+ char *keys)
{
cell_t cell;
crypt_path_t *tmp_cpath;
@@ -941,7 +882,7 @@ onionskin_answer(circuit_t *circ, uint8_t cell_type, char *payload, char *keys)
cell.command = cell_type;
cell.circ_id = circ->p_circ_id;
- circuit_set_state(circ, CIRCUIT_STATE_OPEN);
+ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
memcpy(cell.payload, payload,
cell_type == CELL_CREATED ? ONIONSKIN_REPLY_LEN : DIGEST_LEN*2);
@@ -1338,13 +1279,13 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
* router (or use <b>exit</b> if provided). Store these in the
* cpath. Return 0 if ok, -1 if circuit should be closed. */
static int
-onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit)
+onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
{
cpath_build_state_t *state = circ->build_state;
routerlist_t *rl = router_get_routerlist();
int r;
- r = new_route_len(get_options()->PathlenCoinWeight, circ->purpose,
+ r = new_route_len(get_options()->PathlenCoinWeight, circ->_base.purpose,
exit, rl->routers);
if (r < 1) /* must be at least 1 */
return -1;
@@ -1355,8 +1296,8 @@ onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit)
exit = extend_info_dup(exit);
} else { /* we have to decide one */
routerinfo_t *router =
- choose_good_exit_server(circ->purpose, rl, state->need_uptime,
- state->need_capacity, state->is_internal);
+ choose_good_exit_server(circ->_base.purpose, rl, state->need_uptime,
+ state->need_capacity, state->is_internal);
if (!router) {
log_warn(LD_CIRC,"failed to choose an exit server");
return -1;
@@ -1372,11 +1313,11 @@ onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit)
* the caller will do this if it wants to.
*/
int
-circuit_append_new_exit(circuit_t *circ, extend_info_t *info)
+circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info)
{
cpath_build_state_t *state;
tor_assert(info);
- tor_assert(circ && CIRCUIT_IS_ORIGIN(circ));
+ tor_assert(circ);
state = circ->build_state;
tor_assert(state);
@@ -1394,15 +1335,14 @@ circuit_append_new_exit(circuit_t *circ, extend_info_t *info)
* send the next extend cell to begin connecting to that hop.
*/
int
-circuit_extend_to_new_exit(circuit_t *circ, extend_info_t *info)
+circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info)
{
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
circuit_append_new_exit(circ, info);
- circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
+ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
if (circuit_send_next_onion_skin(circ)<0) {
log_warn(LD_CIRC, "Couldn't extend circuit to new point '%s'.",
info->nickname);
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return -1;
}
return 0;
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 73513c4030..69e611dd98 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -68,35 +68,14 @@ HT_GENERATE(orconn_circid_map, orconn_circid_circuit_map_t, node,
*/
orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL;
-/** Set the p_conn or n_conn field of a circuit <b>circ</b>, along
- * with the corresponding circuit ID, and add the circuit as appropriate
- * to the (orconn,id)-\>circuit map. */
-void
-circuit_set_circid_orconn(circuit_t *circ, uint16_t id,
- connection_t *conn,
- enum which_conn_changed_t which)
+static void
+circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
+ connection_t *conn,
+ uint16_t old_id, connection_t *old_conn)
{
- uint16_t old_id;
- connection_t *old_conn;
orconn_circid_circuit_map_t search;
orconn_circid_circuit_map_t *found;
- tor_assert(!conn || conn->type == CONN_TYPE_OR);
-
- if (which == P_CONN_CHANGED) {
- old_id = circ->p_circ_id;
- old_conn = circ->p_conn;
- circ->p_circ_id = id;
- circ->p_conn = conn;
- } else {
- old_id = circ->n_circ_id;
- old_conn = circ->n_conn;
- circ->n_circ_id = id;
- circ->n_conn = conn;
- }
- if (conn == old_conn && old_id == id)
- return;
-
if (_last_circid_orconn_ent &&
((old_id == _last_circid_orconn_ent->circ_id &&
old_conn == _last_circid_orconn_ent->or_conn) ||
@@ -135,6 +114,47 @@ circuit_set_circid_orconn(circuit_t *circ, uint16_t id,
++conn->n_circuits;
}
+/** Set the p_conn field of a circuit <b>circ</b>, along
+ * with the corresponding circuit ID, and add the circuit as appropriate
+ * to the (orconn,id)-\>circuit map. */
+void
+circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
+ connection_t *conn)
+{
+ uint16_t old_id;
+ connection_t *old_conn;
+
+ old_id = circ->p_circ_id;
+ old_conn = circ->p_conn;
+ circ->p_circ_id = id;
+ circ->p_conn = conn;
+
+ if (id == old_id && conn == old_conn)
+ return;
+ circuit_set_circid_orconn_helper(TO_CIRCUIT(circ), id, conn,
+ old_id, old_conn);
+}
+
+/** Set the n_conn field of a circuit <b>circ</b>, along
+ * with the corresponding circuit ID, and add the circuit as appropriate
+ * to the (orconn,id)-\>circuit map. */
+void
+circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
+ connection_t *conn)
+{
+ uint16_t old_id;
+ connection_t *old_conn;
+
+ old_id = circ->n_circ_id;
+ old_conn = circ->n_conn;
+ circ->n_circ_id = id;
+ circ->n_conn = conn;
+
+ if (id == old_id && conn == old_conn)
+ return;
+ circuit_set_circid_orconn_helper(circ, id, conn, old_id, old_conn);
+}
+
/** Change the state of <b>circ</b> to <b>state</b>, adding it to or removing
* it from lists as appropriate. */
void
@@ -224,36 +244,53 @@ circuit_state_to_string(int state)
}
}
-/** Allocate space for a new circuit, initializing with <b>p_circ_id</b>
- * and <b>p_conn</b>. Add it to the global circuit list.
- */
-circuit_t *
-circuit_new(uint16_t p_circ_id, connection_t *p_conn)
+/* DOCDOC */
+static void
+init_circuit_base(circuit_t *circ)
{
- circuit_t *circ;
static uint32_t n_circuits_allocated = 1;
/* never zero, since a global ID of 0 is treated specially by the
* controller */
-
- circ = tor_malloc_zero(sizeof(circuit_t));
- circ->magic = CIRCUIT_MAGIC;
-
circ->timestamp_created = time(NULL);
- /* CircIDs */
- if (p_conn) {
- circuit_set_circid_orconn(circ, p_circ_id, p_conn, P_CONN_CHANGED);
- }
- /* circ->n_circ_id remains 0 because we haven't identified the next hop
- * yet */
-
circ->package_window = CIRCWINDOW_START;
circ->deliver_window = CIRCWINDOW_START;
-
- circ->next_stream_id = crypto_rand_int(1<<16);
circ->global_identifier = n_circuits_allocated++;
circuit_add(circ);
+}
+
+/** Allocate space for a new circuit, initializing with <b>p_circ_id</b>
+ * and <b>p_conn</b>. Add it to the global circuit list.
+ */
+origin_circuit_t *
+origin_circuit_new(void)
+{
+ origin_circuit_t *circ;
+
+ circ = tor_malloc_zero(sizeof(origin_circuit_t));
+ circ->_base.magic = ORIGIN_CIRCUIT_MAGIC;
+
+ circ->next_stream_id = crypto_rand_int(1<<16);
+
+ init_circuit_base(TO_CIRCUIT(circ));
+
+ return circ;
+}
+
+or_circuit_t *
+or_circuit_new(uint16_t p_circ_id, connection_t *p_conn)
+{
+ /* CircIDs */
+ or_circuit_t *circ;
+
+ circ = tor_malloc_zero(sizeof(or_circuit_t));
+ circ->_base.magic = OR_CIRCUIT_MAGIC;
+
+ if (p_conn)
+ circuit_set_p_circid_orconn(circ, p_circ_id, p_conn);
+
+ init_circuit_base(TO_CIRCUIT(circ));
return circ;
}
@@ -263,35 +300,53 @@ circuit_new(uint16_t p_circ_id, connection_t *p_conn)
static void
circuit_free(circuit_t *circ)
{
+ void *mem;
tor_assert(circ);
- tor_assert(circ->magic == CIRCUIT_MAGIC);
- if (circ->n_crypto)
- crypto_free_cipher_env(circ->n_crypto);
- if (circ->p_crypto)
- crypto_free_cipher_env(circ->p_crypto);
- if (circ->n_digest)
- crypto_free_digest_env(circ->n_digest);
- if (circ->p_digest)
- crypto_free_digest_env(circ->p_digest);
- if (circ->build_state) {
- if (circ->build_state->chosen_exit)
- extend_info_free(circ->build_state->chosen_exit);
- if (circ->build_state->pending_final_cpath)
- circuit_free_cpath_node(circ->build_state->pending_final_cpath);
- }
- tor_free(circ->build_state);
- tor_free(circ->onionskin);
- circuit_free_cpath(circ->cpath);
- if (circ->rend_splice) {
- tor_assert(circ->rend_splice->magic == CIRCUIT_MAGIC);
- circ->rend_splice->rend_splice = NULL;
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ mem = ocirc;
+ tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC);
+ if (ocirc->build_state) {
+ if (ocirc->build_state->chosen_exit)
+ extend_info_free(ocirc->build_state->chosen_exit);
+ if (ocirc->build_state->pending_final_cpath)
+ circuit_free_cpath_node(ocirc->build_state->pending_final_cpath);
+ }
+ tor_free(ocirc->build_state);
+
+ circuit_free_cpath(ocirc->cpath);
+
+ } else {
+ or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
+ mem = ocirc;
+ tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
+
+ if (ocirc->p_crypto)
+ crypto_free_cipher_env(ocirc->p_crypto);
+ if (ocirc->p_digest)
+ crypto_free_digest_env(ocirc->p_digest);
+ if (ocirc->n_crypto)
+ crypto_free_cipher_env(ocirc->n_crypto);
+ if (ocirc->n_digest)
+ crypto_free_digest_env(ocirc->n_digest);
+
+ if (ocirc->rend_splice) {
+ or_circuit_t *other = ocirc->rend_splice;
+ tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC);
+ other->rend_splice = NULL;
+ }
+
+ tor_free(circ->onionskin);
+
+ /* remove from map. */
+ circuit_set_p_circid_orconn(ocirc, 0, NULL);
}
+
/* Remove from map. */
- circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
- circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
+ circuit_set_n_circid_orconn(circ, 0, NULL);
memset(circ, 0xAA, sizeof(circuit_t)); /* poison memory */
- tor_free(circ);
+ tor_free(mem);
}
/** Deallocate space associated with the linked list <b>cpath</b>. */
@@ -321,11 +376,14 @@ circuit_free_all(void)
circuit_t *next;
while (global_circuitlist) {
next = global_circuitlist->next;
- while (global_circuitlist->resolving_streams) {
- connection_t *next;
- next = global_circuitlist->resolving_streams->next_stream;
- connection_free(global_circuitlist->resolving_streams);
- global_circuitlist->resolving_streams = next;
+ if (! CIRCUIT_IS_ORIGIN(global_circuitlist)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(global_circuitlist);
+ while (or_circ->resolving_streams) {
+ connection_t *next;
+ next = or_circ->resolving_streams->next_stream;
+ connection_free(or_circ->resolving_streams);
+ or_circ->resolving_streams = next;
+ }
}
circuit_free(global_circuitlist);
global_circuitlist = next;
@@ -358,6 +416,76 @@ circuit_free_cpath_node(crypt_path_t *victim)
tor_free(victim);
}
+/** A helper function for circuit_dump_by_conn() below. Log a bunch
+ * of information about circuit <b>circ</b>.
+ */
+static void
+circuit_dump_details(int severity, circuit_t *circ, int poll_index,
+ const char *type, int this_circid, int other_circid)
+{
+ log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), "
+ "state %d (%s), born %d:",
+ poll_index, type, this_circid, other_circid, circ->state,
+ circuit_state_to_string(circ->state), (int)circ->timestamp_created);
+ if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
+ circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ));
+ }
+}
+
+/** Log, at severity <b>severity</b>, information about each circuit
+ * that is connected to <b>conn</b>.
+ */
+void
+circuit_dump_by_conn(connection_t *conn, int severity)
+{
+ circuit_t *circ;
+ connection_t *tmpconn;
+
+ for (circ=global_circuitlist;circ;circ = circ->next) {
+ circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
+ if (circ->marked_for_close)
+ continue;
+
+ 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)
+ 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) {
+ circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
+ p_circ_id, n_circ_id);
+ }
+ }
+ }
+ if (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) {
+ circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
+ n_circ_id, p_circ_id);
+ }
+ }
+ }
+ 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)) {
+ circuit_dump_details(severity, circ, conn->poll_index,
+ (circ->state == CIRCUIT_STATE_OPEN &&
+ !CIRCUIT_IS_ORIGIN(circ)) ?
+ "Endpoint" : "Pending",
+ n_circ_id, p_circ_id);
+ }
+ }
+}
+
/** Return the circuit whose global ID is <b>id</b>, or NULL if no
* such circuit exists. */
circuit_t *
@@ -407,10 +535,13 @@ circuit_get_by_circid_orconn_impl(uint16_t circ_id, connection_t *conn)
{
circuit_t *circ;
for (circ=global_circuitlist;circ;circ = circ->next) {
- if (circ->p_conn == conn && circ->p_circ_id == circ_id) {
- log_warn(LD_BUG,
- "circuit matches p_conn, but not in hash table (Bug!)");
- return circ;
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ if (or_circ->p_conn == conn && or_circ->p_circ_id == circ_id) {
+ log_warn(LD_BUG,
+ "circuit matches p_conn, but not in hash table (Bug!)");
+ return circ;
+ }
}
if (circ->n_conn == conn && circ->n_circ_id == circ_id) {
log_warn(LD_BUG,
@@ -462,7 +593,9 @@ circuit_get_by_edge_conn(connection_t *conn)
tor_assert(CONN_IS_EDGE(conn));
circ = conn->on_circuit;
- tor_assert(!circ || circ->magic == CIRCUIT_MAGIC);
+ tor_assert(!circ ||
+ (CIRCUIT_IS_ORIGIN(circ) ? circ->magic == ORIGIN_CIRCUIT_MAGIC
+ : circ->magic == OR_CIRCUIT_MAGIC));
return circ;
}
@@ -476,14 +609,20 @@ circuit_unlink_all_from_or_conn(connection_t *conn, int reason)
{
circuit_t *circ;
for (circ = global_circuitlist; circ; circ = circ->next) {
- if (circ->n_conn == conn || circ->p_conn == conn) {
- if (circ->n_conn == conn)
- circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
- if (circ->p_conn == conn)
- circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
- if (!circ->marked_for_close)
- circuit_mark_for_close(circ, reason);
+ int mark = 0;
+ if (circ->n_conn == conn) {
+ circuit_set_n_circid_orconn(circ, 0, NULL);
+ mark = 1;
+ }
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ if (or_circ->p_conn == conn) {
+ circuit_set_p_circid_orconn(or_circ, 0, NULL);
+ mark = 1;
+ }
}
+ if (mark && !circ->marked_for_close)
+ circuit_mark_for_close(circ, reason);
}
}
@@ -536,7 +675,7 @@ circuit_get_next_by_pk_and_purpose(circuit_t *start,
/** Return the circuit waiting for a rendezvous with the provided cookie.
* Return NULL if no such circuit is found.
*/
-circuit_t *
+or_circuit_t *
circuit_get_rendezvous(const char *cookie)
{
circuit_t *circ;
@@ -544,7 +683,7 @@ circuit_get_rendezvous(const char *cookie)
if (! circ->marked_for_close &&
circ->purpose == CIRCUIT_PURPOSE_REND_POINT_WAITING &&
! memcmp(circ->rend_cookie, cookie, REND_COOKIE_LEN) )
- return circ;
+ return TO_OR_CIRCUIT(circ);
}
return NULL;
}
@@ -559,41 +698,43 @@ circuit_get_rendezvous(const char *cookie)
*
* Only return internal circuits if that is requested.
*/
-circuit_t *
+origin_circuit_t *
circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
int need_uptime,
int need_capacity, int internal)
{
- circuit_t *circ;
- circuit_t *best=NULL;
+ circuit_t *_circ;
+ origin_circuit_t *best=NULL;
log_debug(LD_CIRC,
"Hunting for a circ to cannibalize: purpose %d, uptime %d, "
"capacity %d, internal %d",
purpose, need_uptime, need_capacity, internal);
- for (circ=global_circuitlist; circ; circ = circ->next) {
- if (CIRCUIT_IS_ORIGIN(circ) &&
- circ->state == CIRCUIT_STATE_OPEN &&
- !circ->marked_for_close &&
- circ->purpose == purpose &&
- !circ->timestamp_dirty &&
- (!need_uptime || circ->build_state->need_uptime) &&
- (!need_capacity || circ->build_state->need_capacity) &&
- (internal == circ->build_state->is_internal)) {
- if (info) {
- /* need to make sure we don't duplicate hops */
- crypt_path_t *hop = circ->cpath;
- do {
- if (!memcmp(hop->extend_info->identity_digest,
- info->identity_digest, DIGEST_LEN))
- goto next;
- hop=hop->next;
- } while (hop!=circ->cpath);
- }
- if (!best || (best->build_state->need_uptime && !need_uptime))
- best = circ;
+ for (_circ=global_circuitlist; _circ; _circ = _circ->next) {
+ if (CIRCUIT_IS_ORIGIN(_circ) &&
+ _circ->state == CIRCUIT_STATE_OPEN &&
+ !_circ->marked_for_close &&
+ _circ->purpose == purpose &&
+ !_circ->timestamp_dirty) {
+ origin_circuit_t *circ = TO_ORIGIN_CIRCUIT(_circ);
+ if ((!need_uptime || circ->build_state->need_uptime) &&
+ (!need_capacity || circ->build_state->need_capacity) &&
+ (internal == circ->build_state->is_internal)) {
+ if (info) {
+ /* need to make sure we don't duplicate hops */
+ crypt_path_t *hop = circ->cpath;
+ do {
+ if (!memcmp(hop->extend_info->identity_digest,
+ info->identity_digest, DIGEST_LEN))
+ goto next;
+ hop=hop->next;
+ } while (hop!=circ->cpath);
+ }
+ if (!best || (best->build_state->need_uptime && !need_uptime))
+ best = circ;
next: ;
+ }
}
}
return best;
@@ -685,7 +826,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
}
if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
- onion_pending_remove(circ);
+ onion_pending_remove(TO_OR_CIRCUIT(circ));
}
/* If the circuit ever became OPEN, we sent it to the reputation history
* module then. If it isn't OPEN, we send it there now to remember which
@@ -693,60 +834,72 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
*/
if (circ->state != CIRCUIT_STATE_OPEN) {
if (CIRCUIT_IS_ORIGIN(circ)) {
- circuit_build_failed(circ); /* take actions if necessary */
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ circuit_build_failed(ocirc); /* take actions if necessary */
+ circuit_rep_hist_note_result(ocirc);
}
- circuit_rep_hist_note_result(circ);
}
if (circ->state == CIRCUIT_STATE_OR_WAIT) {
if (circuits_pending_or_conns)
smartlist_remove(circuits_pending_or_conns, circ);
}
if (CIRCUIT_IS_ORIGIN(circ)) {
- control_event_circuit_status(circ,
+ control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
(circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED);
}
if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
tor_assert(circ->state == CIRCUIT_STATE_OPEN);
- tor_assert(circ->build_state->chosen_exit);
+ tor_assert(ocirc->build_state->chosen_exit);
/* treat this like getting a nack from it */
log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). "
"Removing from descriptor.",
safe_str(circ->rend_query),
- safe_str(build_state_get_exit_nickname(circ->build_state)));
- rend_client_remove_intro_point(circ->build_state->chosen_exit,
+ safe_str(build_state_get_exit_nickname(ocirc->build_state)));
+ rend_client_remove_intro_point(ocirc->build_state->chosen_exit,
circ->rend_query);
}
-
if (circ->n_conn)
connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason);
- for (conn=circ->n_streams; conn; conn=conn->next_stream)
- connection_edge_destroy(circ->n_circ_id, conn);
- while (circ->resolving_streams) {
- conn = circ->resolving_streams;
- circ->resolving_streams = conn->next_stream;
- if (!conn->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);
+
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ 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) {
+ /* 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->on_circuit = NULL;
}
- conn->on_circuit = NULL;
+
+ if (or_circ->p_conn)
+ connection_or_send_destroy(or_circ->p_circ_id, or_circ->p_conn, reason);
+ } else {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ for (conn=ocirc->p_streams; conn; conn=conn->next_stream)
+ connection_edge_destroy(circ->n_circ_id, conn);
}
- if (circ->p_conn)
- connection_or_send_destroy(circ->p_circ_id, circ->p_conn, reason);
- for (conn=circ->p_streams; conn; conn=conn->next_stream)
- connection_edge_destroy(circ->p_circ_id, conn);
circ->marked_for_close = line;
circ->marked_for_close_file = file;
- if (circ->rend_splice) {
- if (!circ->rend_splice->marked_for_close) {
- /* do this after marking this circuit, to avoid infinite recursion. */
- circuit_mark_for_close(circ->rend_splice, reason);
+ if (! CIRCUIT_IS_ORIGIN(circ)) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ if (or_circ->rend_splice) {
+ if (!or_circ->rend_splice->_base.marked_for_close) {
+ /* do this after marking this circuit, to avoid infinite recursion. */
+ circuit_mark_for_close(TO_CIRCUIT(or_circ->rend_splice), reason);
+ }
+ or_circ->rend_splice = NULL;
}
- circ->rend_splice = NULL;
}
}
@@ -810,12 +963,19 @@ void
assert_circuit_ok(const circuit_t *c)
{
connection_t *conn;
+ const or_circuit_t *or_circ = NULL;
+ const origin_circuit_t *origin_circ = NULL;
tor_assert(c);
- tor_assert(c->magic == CIRCUIT_MAGIC);
+ tor_assert(c->magic == ORIGIN_CIRCUIT_MAGIC || c->magic == OR_CIRCUIT_MAGIC);
tor_assert(c->purpose >= _CIRCUIT_PURPOSE_MIN &&
c->purpose <= _CIRCUIT_PURPOSE_MAX);
+ if (CIRCUIT_IS_ORIGIN(c))
+ origin_circ = TO_ORIGIN_CIRCUIT((circuit_t*)c);
+ else
+ 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,
@@ -823,32 +983,28 @@ assert_circuit_ok(const circuit_t *c)
if (c->n_circ_id)
tor_assert(c == circuit_get_by_circid_orconn(c->n_circ_id, c->n_conn));
}
- if (c->p_conn) {
- tor_assert(c->p_conn->type == CONN_TYPE_OR);
- if (c->p_circ_id)
- tor_assert(c == circuit_get_by_circid_orconn(c->p_circ_id, c->p_conn));
+ if (or_circ && or_circ->p_conn) {
+ tor_assert(or_circ->p_conn->type == CONN_TYPE_OR);
+ if (or_circ->p_circ_id)
+ tor_assert(c == circuit_get_by_circid_orconn(or_circ->p_circ_id,
+ or_circ->p_conn));
}
- for (conn = c->p_streams; conn; conn = conn->next_stream)
- tor_assert(conn->type == CONN_TYPE_AP);
- for (conn = c->n_streams; conn; conn = conn->next_stream)
- tor_assert(conn->type == CONN_TYPE_EXIT);
+ if (origin_circ)
+ for (conn = origin_circ->p_streams; conn; conn = conn->next_stream)
+ tor_assert(conn->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(c->deliver_window >= 0);
tor_assert(c->package_window >= 0);
if (c->state == CIRCUIT_STATE_OPEN) {
tor_assert(!c->onionskin);
- if (c->cpath) {
- tor_assert(CIRCUIT_IS_ORIGIN(c));
- tor_assert(!c->n_crypto);
- tor_assert(!c->p_crypto);
- tor_assert(!c->n_digest);
- tor_assert(!c->p_digest);
- } else {
- tor_assert(!CIRCUIT_IS_ORIGIN(c));
- tor_assert(c->n_crypto);
- tor_assert(c->p_crypto);
- tor_assert(c->n_digest);
- tor_assert(c->p_digest);
+ if (or_circ) {
+ tor_assert(or_circ->n_crypto);
+ tor_assert(or_circ->p_crypto);
+ tor_assert(or_circ->n_digest);
+ tor_assert(or_circ->p_digest);
}
}
if (c->state == CIRCUIT_STATE_OR_WAIT && !c->marked_for_close) {
@@ -858,17 +1014,18 @@ assert_circuit_ok(const circuit_t *c)
tor_assert(!circuits_pending_or_conns ||
!smartlist_isin(circuits_pending_or_conns, c));
}
- if (c->cpath) {
- assert_cpath_ok(c->cpath);
+ if (origin_circ->cpath) {
+ assert_cpath_ok(origin_circ->cpath);
}
if (c->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED) {
+ tor_assert(or_circ);
if (!c->marked_for_close) {
- tor_assert(c->rend_splice);
- tor_assert(c->rend_splice->rend_splice == c);
+ tor_assert(or_circ->rend_splice);
+ tor_assert(or_circ->rend_splice->rend_splice == or_circ);
}
- tor_assert(c->rend_splice != c);
+ tor_assert(or_circ->rend_splice != or_circ);
} else {
- tor_assert(!c->rend_splice);
+ tor_assert(!or_circ || !or_circ->rend_splice);
}
}
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 0c7198a7bf..b64aaa3a66 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -32,6 +32,7 @@ circuit_is_acceptable(circuit_t *circ, connection_t *conn,
time_t now)
{
routerinfo_t *exitrouter;
+ cpath_build_state_t *build_state;
tor_assert(circ);
tor_assert(conn);
tor_assert(conn->socks_request);
@@ -71,11 +72,12 @@ circuit_is_acceptable(circuit_t *circ, connection_t *conn,
* circuit, it's the magical extra bob hop. so just check the nickname
* of the one we meant to finish at.
*/
- exitrouter = build_state_get_exit_router(circ->build_state);
+ build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
+ exitrouter = build_state_get_exit_router(build_state);
- if (need_uptime && !circ->build_state->need_uptime)
+ if (need_uptime && !build_state->need_uptime)
return 0;
- if (need_internal != circ->build_state->is_internal)
+ if (need_internal != build_state->is_internal)
return 0;
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
@@ -114,9 +116,11 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
return 1;
} else {
if (a->timestamp_dirty ||
- b->build_state->is_internal ||
a->timestamp_created > b->timestamp_created)
return 1;
+ if (CIRCUIT_IS_ORIGIN(b) &&
+ TO_ORIGIN_CIRCUIT(b)->build_state->is_internal)
+ return 1;
}
break;
case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
@@ -149,7 +153,7 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
* If it's INTRODUCE_ACK_WAIT and must_be_open==0, then return the
* closest introduce-purposed circuit that you can find.
*/
-static circuit_t *
+static origin_circuit_t *
circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose,
int need_uptime, int need_internal)
{
@@ -163,6 +167,8 @@ circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose,
purpose == CIRCUIT_PURPOSE_C_REND_JOINED);
for (circ=global_circuitlist;circ;circ = circ->next) {
+ if (!CIRCUIT_IS_ORIGIN(circ))
+ continue;
if (!circuit_is_acceptable(circ,conn,must_be_open,purpose,
need_uptime,need_internal,now))
continue;
@@ -174,7 +180,7 @@ circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose,
best = circ;
}
- return best;
+ return best ? TO_ORIGIN_CIRCUIT(best) : NULL;
}
/** Close all circuits that start at us, aren't open, and were born
@@ -255,7 +261,7 @@ circuit_expire_building(time_t now)
victim->n_circ_id, victim->state,
circuit_state_to_string(victim->state), victim->purpose);
- circuit_log_path(LOG_INFO,LD_CIRC,victim);
+ circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
circuit_mark_for_close(victim, END_CIRC_AT_ORIGIN);
}
}
@@ -301,12 +307,14 @@ circuit_stream_is_being_handled(connection_t *conn, uint16_t port, int min)
if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close &&
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
- !circ->build_state->is_internal &&
(!circ->timestamp_dirty ||
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness > now)) {
- exitrouter = build_state_get_exit_router(circ->build_state);
- if (exitrouter &&
- (!need_uptime || circ->build_state->need_uptime)) {
+ cpath_build_state_t *build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
+ if (build_state->is_internal)
+ continue;
+
+ exitrouter = build_state_get_exit_router(build_state);
+ if (exitrouter && (!need_uptime || build_state->need_uptime)) {
int ok;
if (conn) {
ok = connection_ap_can_use_exit(conn, exitrouter);
@@ -343,6 +351,7 @@ circuit_predict_and_launch_new(void)
/* First, count how many of each type of circuit we have already. */
for (circ=global_circuitlist;circ;circ = circ->next) {
+ cpath_build_state_t *build_state;
if (!CIRCUIT_IS_ORIGIN(circ))
continue;
if (circ->marked_for_close)
@@ -352,9 +361,10 @@ circuit_predict_and_launch_new(void)
if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL)
continue; /* only pay attention to general-purpose circs */
num++;
- if (circ->build_state->is_internal)
+ build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
+ if (build_state->is_internal)
num_internal++;
- if (circ->build_state->need_uptime && circ->build_state->is_internal)
+ if (build_state->need_uptime && build_state->is_internal)
num_uptime_internal++;
}
@@ -455,44 +465,49 @@ circuit_detach_stream(circuit_t *circ, connection_t *conn)
conn->cpath_layer = NULL; /* make sure we don't keep a stale pointer */
conn->on_circuit = NULL;
- if (conn == circ->p_streams) {
- circ->p_streams = conn->next_stream;
- return;
- }
- if (conn == circ->n_streams) {
- circ->n_streams = conn->next_stream;
- return;
- }
- if (conn == circ->resolving_streams) {
- circ->resolving_streams = conn->next_stream;
- return;
- }
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ if (conn == origin_circ->p_streams) {
+ origin_circ->p_streams = conn->next_stream;
+ return;
+ }
- for (prevconn = circ->p_streams;
- prevconn && prevconn->next_stream && prevconn->next_stream != conn;
- prevconn = prevconn->next_stream)
- ;
- if (prevconn && prevconn->next_stream) {
- prevconn->next_stream = conn->next_stream;
- return;
- }
+ for (prevconn = origin_circ->p_streams;
+ prevconn && prevconn->next_stream && prevconn->next_stream != conn;
+ prevconn = prevconn->next_stream)
+ ;
+ if (prevconn && prevconn->next_stream) {
+ prevconn->next_stream = conn->next_stream;
+ return;
+ }
+ } else {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
+ if (conn == or_circ->n_streams) {
+ or_circ->n_streams = conn->next_stream;
+ return;
+ }
+ if (conn == or_circ->resolving_streams) {
+ or_circ->resolving_streams = conn->next_stream;
+ return;
+ }
- for (prevconn = circ->n_streams;
- prevconn && prevconn->next_stream && prevconn->next_stream != conn;
- prevconn = prevconn->next_stream)
- ;
- if (prevconn && prevconn->next_stream) {
- prevconn->next_stream = conn->next_stream;
- return;
- }
+ for (prevconn = or_circ->n_streams;
+ prevconn && prevconn->next_stream && prevconn->next_stream != conn;
+ prevconn = prevconn->next_stream)
+ ;
+ if (prevconn && prevconn->next_stream) {
+ prevconn->next_stream = conn->next_stream;
+ return;
+ }
- for (prevconn = circ->resolving_streams;
- prevconn && prevconn->next_stream && prevconn->next_stream != conn;
- prevconn = prevconn->next_stream)
- ;
- if (prevconn && prevconn->next_stream) {
- prevconn->next_stream = conn->next_stream;
- return;
+ for (prevconn = or_circ->resolving_streams;
+ prevconn && prevconn->next_stream && prevconn->next_stream != conn;
+ prevconn = prevconn->next_stream)
+ ;
+ if (prevconn && prevconn->next_stream) {
+ prevconn->next_stream = conn->next_stream;
+ return;
+ }
}
log_err(LD_BUG,"edge conn not in circuit's list?");
@@ -543,7 +558,7 @@ circuit_about_to_close_connection(connection_t *conn)
}
/** Find each circuit that has been unused for too long, or dirty
- * for too long and has no streams on it: mark it for close.
+ * for too long and has no streax=ms on it: mark it for close.
*/
static void
circuit_expire_old_circuits(time_t now)
@@ -552,23 +567,21 @@ circuit_expire_old_circuits(time_t now)
time_t cutoff = now - get_options()->CircuitIdleTimeout;
for (circ = global_circuitlist; circ; circ = circ->next) {
- if (circ->marked_for_close)
+ if (circ->marked_for_close || ! CIRCUIT_IS_ORIGIN(circ))
continue;
/* If the circuit has been dirty for too long, and there are no streams
* on it, mark it for close.
*/
if (circ->timestamp_dirty &&
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness < now &&
- CIRCUIT_IS_ORIGIN(circ) &&
- !circ->p_streams /* nothing attached */ ) {
+ !TO_ORIGIN_CIRCUIT(circ)->p_streams /* nothing attached */ ) {
log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %d secs ago, purp %d)",
circ->n_circ_id, (int)(now - circ->timestamp_dirty),
circ->purpose);
/* (only general and purpose_c circs can get dirty) */
- tor_assert(!circ->n_streams);
tor_assert(circ->purpose <= CIRCUIT_PURPOSE_C_REND_JOINED);
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
- } else if (!circ->timestamp_dirty && CIRCUIT_IS_ORIGIN(circ) &&
+ } else if (!circ->timestamp_dirty &&
circ->state == CIRCUIT_STATE_OPEN &&
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (circ->timestamp_created < cutoff) {
@@ -583,17 +596,17 @@ circuit_expire_old_circuits(time_t now)
/** A testing circuit has completed. Take whatever stats we want. */
static void
-circuit_testing_opened(circuit_t *circ)
+circuit_testing_opened(origin_circuit_t *circ)
{
/* For now, we only use testing circuits to see if our ORPort is
reachable. But we remember reachability in onionskin_answer(),
so there's no need to record anything here. Just close the circ. */
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
}
/** A testing circuit has failed to build. Take whatever stats we want. */
static void
-circuit_testing_failed(circuit_t *circ, int at_last_hop)
+circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
{
if (server_mode(get_options()) && check_whether_orport_reachable())
return;
@@ -614,11 +627,11 @@ circuit_testing_failed(circuit_t *circ, int at_last_hop)
* that could use circ.
*/
void
-circuit_has_opened(circuit_t *circ)
+circuit_has_opened(origin_circuit_t *circ)
{
control_event_circuit_status(circ, CIRC_EVENT_BUILT);
- switch (circ->purpose) {
+ switch (TO_CIRCUIT(circ)->purpose) {
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
rend_client_rendcirc_has_opened(circ);
connection_ap_attach_pending();
@@ -643,7 +656,7 @@ circuit_has_opened(circuit_t *circ)
circuit_testing_opened(circ);
break;
default:
- log_err(LD_BUG,"unhandled purpose %d",circ->purpose);
+ log_err(LD_BUG,"unhandled purpose %d",circ->_base.purpose);
tor_assert(0);
}
}
@@ -651,7 +664,7 @@ circuit_has_opened(circuit_t *circ)
/** Called whenever a circuit could not be successfully built.
*/
void
-circuit_build_failed(circuit_t *circ)
+circuit_build_failed(origin_circuit_t *circ)
{
/* we should examine circ and see if it failed because of
* the last hop or an earlier hop. then use this info below.
@@ -669,11 +682,12 @@ circuit_build_failed(circuit_t *circ)
/* We failed at the first hop. If there's an OR connection
to blame, blame it. */
connection_t *n_conn = NULL;
- if (circ->n_conn) {
- n_conn = circ->n_conn;
- } else if (circ->state == CIRCUIT_STATE_OR_WAIT) {
+ if (circ->_base.n_conn) {
+ n_conn = circ->_base.n_conn;
+ } else if (circ->_base.state == CIRCUIT_STATE_OR_WAIT) {
/* we have to hunt for it */
- n_conn = connection_or_get_by_identity_digest(circ->n_conn_id_digest);
+ n_conn = connection_or_get_by_identity_digest(
+ circ->_base.n_conn_id_digest);
}
if (n_conn) {
log_info(LD_OR,
@@ -685,7 +699,7 @@ circuit_build_failed(circuit_t *circ)
}
}
- switch (circ->purpose) {
+ switch (circ->_base.purpose) {
case CIRCUIT_PURPOSE_C_GENERAL:
/* If we never built the circuit, note it as a failure. */
circuit_increment_failure_count();
@@ -695,7 +709,7 @@ circuit_build_failed(circuit_t *circ)
break;
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
/* at Bob, waiting for introductions */
- if (circ->state != CIRCUIT_STATE_OPEN) {
+ if (circ->_base.state != CIRCUIT_STATE_OPEN) {
circuit_increment_failure_count();
}
/* no need to care here, because bob will rebuild intro
@@ -744,11 +758,11 @@ static int did_circs_fail_last_period = 0;
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
-circuit_t *
+origin_circuit_t *
circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
int need_uptime, int need_capacity, int internal)
{
- circuit_t *circ;
+ origin_circuit_t *circ;
extend_info_t *info = NULL;
if (exit)
info = extend_info_from_router(exit);
@@ -765,11 +779,11 @@ circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
* choose among routers with high bandwidth. If <b>internal</b> is true, the
* last hop need not be an exit node. Return the newly allocated circuit on
* success, or NULL on failure. */
-circuit_t *
+origin_circuit_t *
circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info,
int need_uptime, int need_capacity, int internal)
{
- circuit_t *circ;
+ origin_circuit_t *circ;
if (!router_have_minimum_dir_info()) {
log_debug(LD_CIRC,"Haven't fetched enough directory info yet; canceling "
@@ -785,11 +799,11 @@ circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info,
if (circ) {
log_info(LD_CIRC,"Cannibalizing circ '%s' for purpose %d",
build_state_get_exit_nickname(circ->build_state), purpose);
- circ->purpose = purpose;
+ circ->_base.purpose = purpose;
/* reset the birth date of this circ, else expire_building
* will see it and think it's been trying to build since it
* began. */
- circ->timestamp_created = time(NULL);
+ circ->_base.timestamp_created = time(NULL);
switch (purpose) {
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
@@ -829,7 +843,7 @@ circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info,
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
-circuit_t *
+origin_circuit_t *
circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname,
int need_uptime, int need_capacity, int internal)
{
@@ -879,9 +893,9 @@ circuit_reset_failure_count(int timeout)
static int
circuit_get_open_circ_or_launch(connection_t *conn,
uint8_t desired_circuit_purpose,
- circuit_t **circp)
+ origin_circuit_t **circp)
{
- circuit_t *circ;
+ origin_circuit_t *circ;
int is_resolve;
int need_uptime, need_internal;
@@ -996,9 +1010,10 @@ circuit_get_open_circ_or_launch(connection_t *conn,
rep_hist_note_used_internal(time(NULL), need_uptime, 1);
if (circ) {
/* write the service_id into circ */
- strlcpy(circ->rend_query, conn->rend_query, sizeof(circ->rend_query));
- if (circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
- circ->state == CIRCUIT_STATE_OPEN)
+ strlcpy(circ->_base.rend_query, conn->rend_query,
+ sizeof(circ->_base.rend_query));
+ if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
+ circ->_base.state == CIRCUIT_STATE_OPEN)
rend_client_rendcirc_has_opened(circ);
}
}
@@ -1017,19 +1032,18 @@ circuit_get_open_circ_or_launch(connection_t *conn,
* circ's cpath.
*/
static void
-link_apconn_to_circ(connection_t *apconn, circuit_t *circ)
+link_apconn_to_circ(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->n_circ_id);
+ circ->_base.n_circ_id);
/* reset it, so we can measure circ timeouts */
apconn->timestamp_lastread = time(NULL);
apconn->next_stream = circ->p_streams;
- apconn->on_circuit = circ;
+ apconn->on_circuit = TO_CIRCUIT(circ);
/* assert_connection_ok(conn, time(NULL)); */
circ->p_streams = apconn;
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
tor_assert(circ->cpath);
tor_assert(circ->cpath->prev);
tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
@@ -1039,7 +1053,7 @@ link_apconn_to_circ(connection_t *apconn, circuit_t *circ)
/** If an exit wasn't specifically chosen, save the history for future
* use. */
static void
-consider_recording_trackhost(connection_t *conn, circuit_t *circ)
+consider_recording_trackhost(connection_t *conn, origin_circuit_t *circ)
{
int found_needle = 0;
char *str;
@@ -1094,7 +1108,7 @@ consider_recording_trackhost(connection_t *conn, circuit_t *circ)
* for connection_ap_handshake_attach_circuit. */
int
connection_ap_handshake_attach_chosen_circuit(connection_t *conn,
- circuit_t *circ)
+ origin_circuit_t *circ)
{
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_AP);
@@ -1102,12 +1116,12 @@ connection_ap_handshake_attach_chosen_circuit(connection_t *conn,
conn->state == AP_CONN_STATE_CONTROLLER_WAIT);
tor_assert(conn->socks_request);
tor_assert(circ);
- tor_assert(circ->state == CIRCUIT_STATE_OPEN);
+ tor_assert(circ->_base.state == CIRCUIT_STATE_OPEN);
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
- if (!circ->timestamp_dirty)
- circ->timestamp_dirty = time(NULL);
+ if (!circ->_base.timestamp_dirty)
+ circ->_base.timestamp_dirty = time(NULL);
link_apconn_to_circ(conn, circ);
tor_assert(conn->socks_request);
@@ -1153,7 +1167,7 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
}
if (!connection_edge_is_rendezvous_stream(conn)) { /* we're a general conn */
- circuit_t *circ=NULL;
+ origin_circuit_t *circ=NULL;
if (conn->chosen_exit_name) {
routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
@@ -1190,7 +1204,7 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
log_debug(LD_APP|LD_CIRC,
"Attaching apconn to circ %d (stream %d sec old).",
- circ->n_circ_id, conn_age);
+ circ->_base.n_circ_id, conn_age);
/* here, print the circ's path. so people can figure out which circs are
* sucking. */
circuit_log_path(LOG_INFO,LD_APP|LD_CIRC,circ);
@@ -1199,7 +1213,7 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
return connection_ap_handshake_attach_chosen_circuit(conn, circ);
} else { /* we're a rendezvous conn */
- circuit_t *rendcirc=NULL, *introcirc=NULL;
+ origin_circuit_t *rendcirc=NULL, *introcirc=NULL;
tor_assert(!conn->cpath_layer);
@@ -1215,25 +1229,25 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
log_info(LD_REND,
"rend joined circ %d already here. attaching. "
"(stream %d sec old)",
- rendcirc->n_circ_id, conn_age);
+ rendcirc->_base.n_circ_id, conn_age);
/* Mark rendezvous circuits as 'newly dirty' every time you use
* them, since the process of rebuilding a rendezvous circ is so
* expensive. There is a tradeoffs between linkability and
* feasibility, at this point.
*/
- rendcirc->timestamp_dirty = time(NULL);
+ rendcirc->_base.timestamp_dirty = time(NULL);
link_apconn_to_circ(conn, rendcirc);
if (connection_ap_handshake_send_begin(conn, rendcirc) < 0)
return 0; /* already marked, let them fade away */
return 1;
}
- if (rendcirc && (rendcirc->purpose ==
+ if (rendcirc && (rendcirc->_base.purpose ==
CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)) {
log_info(LD_REND,
"pending-join circ %d already here, with intro ack. "
"Stalling. (stream %d sec old)",
- rendcirc->n_circ_id, conn_age);
+ rendcirc->_base.n_circ_id, conn_age);
return 0;
}
@@ -1247,7 +1261,8 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
tor_assert(introcirc);
log_info(LD_REND, "Intro circ %d present and awaiting ack (rend %d). "
"Stalling. (stream %d sec old)",
- introcirc->n_circ_id, rendcirc ? rendcirc->n_circ_id : 0,
+ introcirc->_base.n_circ_id,
+ rendcirc ? rendcirc->_base.n_circ_id : 0,
conn_age);
return 0;
}
@@ -1255,32 +1270,34 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
/* now rendcirc and introcirc are each either undefined or not finished */
if (rendcirc && introcirc &&
- rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
+ rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY) {
log_info(LD_REND,
"ready rend circ %d already here (no intro-ack yet on "
"intro %d). (stream %d sec old)",
- rendcirc->n_circ_id, introcirc->n_circ_id, conn_age);
+ rendcirc->_base.n_circ_id,
+ introcirc->_base.n_circ_id, conn_age);
- tor_assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
- if (introcirc->state == CIRCUIT_STATE_OPEN) {
+ tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
+ if (introcirc->_base.state == CIRCUIT_STATE_OPEN) {
log_info(LD_REND,"found open intro circ %d (rend %d); sending "
"introduction. (stream %d sec old)",
- introcirc->n_circ_id, rendcirc->n_circ_id, conn_age);
+ introcirc->_base.n_circ_id, rendcirc->_base.n_circ_id,
+ conn_age);
if (rend_client_send_introduction(introcirc, rendcirc) < 0) {
return -1;
}
- rendcirc->timestamp_dirty = time(NULL);
- introcirc->timestamp_dirty = time(NULL);
- assert_circuit_ok(rendcirc);
- assert_circuit_ok(introcirc);
+ rendcirc->_base.timestamp_dirty = time(NULL);
+ introcirc->_base.timestamp_dirty = time(NULL);
+ assert_circuit_ok(TO_CIRCUIT(rendcirc));
+ assert_circuit_ok(TO_CIRCUIT(introcirc));
return 0;
}
}
log_info(LD_REND, "Intro (%d) and rend (%d) circs are not both ready. "
"Stalling conn. (%d sec old)",
- introcirc ? introcirc->n_circ_id : 0,
- rendcirc ? rendcirc->n_circ_id : 0, conn_age);
+ introcirc ? introcirc->_base.n_circ_id : 0,
+ rendcirc ? rendcirc->_base.n_circ_id : 0, conn_age);
return 0;
}
}
diff --git a/src/or/command.c b/src/or/command.c
index 0e4742b075..49fcc654c7 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -161,7 +161,7 @@ command_process_cell(cell_t *cell, connection_t *conn)
static void
command_process_create_cell(cell_t *cell, connection_t *conn)
{
- circuit_t *circ;
+ or_circuit_t *circ;
int id_is_high;
if (we_are_hibernating()) {
@@ -186,9 +186,7 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
return;
}
- circ = circuit_get_by_circid_orconn(cell->circ_id, conn);
-
- if (circ) {
+ if (circuit_get_by_circid_orconn(cell->circ_id, conn)) {
routerinfo_t *router = router_get_by_digest(conn->identity_digest);
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received CREATE cell (circID %d) for known circ. "
@@ -201,17 +199,17 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
return;
}
- circ = circuit_new(cell->circ_id, conn);
- circ->purpose = CIRCUIT_PURPOSE_OR;
- circuit_set_state(circ, CIRCUIT_STATE_ONIONSKIN_PENDING);
+ circ = or_circuit_new(cell->circ_id, conn);
+ circ->_base.purpose = CIRCUIT_PURPOSE_OR;
+ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING);
if (cell->command == CELL_CREATE) {
- circ->onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
- memcpy(circ->onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
+ circ->_base.onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
+ memcpy(circ->_base.onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
/* hand it off to the cpuworkers, and then return. */
if (assign_to_cpuworker(NULL, CPUWORKER_TASK_ONION, circ) < 0) {
log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing.");
- circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return;
}
log_debug(LD_OR,"success: handed off onionskin.");
@@ -223,12 +221,12 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
tor_assert(cell->command == CELL_CREATE_FAST);
if (fast_server_handshake(cell->payload, reply, keys, sizeof(keys))<0) {
log_warn(LD_OR,"Failed to generate key material. Closing.");
- circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return;
}
if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) {
log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing.");
- circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return;
}
}
@@ -264,14 +262,16 @@ command_process_created_cell(cell_t *cell, connection_t *conn)
}
if (CIRCUIT_IS_ORIGIN(circ)) { /* we're the OP. Handshake this. */
+ origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
log_debug(LD_OR,"at OP. Finishing handshake.");
- if (circuit_finish_handshake(circ, cell->command, cell->payload) < 0) {
+ if (circuit_finish_handshake(origin_circ, cell->command,
+ cell->payload) < 0) {
log_warn(LD_OR,"circuit_finish_handshake failed.");
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return;
}
log_debug(LD_OR,"Moving to next skin.");
- if (circuit_send_next_onion_skin(circ) < 0) {
+ if (circuit_send_next_onion_skin(origin_circ) < 0) {
log_info(LD_OR,"circuit_send_next_onion_skin failed.");
/* XXX push this circuit_close lower */
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
@@ -310,7 +310,9 @@ command_process_relay_cell(cell_t *cell, connection_t *conn)
return;
}
- if (cell->circ_id == circ->p_circ_id) { /* it's an outgoing cell */
+ if (!CIRCUIT_IS_ORIGIN(circ) &&
+ cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) {
+ /* it's an outgoing cell */
if ((reason = circuit_receive_relay_cell(cell, circ,
CELL_DIRECTION_OUT)) < 0) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit_receive_relay_cell "
@@ -357,12 +359,13 @@ command_process_destroy_cell(cell_t *cell, connection_t *conn)
}
log_debug(LD_OR,"Received for circID %d.",cell->circ_id);
- if (cell->circ_id == circ->p_circ_id) {
+ if (!CIRCUIT_IS_ORIGIN(circ) &&
+ cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) {
/* the destroy came from behind */
- circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
+ circuit_set_p_circid_orconn(TO_OR_CIRCUIT(circ), 0, NULL);
circuit_mark_for_close(circ, reason);
} else { /* the destroy came from ahead */
- circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
+ circuit_set_n_circid_orconn(circ, 0, NULL);
if (CIRCUIT_IS_ORIGIN(circ)) {
circuit_mark_for_close(circ, reason);
} else {
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index ef16c5efd4..0d1ecd6a69 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -60,20 +60,6 @@ _connection_mark_unattached_ap(connection_t *conn, int endreason,
int
connection_edge_reached_eof(connection_t *conn)
{
-#ifdef HALF_OPEN
- /* eof reached; we're done reading, but we might want to write more. */
- conn->done_receiving = 1;
- shutdown(conn->s, 0); /* XXX check return, refactor NM */
- if (conn->done_sending) {
- connection_edge_end(conn, END_STREAM_REASON_DONE, conn->cpath_layer);
- connection_mark_for_close(conn);
- } else {
- connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
- RELAY_COMMAND_END,
- NULL, 0, conn->cpath_layer);
- }
- return 0;
-#else
if (buf_datalen(conn->inbuf) && connection_state_is_open(conn)) {
/* it still has stuff to process. don't let it die yet. */
return 0;
@@ -88,7 +74,6 @@ connection_edge_reached_eof(connection_t *conn)
connection_mark_for_close(conn);
}
return 0;
-#endif
}
/** Handle new bytes on conn->inbuf based on state:
@@ -386,7 +371,8 @@ connection_ap_expire_beginning(void)
continue;
}
tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL);
- nickname = build_state_get_exit_nickname(circ->build_state);
+ nickname = build_state_get_exit_nickname(
+ TO_ORIGIN_CIRCUIT(circ)->build_state);
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.",
@@ -406,7 +392,7 @@ connection_ap_expire_beginning(void)
conn->timestamp_lastread += cutoff;
conn->num_socks_retries++;
/* move it back into 'pending' state, and try to attach. */
- if (connection_ap_detach_retriable(conn, circ)<0) {
+ if (connection_ap_detach_retriable(conn, TO_ORIGIN_CIRCUIT(circ))<0) {
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
}
} /* end for */
@@ -444,17 +430,17 @@ 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, circuit_t *circ)
+connection_ap_detach_retriable(connection_t *conn, origin_circuit_t *circ)
{
control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE);
conn->timestamp_lastread = time(NULL);
if (! get_options()->LeaveStreamsUnattached) {
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
- circuit_detach_stream(circ,conn);
+ circuit_detach_stream(TO_CIRCUIT(circ),conn);
return connection_ap_handshake_attach_circuit(conn);
} else {
conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
- circuit_detach_stream(circ,conn);
+ circuit_detach_stream(TO_CIRCUIT(circ),conn);
return 0;
}
}
@@ -1026,7 +1012,7 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
*/
int
connection_ap_handshake_rewrite_and_attach(connection_t *conn,
- circuit_t *circ)
+ origin_circuit_t *circ)
{
socks_request_t *socks = conn->socks_request;
hostname_type_t addresstype;
@@ -1287,7 +1273,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
* already in use; return it. Return 0 if can't get a unique stream_id.
*/
static uint16_t
-get_unique_stream_id_by_circ(circuit_t *circ)
+get_unique_stream_id_by_circ(origin_circuit_t *circ)
{
connection_t *tmpconn;
uint16_t test_stream_id;
@@ -1314,7 +1300,8 @@ 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, circuit_t *circ)
+connection_ap_handshake_send_begin(connection_t *ap_conn,
+ origin_circuit_t *circ)
{
char payload[CELL_PAYLOAD_SIZE];
int payload_len;
@@ -1326,12 +1313,12 @@ connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
if (ap_conn->stream_id==0) {
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
- circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
return -1;
}
tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:%d",
- (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) ?
+ (circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL) ?
ap_conn->socks_request->address : "",
ap_conn->socks_request->port);
payload_len = strlen(payload)+1;
@@ -1339,7 +1326,8 @@ connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
log_debug(LD_APP,
"Sending relay cell to begin stream %d.", ap_conn->stream_id);
- if (connection_edge_send_command(ap_conn, circ, RELAY_COMMAND_BEGIN,
+ if (connection_edge_send_command(ap_conn, TO_CIRCUIT(circ),
+ RELAY_COMMAND_BEGIN,
payload, payload_len,
ap_conn->cpath_layer) < 0)
return -1; /* circuit is closed, don't continue */
@@ -1348,7 +1336,7 @@ connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
ap_conn->deliver_window = STREAMWINDOW_START;
ap_conn->state = AP_CONN_STATE_CONNECT_WAIT;
log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d",
- ap_conn->s, circ->n_circ_id);
+ ap_conn->s, circ->_base.n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT);
return 0;
}
@@ -1359,7 +1347,8 @@ connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
* 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, circuit_t *circ)
+connection_ap_handshake_send_resolve(connection_t *ap_conn,
+ origin_circuit_t *circ)
{
int payload_len;
const char *string_addr;
@@ -1368,12 +1357,12 @@ connection_ap_handshake_send_resolve(connection_t *ap_conn, circuit_t *circ)
tor_assert(ap_conn->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->purpose == CIRCUIT_PURPOSE_C_GENERAL);
+ tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL);
ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
if (ap_conn->stream_id==0) {
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
- circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
return -1;
}
@@ -1384,13 +1373,14 @@ connection_ap_handshake_send_resolve(connection_t *ap_conn, circuit_t *circ)
log_debug(LD_APP,
"Sending relay cell to begin stream %d.", ap_conn->stream_id);
- if (connection_edge_send_command(ap_conn, circ, RELAY_COMMAND_RESOLVE,
+ if (connection_edge_send_command(ap_conn, TO_CIRCUIT(circ),
+ RELAY_COMMAND_RESOLVE,
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;
log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d",
- ap_conn->s, circ->n_circ_id);
+ ap_conn->s, circ->_base.n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE);
return 0;
}
@@ -1643,6 +1633,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
n_stream->deliver_window = STREAMWINDOW_START;
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;
@@ -1650,7 +1641,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
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, circ) < 0) {
+ if (rend_service_set_connection_addr_port(n_stream, origin_circ) < 0) {
log_info(LD_REND,"Didn't find rendezvous service (port %d)",
n_stream->port);
connection_edge_end(n_stream, END_STREAM_REASON_EXITPOLICY,
@@ -1663,12 +1654,12 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
}
assert_circuit_ok(circ);
log_debug(LD_REND,"Finished assigning addr/port");
- n_stream->cpath_layer = circ->cpath->prev; /* link it */
+ n_stream->cpath_layer = origin_circ->cpath->prev; /* link it */
/* add it into the linked list of n_streams on this circuit */
- n_stream->next_stream = circ->n_streams;
+ n_stream->next_stream = origin_circ->p_streams;
n_stream->on_circuit = circ;
- circ->n_streams = n_stream;
+ origin_circ->p_streams = n_stream;
assert_circuit_ok(circ);
connection_exit_connect(n_stream);
@@ -1693,9 +1684,9 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
case 1: /* resolve worked */
/* add it into the linked list of n_streams on this circuit */
- n_stream->next_stream = circ->n_streams;
+ n_stream->next_stream = TO_OR_CIRCUIT(circ)->n_streams;
n_stream->on_circuit = circ;
- circ->n_streams = n_stream;
+ TO_OR_CIRCUIT(circ)->n_streams = n_stream;
assert_circuit_ok(circ);
log_debug(LD_EXIT,"about to call connection_exit_connect().");
@@ -1706,9 +1697,9 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
break;
case 0: /* resolve added to pending list */
/* add it into the linked list of resolving_streams on this circuit */
- n_stream->next_stream = circ->resolving_streams;
+ n_stream->next_stream = TO_OR_CIRCUIT(circ)->resolving_streams;
n_stream->on_circuit = circ;
- circ->resolving_streams = n_stream;
+ TO_OR_CIRCUIT(circ)->resolving_streams = n_stream;
assert_circuit_ok(circ);
;
}
@@ -1720,12 +1711,12 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
* begin resolving the hostname, and (eventually) reply with a RESOLVED cell.
*/
int
-connection_exit_begin_resolve(cell_t *cell, circuit_t *circ)
+connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
{
connection_t *dummy_conn;
relay_header_t rh;
- assert_circuit_ok(circ);
+ assert_circuit_ok(TO_CIRCUIT(circ));
relay_header_unpack(&rh, cell->payload);
/* This 'dummy_conn' only exists to remember the stream ID
@@ -1754,9 +1745,9 @@ connection_exit_begin_resolve(cell_t *cell, circuit_t *circ)
return 0;
case 0: /* resolve added to pending list */
dummy_conn->next_stream = circ->resolving_streams;
- dummy_conn->on_circuit = circ;
+ dummy_conn->on_circuit = TO_CIRCUIT(circ);
circ->resolving_streams = dummy_conn;
- assert_circuit_ok(circ);
+ assert_circuit_ok(TO_CIRCUIT(circ));
break;
}
return 0;
diff --git a/src/or/control.c b/src/or/control.c
index c2d86f8c7d..7737e9a21f 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1372,7 +1372,7 @@ handle_getinfo_helper(const char *question, char **answer)
const char *state;
if (! CIRCUIT_IS_ORIGIN(circ) || circ->marked_for_close)
continue;
- path = circuit_list_path(circ,0);
+ path = circuit_list_path(TO_ORIGIN_CIRCUIT(circ),0);
if (circ->state == CIRCUIT_STATE_OPEN)
state = "BUILT";
else if (strlen(path))
@@ -1728,6 +1728,15 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
}
}
+ if (circ && ! CIRCUIT_IS_ORIGIN(circ)) {
+ if (v0)
+ send_control0_error(conn, ERR_NO_CIRC,"Circuit does not originate here");
+ else
+ connection_printf_to_buf(conn,
+ "555 Circuit does not originate here\r\n");
+ goto done;
+ }
+
routers = smartlist_create();
SMARTLIST_FOREACH(router_nicknames, const char *, n,
{
@@ -1751,20 +1760,20 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
if (zero_circ) {
/* start a new circuit */
- circ = circuit_init(intended_purpose, 0, 0, 0);
+ circ = TO_CIRCUIT( origin_circuit_init(intended_purpose, 0, 0, 0) );
}
/* now circ refers to something that is ready to be extended */
SMARTLIST_FOREACH(routers, routerinfo_t *, r,
{
extend_info_t *info = extend_info_from_router(r);
- circuit_append_new_exit(circ, info);
+ circuit_append_new_exit(TO_ORIGIN_CIRCUIT(circ), info);
extend_info_free(info);
});
/* now that we've populated the cpath, start extending */
if (zero_circ) {
- if (circuit_handle_first_hop(circ) < 0) {
+ if (circuit_handle_first_hop(TO_ORIGIN_CIRCUIT(circ)) < 0) {
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
if (v0)
send_control0_error(conn, ERR_INTERNAL, "couldn't start circuit");
@@ -1775,7 +1784,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
} else {
if (circ->state == CIRCUIT_STATE_OPEN) {
circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
- if (circuit_send_next_onion_skin(circ) < 0) {
+ if (circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)) < 0) {
log_info(LD_CONTROL,
"send_next_onion_skin failed; circuit marked for closing.");
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
@@ -1940,17 +1949,19 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
ap_conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
}
- if (circ && circ->state != CIRCUIT_STATE_OPEN) {
+ if (circ &&
+ (circ->state != CIRCUIT_STATE_OPEN || ! CIRCUIT_IS_ORIGIN(circ))) {
if (STATE_IS_V0(conn->state))
send_control0_error(conn, ERR_INTERNAL,
- "Refuse to attach stream to non-open circ.");
+ "Refuse to attach stream to non-open, origin circ.");
else
connection_write_str_to_buf(
- "551 Can't attach stream to non-open circuit\r\n",
- conn);
+ "551 Can't attach stream to non-open, origin circuit\r\n",
+ conn);
return 0;
}
- if (connection_ap_handshake_rewrite_and_attach(ap_conn, circ) < 0) {
+ if (connection_ap_handshake_rewrite_and_attach(ap_conn,
+ circ ? TO_ORIGIN_CIRCUIT(circ) : NULL) < 0) {
if (STATE_IS_V0(conn->state))
send_control0_error(conn, ERR_INTERNAL, "Unable to attach stream.");
else
@@ -2195,7 +2206,8 @@ handle_control_closecircuit(connection_t *conn, uint32_t len,
return 0;
}
- if (!safe || !circ->p_streams) {
+ if (!safe || !CIRCUIT_IS_ORIGIN(circ) ||
+ !TO_ORIGIN_CIRCUIT(circ)->p_streams) {
circuit_mark_for_close(circ, END_CIRC_REASON_NONE);
}
@@ -2586,20 +2598,19 @@ connection_control_process_inbuf(connection_t *conn)
/** Something has happened to circuit <b>circ</b>: tell any interested
* control connections. */
int
-control_event_circuit_status(circuit_t *circ, circuit_status_event_t tp)
+control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp)
{
char *path, *msg;
if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
return 0;
tor_assert(circ);
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
path = circuit_list_path(circ,0);
if (EVENT_IS_INTERESTING0(EVENT_CIRCUIT_STATUS)) {
size_t path_len = strlen(path);
msg = tor_malloc(1+4+path_len+1); /* event, circid, path, NUL. */
msg[0] = (uint8_t) tp;
- set_uint32(msg+1, htonl(circ->global_identifier));
+ set_uint32(msg+1, htonl(circ->_base.global_identifier));
strlcpy(msg+5,path,path_len+1);
send_control0_event(EVENT_CIRCUIT_STATUS, (uint32_t)(path_len+6), msg);
@@ -2620,7 +2631,7 @@ control_event_circuit_status(circuit_t *circ, circuit_status_event_t tp)
}
send_control1_event(EVENT_CIRCUIT_STATUS,
"650 CIRC %lu %s %s\r\n",
- (unsigned long)circ->global_identifier,
+ (unsigned long)circ->_base.global_identifier,
status, path);
}
tor_free(path);
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index c86753fb58..1ed91b0426 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -181,8 +181,8 @@ connection_cpu_process_inbuf(connection_t *conn)
log_debug(LD_OR,"processed onion for a circ that's gone. Dropping.");
goto done_processing;
}
- tor_assert(circ->p_conn);
- if (onionskin_answer(circ, CELL_CREATED, buf+TAG_LEN,
+ tor_assert(! CIRCUIT_IS_ORIGIN(circ));
+ if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN,
buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) {
log_warn(LD_OR,"onionskin_answer failed. Closing.");
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
@@ -386,7 +386,7 @@ spawn_enough_cpuworkers(void)
static void
process_pending_task(connection_t *cpuworker)
{
- circuit_t *circ;
+ or_circuit_t *circ;
tor_assert(cpuworker);
@@ -444,7 +444,7 @@ int
assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
void *task)
{
- circuit_t *circ;
+ or_circuit_t *circ;
char tag[TAG_LEN];
tor_assert(question_type == CPUWORKER_TASK_ONION);
@@ -454,7 +454,7 @@ assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
if (question_type == CPUWORKER_TASK_ONION) {
circ = task;
- tor_assert(circ->onionskin);
+ tor_assert(circ->_base.onionskin);
if (num_cpuworkers_busy == num_cpuworkers) {
log_debug(LD_OR,"No idle cpuworkers. Queuing.");
@@ -484,9 +484,9 @@ assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
connection_write_to_buf((char*)&question_type, 1, cpuworker);
connection_write_to_buf(tag, sizeof(tag), cpuworker);
- connection_write_to_buf(circ->onionskin, ONIONSKIN_CHALLENGE_LEN,
+ connection_write_to_buf(circ->_base.onionskin, ONIONSKIN_CHALLENGE_LEN,
cpuworker);
- tor_free(circ->onionskin);
+ tor_free(circ->_base.onionskin);
}
return 0;
}
diff --git a/src/or/dns.c b/src/or/dns.c
index d0545f19e9..3844741ee0 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -686,12 +686,13 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
circ = circuit_get_by_edge_conn(pend->conn);
tor_assert(circ);
+ tor_assert(!CIRCUIT_IS_ORIGIN(circ));
/* unlink pend->conn from resolving_streams, */
circuit_detach_stream(circ, pend->conn);
/* and link it to n_streams */
- pend->conn->next_stream = circ->n_streams;
+ pend->conn->next_stream = TO_OR_CIRCUIT(circ)->n_streams;
pend->conn->on_circuit = circ;
- circ->n_streams = pend->conn;
+ TO_OR_CIRCUIT(circ)->n_streams = pend->conn;
connection_exit_connect(pend->conn);
} else {
diff --git a/src/or/onion.c b/src/or/onion.c
index 315c5f12dd..ba41f21a22 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -17,7 +17,7 @@ const char onion_c_id[] =
/** Type for a linked list of circuits that are waiting for a free CPU worker
* to process a waiting onion handshake. */
typedef struct onion_queue_t {
- circuit_t *circ;
+ or_circuit_t *circ;
time_t when_added;
struct onion_queue_t *next;
} onion_queue_t;
@@ -35,7 +35,7 @@ static int ol_length=0;
* if ol_list is too long, in which case do nothing and return -1.
*/
int
-onion_pending_add(circuit_t *circ)
+onion_pending_add(or_circuit_t *circ)
{
onion_queue_t *tmp;
time_t now = time(NULL);
@@ -75,7 +75,7 @@ onion_pending_add(circuit_t *circ)
onion_pending_remove(ol_list->circ);
log_info(LD_CIRC,
"Circuit create request is too old; cancelling due to overload.");
- circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
}
return 0;
}
@@ -83,10 +83,10 @@ onion_pending_add(circuit_t *circ)
/** Remove the first item from ol_list and return it, or return
* NULL if the list is empty.
*/
-circuit_t *
+or_circuit_t *
onion_next_task(void)
{
- circuit_t *circ;
+ or_circuit_t *circ;
if (!ol_list)
return NULL; /* no onions pending, we're done */
@@ -103,7 +103,7 @@ onion_next_task(void)
* circ, remove and free that element. Leave circ itself alone.
*/
void
-onion_pending_remove(circuit_t *circ)
+onion_pending_remove(or_circuit_t *circ)
{
onion_queue_t *tmpo, *victim;
diff --git a/src/or/or.h b/src/or/or.h
index 63869e6dd8..06d32e5031 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1040,7 +1040,10 @@ typedef struct {
time_t expiry_time;
} cpath_build_state_t;
-#define CIRCUIT_MAGIC 0x35315243u
+#define ORIGIN_CIRCUIT_MAGIC 0x35315243u
+#define OR_CIRCUIT_MAGIC 0x98ABC04Fu
+
+typedef uint16_t circid_t;
/**
* A circuit is a path over the onion routing
@@ -1064,29 +1067,20 @@ typedef struct {
* "backward" (towards the OP). At the OR, a circuit has only two stream
* ciphers: one for data going forward, and one for data going backward.
*/
-struct circuit_t {
- uint32_t magic; /**< For memory debugging: must equal CIRCUIT_MAGIC. */
+typedef struct circuit_t {
+ uint32_t magic; /**< For memory and type debugging: must equal
+ * ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
- /** The OR connection that is previous in this circuit. */
- connection_t *p_conn;
/** The OR connection that is next in this circuit. */
connection_t *n_conn;
/** The identity hash of n_conn. */
char n_conn_id_digest[DIGEST_LEN];
- /** Linked list of AP streams associated with this circuit. */
- connection_t *p_streams;
- /** Linked list of Exit streams associated with this circuit. */
- connection_t *n_streams;
- /** Linked list of Exit streams associated with this circuit that are
- * still being resolved. */
- connection_t *resolving_streams;
+ /** The circuit_id used in the next (forward) hop of this circuit. */
+ uint16_t n_circ_id;
/** The IPv4 address of the OR that is next in this circuit. */
uint32_t n_addr;
/** The port for the OR that is next in this circuit. */
uint16_t n_port;
- /** The next stream_id that will be tried when we're attempting to
- * construct a new AP stream originating at this circuit. */
- uint16_t next_stream_id;
/** How many relay data cells can we package (read from edge streams)
* on this circuit before we receive a circuit-level sendme cell asking
* for more? */
@@ -1097,48 +1091,12 @@ struct circuit_t {
* more. */
int deliver_window;
- /** The circuit_id used in the previous (backward) hop of this circuit. */
- uint16_t p_circ_id;
- /** The circuit_id used in the next (forward) hop of this circuit. */
- uint16_t n_circ_id;
-
- /** The cipher used by intermediate hops for cells heading toward the
- * OP. */
- crypto_cipher_env_t *p_crypto;
- /** The cipher used by intermediate hops for cells heading away from
- * the OP. */
- crypto_cipher_env_t *n_crypto;
-
- /** The integrity-checking digest used by intermediate hops, for
- * cells packaged here and heading towards the OP.
- */
- crypto_digest_env_t *p_digest;
- /** The integrity-checking digest used by intermediate hops, for
- * cells packaged at the OP and arriving here.
- */
- crypto_digest_env_t *n_digest;
-
- /** Build state for this circuit. It includes the intended path
- * length, the chosen exit router, rendezvous information, etc.
- */
- cpath_build_state_t *build_state;
- /** The doubly-linked list of crypt_path_t entries, one per hop,
- * for this circuit. This includes ciphers for each hop,
- * integrity-checking digests for each hop, and package/delivery
- * windows for each hop.
- *
- * The cpath field is defined only when we are the circuit's origin.
- */
- crypt_path_t *cpath;
-
/** For storage while passing to cpuworker (state
* CIRCUIT_STATE_ONIONSKIN_PENDING), or while n_conn is pending
* (state CIRCUIT_STATE_OR_WAIT). When defined, it is always
* length ONIONSKIN_CHALLENGE_LEN. */
char *onionskin;
- char handshake_digest[DIGEST_LEN]; /**< Stores KH for intermediate hops. */
-
time_t timestamp_created; /**< When was this circuit created? */
time_t timestamp_dirty; /**< When the circuit was first used, or 0 if the
* circuit is clean. */
@@ -1169,18 +1127,85 @@ struct circuit_t {
*/
char rend_cookie[REND_COOKIE_LEN];
- /** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
- * is not marked for close. */
- struct circuit_t *rend_splice;
-
/** Quasi-global identifier for this circuit; used for control.c */
/* XXXX NM This can get re-used after 2**32 circuits. */
uint32_t global_identifier;
struct circuit_t *next; /**< Next circuit in linked list. */
-};
+} circuit_t;
+
+typedef struct origin_circuit_t {
+ circuit_t _base;
+
+ /** Linked list of AP streams associated with this circuit. */
+ connection_t *p_streams;
+ /** The next stream_id that will be tried when we're attempting to
+ * construct a new AP stream originating at this circuit. */
+ uint16_t next_stream_id;
+ /** Build state for this circuit. It includes the intended path
+ * length, the chosen exit router, rendezvous information, etc.
+ */
+ cpath_build_state_t *build_state;
+ /** The doubly-linked list of crypt_path_t entries, one per hop,
+ * for this circuit. This includes ciphers for each hop,
+ * integrity-checking digests for each hop, and package/delivery
+ * windows for each hop.
+ *
+ * The cpath field is defined only when we are the circuit's origin.
+ */
+ crypt_path_t *cpath;
-typedef struct circuit_t circuit_t;
+} origin_circuit_t;
+
+typedef struct or_circuit_t {
+ circuit_t _base;
+
+ /** 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;
+ /** Linked list of Exit streams associated with this circuit. */
+ connection_t *n_streams;
+ /** Linked list of Exit streams associated with this circuit that are
+ * still being resolved. */
+ connection_t *resolving_streams;
+ /** The cipher used by intermediate hops for cells heading toward the
+ * OP. */
+ crypto_cipher_env_t *p_crypto;
+ /** The cipher used by intermediate hops for cells heading away from
+ * the OP. */
+ crypto_cipher_env_t *n_crypto;
+
+ /** The integrity-checking digest used by intermediate hops, for
+ * cells packaged here and heading towards the OP.
+ */
+ crypto_digest_env_t *p_digest;
+ /** The integrity-checking digest used by intermediate hops, for
+ * cells packaged at the OP and arriving here.
+ */
+ crypto_digest_env_t *n_digest;
+
+ /** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
+ * is not marked for close. */
+ struct or_circuit_t *rend_splice;
+
+ char handshake_digest[DIGEST_LEN]; /**< Stores KH for intermediate hops. */
+} or_circuit_t;
+
+#define TO_CIRCUIT(x) (&((x)->_base))
+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));
+}
+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));
+}
#define ALLOW_INVALID_ENTRY 1
#define ALLOW_INVALID_EXIT 2
@@ -1505,32 +1530,34 @@ void assert_buf_ok(buf_t *buf);
/********************************* circuitbuild.c **********************/
-char *circuit_list_path(circuit_t *circ, int verbose);
-void circuit_log_path(int severity, unsigned int domain, circuit_t *circ);
-void circuit_rep_hist_note_result(circuit_t *circ);
-void circuit_dump_by_conn(connection_t *conn, int severity);
-circuit_t *circuit_init(uint8_t purpose, int need_uptime,
- int need_capacity, int internal);
-circuit_t *circuit_establish_circuit(uint8_t purpose, extend_info_t *exit,
+char *circuit_list_path(origin_circuit_t *circ, int verbose);
+void circuit_log_path(int severity, unsigned int domain,
+ origin_circuit_t *circ);
+void circuit_rep_hist_note_result(origin_circuit_t *circ);
+origin_circuit_t *origin_circuit_init(uint8_t purpose, int need_uptime,
+ int need_capacity, int internal);
+origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
+ extend_info_t *exit,
int need_uptime, int need_capacity,
int internal);
-int circuit_handle_first_hop(circuit_t *circ);
+int circuit_handle_first_hop(origin_circuit_t *circ);
void circuit_n_conn_done(connection_t *or_conn, int status);
int inform_testing_reachability(void);
-int circuit_send_next_onion_skin(circuit_t *circ);
+int circuit_send_next_onion_skin(origin_circuit_t *circ);
void circuit_note_clock_jumped(int seconds_elapsed);
int circuit_extend(cell_t *cell, circuit_t *circ);
int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data,
int reverse);
-int circuit_finish_handshake(circuit_t *circ, uint8_t cell_type, char *reply);
-int circuit_truncated(circuit_t *circ, crypt_path_t *layer);
-int onionskin_answer(circuit_t *circ, uint8_t cell_type, char *payload,
+int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type,
+ char *reply);
+int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer);
+int onionskin_answer(or_circuit_t *circ, uint8_t cell_type, char *payload,
char *keys);
int circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
int *need_capacity);
-int circuit_append_new_exit(circuit_t *circ, extend_info_t *info);
-int circuit_extend_to_new_exit(circuit_t *circ, extend_info_t *info);
+int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
+int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
extend_info_t *extend_info_from_router(routerinfo_t *r);
extend_info_t *extend_info_dup(extend_info_t *info);
@@ -1551,13 +1578,15 @@ void entry_guards_free_all(void);
circuit_t * _circuit_get_global_list(void);
const char *circuit_state_to_string(int state);
-enum which_conn_changed_t { P_CONN_CHANGED=1, N_CONN_CHANGED=0 };
-void circuit_set_circid_orconn(circuit_t *circ, uint16_t id,
- connection_t *conn,
- enum which_conn_changed_t which);
+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);
+void circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
+ connection_t *conn);
void circuit_set_state(circuit_t *circ, int state);
void circuit_close_all_marked(void);
-circuit_t *circuit_new(uint16_t p_circ_id, connection_t *p_conn);
+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);
@@ -1567,8 +1596,9 @@ circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query,
uint8_t purpose);
circuit_t *circuit_get_next_by_pk_and_purpose(circuit_t *start,
const char *digest, uint8_t purpose);
-circuit_t *circuit_get_rendezvous(const char *cookie);
-circuit_t *circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
+or_circuit_t *circuit_get_rendezvous(const char *cookie);
+origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
+ extend_info_t *info,
int need_uptime,
int need_capacity, int internal);
void circuit_mark_all_unused_circs(void);
@@ -1592,22 +1622,22 @@ int circuit_stream_is_being_handled(connection_t *conn, uint16_t port,
void circuit_build_needed_circs(time_t now);
void circuit_detach_stream(circuit_t *circ, connection_t *conn);
void circuit_about_to_close_connection(connection_t *conn);
-void circuit_has_opened(circuit_t *circ);
-void circuit_build_failed(circuit_t *circ);
-circuit_t *circuit_launch_by_nickname(uint8_t purpose,
+void circuit_has_opened(origin_circuit_t *circ);
+void circuit_build_failed(origin_circuit_t *circ);
+origin_circuit_t *circuit_launch_by_nickname(uint8_t purpose,
const char *exit_nickname,
int need_uptime, int need_capacity,
int is_internal);
-circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
+origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *info,
int need_uptime, int need_capacity,
int is_internal);
-circuit_t *circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
+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,
- circuit_t *circ);
+ origin_circuit_t *circ);
int connection_ap_handshake_attach_circuit(connection_t *conn);
/********************************* command.c ***************************/
@@ -1733,9 +1763,10 @@ 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_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
+int connection_ap_handshake_send_begin(connection_t *ap_conn,
+ origin_circuit_t *circ);
int connection_ap_handshake_send_resolve(connection_t *ap_conn,
- circuit_t *circ);
+ 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,
@@ -1748,13 +1779,13 @@ void connection_ap_handshake_socks_resolved(connection_t *conn,
int ttl);
int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
-int connection_exit_begin_resolve(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_ap_expire_beginning(void);
void connection_ap_attach_pending(void);
-int connection_ap_detach_retriable(connection_t *conn, circuit_t *circ);
+int connection_ap_detach_retriable(connection_t *conn, origin_circuit_t *circ);
void addressmap_init(void);
void addressmap_clean(time_t now);
@@ -1776,7 +1807,7 @@ 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,
- circuit_t *circ);
+ origin_circuit_t *circ);
void set_exit_redirects(smartlist_t *lst);
typedef enum hostname_type_t {
@@ -1865,7 +1896,8 @@ 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 control_event_circuit_status(circuit_t *circ, circuit_status_event_t e);
+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_bandwidth_used(uint32_t n_read, uint32_t n_written);
@@ -2026,9 +2058,9 @@ int tor_main(int argc, char *argv[]);
/********************************* onion.c ***************************/
-int onion_pending_add(circuit_t *circ);
-circuit_t *onion_next_task(void);
-void onion_pending_remove(circuit_t *circ);
+int onion_pending_add(or_circuit_t *circ);
+or_circuit_t *onion_next_task(void);
+void onion_pending_remove(or_circuit_t *circ);
int onion_skin_create(crypto_pk_env_t *router_key,
crypto_dh_env_t **handshake_state_out,
@@ -2148,22 +2180,23 @@ void rep_hist_free_all(void);
/********************************* rendclient.c ***************************/
-void rend_client_introcirc_has_opened(circuit_t *circ);
-void rend_client_rendcirc_has_opened(circuit_t *circ);
-int rend_client_introduction_acked(circuit_t *circ, const char *request,
+void rend_client_introcirc_has_opened(origin_circuit_t *circ);
+void rend_client_rendcirc_has_opened(origin_circuit_t *circ);
+int rend_client_introduction_acked(origin_circuit_t *circ, const char *request,
size_t request_len);
void rend_client_refetch_renddesc(const char *query);
int rend_client_remove_intro_point(extend_info_t *failed_intro,
const char *query);
-int rend_client_rendezvous_acked(circuit_t *circ, const char *request,
+int rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
size_t request_len);
-int rend_client_receive_rendezvous(circuit_t *circ, const char *request,
+int rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
size_t request_len);
void rend_client_desc_here(const char *query);
extend_info_t *rend_client_get_random_intro(const char *query);
-int rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc);
+int rend_client_send_introduction(origin_circuit_t *introcirc,
+ origin_circuit_t *rendcirc);
/********************************* rendcommon.c ***************************/
@@ -2228,25 +2261,27 @@ void rend_services_init(void);
void rend_services_introduce(void);
void rend_consider_services_upload(time_t now);
-void rend_service_intro_has_opened(circuit_t *circuit);
-int rend_service_intro_established(circuit_t *circuit, const char *request,
+void rend_service_intro_has_opened(origin_circuit_t *circuit);
+int rend_service_intro_established(origin_circuit_t *circuit,
+ const char *request,
size_t request_len);
-void rend_service_rendezvous_has_opened(circuit_t *circuit);
-int rend_service_introduce(circuit_t *circuit, const char *request,
+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(circuit_t *oldcirc);
-int rend_service_set_connection_addr_port(connection_t *conn, circuit_t *circ);
+void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc);
+int rend_service_set_connection_addr_port(connection_t *conn,
+ origin_circuit_t *circ);
void rend_service_dump_stats(int severity);
void rend_service_free_all(void);
/********************************* rendmid.c *******************************/
-int rend_mid_establish_intro(circuit_t *circ, const char *request,
+int rend_mid_establish_intro(or_circuit_t *circ, const char *request,
size_t request_len);
-int rend_mid_introduce(circuit_t *circ, const char *request,
+int rend_mid_introduce(or_circuit_t *circ, const char *request,
size_t request_len);
-int rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
+int rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
size_t request_len);
-int rend_mid_rendezvous(circuit_t *circ, const char *request,
+int rend_mid_rendezvous(or_circuit_t *circ, const char *request,
size_t request_len);
/********************************* router.c ***************************/
diff --git a/src/or/relay.c b/src/or/relay.c
index 7dc7d3b7b5..997035fe22 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -191,18 +191,24 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
if (cell_direction == CELL_DIRECTION_OUT) {
cell->circ_id = circ->n_circ_id; /* switch it */
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;
} else {
- cell->circ_id = circ->p_circ_id; /* switch it */
- conn = circ->p_conn;
+ // XXXX NM WARN.
+ return 0;
}
if (!conn) {
- if (circ->rend_splice && cell_direction == CELL_DIRECTION_OUT) {
+ // XXXX Can this splice stuff be done more cleanly?
+ if (! CIRCUIT_IS_ORIGIN(circ) &&
+ TO_OR_CIRCUIT(circ)->rend_splice &&
+ cell_direction == CELL_DIRECTION_OUT) {
+ or_circuit_t *splice = TO_OR_CIRCUIT(circ)->rend_splice;
tor_assert(circ->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
- tor_assert(circ->rend_splice->purpose ==
- CIRCUIT_PURPOSE_REND_ESTABLISHED);
- cell->circ_id = circ->rend_splice->p_circ_id;
- if ((reason = circuit_receive_relay_cell(cell, circ->rend_splice,
+ tor_assert(splice->_base.purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
+ cell->circ_id = splice->p_circ_id;
+ if ((reason = circuit_receive_relay_cell(cell, TO_CIRCUIT(splice),
CELL_DIRECTION_IN)) < 0) {
log_warn(LD_REND, "Error relaying cell across rendezvous; closing "
"circuits");
@@ -244,7 +250,6 @@ static int
relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
crypt_path_t **layer_hint, char *recognized)
{
- crypt_path_t *thishop;
relay_header_t rh;
tor_assert(circ);
@@ -256,8 +261,8 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
if (cell_direction == CELL_DIRECTION_IN) {
if (CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit.
* We'll want to do layered decrypts. */
- tor_assert(circ->cpath);
- thishop = circ->cpath;
+ crypt_path_t *thishop, *cpath = TO_ORIGIN_CIRCUIT(circ)->cpath;
+ thishop = cpath;
if (thishop->state != CPATH_STATE_OPEN) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Relay cell before first created cell? Closing.");
@@ -280,11 +285,12 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
}
thishop = thishop->next;
- } while (thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN);
+ } while (thishop != cpath && thishop->state == CPATH_STATE_OPEN);
log_warn(LD_OR,"in-cell at OP not recognized. Closing.");
return -1;
} else { /* we're in the middle. Just one crypt. */
- if (relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
+ if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->p_crypto,
+ cell->payload, 1) < 0)
return -1;
// log_fn(LOG_DEBUG,"Skipping recognized check, because we're not "
// "the OP.");
@@ -292,13 +298,14 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
} else /* cell_direction == CELL_DIRECTION_OUT */ {
/* we're in the middle. Just one crypt. */
- if (relay_crypt_one_payload(circ->n_crypto, cell->payload, 0) < 0)
+ if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->n_crypto,
+ cell->payload, 0) < 0)
return -1;
relay_header_unpack(&rh, cell->payload);
if (rh.recognized == 0) {
/* it's possibly recognized. have to check digest to be sure. */
- if (relay_digest_matches(circ->n_digest, cell)) {
+ if (relay_digest_matches(TO_OR_CIRCUIT(circ)->n_digest, cell)) {
*recognized = 1;
return 0;
}
@@ -307,7 +314,7 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
return 0;
}
-/** Package a relay cell:
+/** Package a relay cell from an edge:
* - Encrypt it to the right layer
* - connection_or_write_cell_to_buf to the right conn
*/
@@ -317,11 +324,11 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
crypt_path_t *layer_hint)
{
connection_t *conn; /* where to send the cell */
- crypt_path_t *thishop; /* counter for repeated crypts */
if (cell_direction == CELL_DIRECTION_OUT) {
+ crypt_path_t *thishop; /* counter for repeated crypts */
conn = circ->n_conn;
- if (!conn) {
+ if (!CIRCUIT_IS_ORIGIN(circ) || !conn) {
log_warn(LD_BUG,"outgoing relay cell has n_conn==NULL. Dropping.");
return 0; /* just drop it */
}
@@ -338,18 +345,20 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
}
thishop = thishop->prev;
- } while (thishop != circ->cpath->prev);
+ } while (thishop != TO_ORIGIN_CIRCUIT(circ)->cpath->prev);
} else { /* incoming cell */
- conn = circ->p_conn;
- if (!conn) {
+ or_circuit_t *or_circ;
+ if (CIRCUIT_IS_ORIGIN(circ)) {
/* XXXX RD This is a bug, right? */
- log_warn(LD_BUG,"incoming relay cell has p_conn==NULL. Dropping.");
+ log_warn(LD_BUG,"incoming relay cell at origin circuit. Dropping.");
assert_circuit_ok(circ);
return 0; /* just drop it */
}
- relay_set_digest(circ->p_digest, cell);
- if (relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
+ or_circ = TO_OR_CIRCUIT(circ);
+ conn = or_circ->p_conn;
+ relay_set_digest(or_circ->p_digest, cell);
+ if (relay_crypt_one_payload(or_circ->p_crypto, cell->payload, 1) < 0)
return -1;
}
++stats_n_relay_cells_relayed;
@@ -375,25 +384,30 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
* that we allow rendezvous *to* an OP.
*/
- for (tmpconn = circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
- if (rh.stream_id == tmpconn->stream_id && !tmpconn->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))
+ 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) {
+ log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
return tmpconn;
+ }
}
- }
- for (tmpconn = circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
- if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
- log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
- return tmpconn;
+ } 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) {
+ log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
+ if (cell_direction == CELL_DIRECTION_OUT ||
+ connection_edge_is_rendezvous_stream(tmpconn))
+ return tmpconn;
+ }
}
- }
- for (tmpconn = circ->resolving_streams; tmpconn;
- tmpconn=tmpconn->next_stream) {
- if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
- log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
- return tmpconn;
+ for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn;
+ tmpconn=tmpconn->next_stream) {
+ if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
+ log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
+ return tmpconn;
+ }
}
}
return NULL; /* probably a begin relay cell */
@@ -445,6 +459,7 @@ connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
cell_t cell;
relay_header_t rh;
int cell_direction;
+ /* XXXX NM Split this function into a separate versions per circuit type? */
if (fromconn && fromconn->marked_for_close) {
log_warn(LD_BUG,
@@ -471,9 +486,11 @@ connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
if (cpath_layer) {
cell.circ_id = circ->n_circ_id;
cell_direction = CELL_DIRECTION_OUT;
- } else {
- cell.circ_id = circ->p_circ_id;
+ } else if (! CIRCUIT_IS_ORIGIN(circ)) {
+ cell.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
cell_direction = CELL_DIRECTION_IN;
+ } else {
+ return -1;
}
memset(&rh, 0, sizeof(rh));
@@ -647,7 +664,7 @@ edge_reason_is_retriable(int reason)
*/
static int
connection_edge_process_end_not_open(
- relay_header_t *rh, cell_t *cell, circuit_t *circ,
+ relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
connection_t *conn, crypt_path_t *layer_hint)
{
struct in_addr in;
@@ -716,8 +733,8 @@ connection_edge_process_end_not_open(
< MAX_RESOLVE_FAILURES) {
/* We haven't retried too many times; reattach the connection. */
circuit_log_path(LOG_INFO,LD_APP,circ);
- tor_assert(circ->timestamp_dirty);
- circ->timestamp_dirty -= get_options()->MaxCircuitDirtiness;
+ tor_assert(circ->_base.timestamp_dirty);
+ circ->_base.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
if (conn->chosen_exit_optional) { /* stop wanting a specific exit */
conn->chosen_exit_optional = 0;
@@ -780,11 +797,17 @@ 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)
{
- if (rh->command == RELAY_COMMAND_END)
- return connection_edge_process_end_not_open(rh, cell, circ, conn,
- layer_hint);
+ if (rh->command == RELAY_COMMAND_END) {
+ if (CIRCUIT_IS_ORIGIN(circ))
+ return connection_edge_process_end_not_open(rh, cell,
+ TO_ORIGIN_CIRCUIT(circ), conn,
+ layer_hint);
+ else
+ return 0;
+ }
if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) {
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
if (conn->state != AP_CONN_STATE_CONNECT_WAIT) {
log_warn(LD_APP,"Got 'connected' while not in state connect_wait. "
"Dropping.");
@@ -812,7 +835,7 @@ connection_edge_process_relay_cell_not_open(
client_dns_set_addressmap(conn->socks_request->address, addr,
conn->chosen_exit_name, ttl);
}
- circuit_log_path(LOG_INFO,LD_APP,circ);
+ circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_SUCCEEDED);
/* handle anything that might have queued */
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
@@ -967,16 +990,6 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (conn->socks_request && !conn->socks_request->has_finished)
log_warn(LD_BUG,
"Bug: open stream hasn't sent socks answer yet? Closing.");
-#ifdef HALF_OPEN
- conn->done_sending = 1;
- shutdown(conn->s, 1); /* XXX check return; refactor NM */
- if (conn->done_receiving) {
- /* We just *got* an end; no reason to send one. */
- conn->has_sent_end = 1;
- connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
- }
-#else
/* We just *got* an end; no reason to send one. */
conn->has_sent_end = 1;
if (!conn->marked_for_close) {
@@ -985,7 +998,6 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
}
-#endif
return 0;
case RELAY_COMMAND_EXTEND:
if (conn) {
@@ -1000,12 +1012,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
return 0;
}
log_debug(domain,"Got an extended cell! Yay.");
- if ((reason = circuit_finish_handshake(circ, CELL_CREATED,
+ if ((reason = circuit_finish_handshake(TO_ORIGIN_CIRCUIT(circ),
+ CELL_CREATED,
cell->payload+RELAY_HEADER_SIZE)) < 0) {
log_warn(domain,"circuit_finish_handshake failed.");
return reason;
}
- if ((reason=circuit_send_next_onion_skin(circ))<0) {
+ if ((reason=circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)))<0) {
log_info(domain,"circuit_send_next_onion_skin() failed.");
return reason;
}
@@ -1018,7 +1031,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (circ->n_conn) {
uint8_t reason = *(uint8_t*)(cell->payload + RELAY_HEADER_SIZE);
connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason);
- circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
+ circuit_set_n_circid_orconn(circ, 0, NULL);
}
log_debug(LD_EXIT, "Processed 'truncate', replying.");
{
@@ -1033,7 +1046,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
log_warn(LD_EXIT,"'truncated' unsupported at non-origin. Dropping.");
return 0;
}
- circuit_truncated(circ, layer_hint);
+ circuit_truncated(TO_ORIGIN_CIRCUIT(circ), layer_hint);
return 0;
case RELAY_COMMAND_CONNECTED:
if (conn) {
@@ -1083,7 +1096,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
circ->purpose);
return 0;
}
- connection_exit_begin_resolve(cell, circ);
+ connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ));
return 0;
case RELAY_COMMAND_RESOLVED:
if (conn) {
@@ -1252,10 +1265,12 @@ circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
log_debug(layer_hint?LD_APP:LD_EXIT,"resuming");
- /* have to check both n_streams and p_streams, to handle rendezvous */
- if (circuit_resume_edge_reading_helper(circ->n_streams, circ, layer_hint)
- >= 0)
- circuit_resume_edge_reading_helper(circ->p_streams, circ, layer_hint);
+ if (CIRCUIT_IS_ORIGIN(circ))
+ circuit_resume_edge_reading_helper(TO_ORIGIN_CIRCUIT(circ)->p_streams,
+ circ, layer_hint);
+ else
+ circuit_resume_edge_reading_helper(TO_OR_CIRCUIT(circ)->n_streams,
+ circ, layer_hint);
}
/** A helper function for circuit_resume_edge_reading() above.
@@ -1304,11 +1319,12 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
unsigned domain = layer_hint ? LD_APP : LD_EXIT;
if (!layer_hint) {
+ or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
log_debug(domain,"considering circ->package_window %d",
circ->package_window);
if (circ->package_window <= 0) {
log_debug(domain,"yes, not-at-origin. stopped.");
- for (conn = circ->n_streams; conn; conn=conn->next_stream)
+ for (conn = or_circ->n_streams; conn; conn=conn->next_stream)
connection_stop_reading(conn);
return 1;
}
@@ -1319,10 +1335,14 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
layer_hint->package_window);
if (layer_hint->package_window <= 0) {
log_debug(domain,"yes, at-origin. stopped.");
+#if 0
+ // XXXX NM DEAD CODE.
for (conn = circ->n_streams; conn; conn=conn->next_stream)
if (conn->cpath_layer == layer_hint)
connection_stop_reading(conn);
- for (conn = circ->p_streams; conn; conn=conn->next_stream)
+#endif
+ for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn;
+ conn=conn->next_stream)
if (conn->cpath_layer == layer_hint)
connection_stop_reading(conn);
return 1;
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 2b3f047450..e9bfe3ef93 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -14,10 +14,9 @@ const char rendclient_c_id[] =
/** Called when we've established a circuit to an introduction point:
* send the introduction request. */
void
-rend_client_introcirc_has_opened(circuit_t *circ)
+rend_client_introcirc_has_opened(origin_circuit_t *circ)
{
- tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
+ tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
tor_assert(circ->cpath);
log_info(LD_REND,"introcirc is open");
@@ -28,19 +27,19 @@ rend_client_introcirc_has_opened(circuit_t *circ)
* it fails, mark the circ for close and return -1. else return 0.
*/
static int
-rend_client_send_establish_rendezvous(circuit_t *circ)
+rend_client_send_establish_rendezvous(origin_circuit_t *circ)
{
- tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
+ tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
log_info(LD_REND, "Sending an ESTABLISH_RENDEZVOUS cell");
- if (crypto_rand(circ->rend_cookie, REND_COOKIE_LEN) < 0) {
+ if (crypto_rand(circ->_base.rend_cookie, REND_COOKIE_LEN) < 0) {
log_warn(LD_BUG, "Internal error: Couldn't produce random cookie.");
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return -1;
}
- if (connection_edge_send_command(NULL,circ,
+ if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
- circ->rend_cookie, REND_COOKIE_LEN,
+ circ->_base.rend_cookie, REND_COOKIE_LEN,
circ->cpath->prev)<0) {
/* circ is already marked for close */
log_warn(LD_GENERAL, "Couldn't send ESTABLISH_RENDEZVOUS cell");
@@ -54,7 +53,8 @@ rend_client_send_establish_rendezvous(circuit_t *circ)
* down introcirc if possible.
*/
int
-rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
+rend_client_send_introduction(origin_circuit_t *introcirc,
+ origin_circuit_t *rendcirc)
{
size_t payload_len;
int r;
@@ -64,15 +64,15 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
crypt_path_t *cpath;
off_t dh_offset;
- tor_assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
- tor_assert(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY);
- tor_assert(!rend_cmp_service_ids(introcirc->rend_query,
- rendcirc->rend_query));
+ tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
+ tor_assert(rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY);
+ tor_assert(!rend_cmp_service_ids(introcirc->_base.rend_query,
+ rendcirc->_base.rend_query));
- if (rend_cache_lookup_entry(introcirc->rend_query, -1, &entry) < 1) {
+ if (rend_cache_lookup_entry(introcirc->_base.rend_query, -1, &entry) < 1) {
log_warn(LD_REND,
"query %s didn't have valid rend desc in cache. Failing.",
- escaped_safe_str(introcirc->rend_query));
+ escaped_safe_str(introcirc->_base.rend_query));
goto err;
}
@@ -111,13 +111,15 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
klen = crypto_pk_asn1_encode(extend_info->onion_key, tmp+7+DIGEST_LEN+2,
sizeof(tmp)-(7+DIGEST_LEN+2));
set_uint16(tmp+7+DIGEST_LEN, htons(klen));
- memcpy(tmp+7+DIGEST_LEN+2+klen, rendcirc->rend_cookie, REND_COOKIE_LEN);
+ memcpy(tmp+7+DIGEST_LEN+2+klen, rendcirc->_base.rend_cookie,
+ REND_COOKIE_LEN);
dh_offset = 7+DIGEST_LEN+2+klen+REND_COOKIE_LEN;
} else {
/* Version 0. */
strncpy(tmp, rendcirc->build_state->chosen_exit->nickname,
(MAX_NICKNAME_LEN+1)); /* nul pads */
- memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->rend_cookie, REND_COOKIE_LEN);
+ memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->_base.rend_cookie,
+ REND_COOKIE_LEN);
dh_offset = MAX_NICKNAME_LEN+1+REND_COOKIE_LEN;
}
@@ -141,7 +143,7 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
tor_assert(DIGEST_LEN + r <= RELAY_PAYLOAD_SIZE); /* we overran something */
payload_len = DIGEST_LEN + r;
- if (connection_edge_send_command(NULL, introcirc,
+ if (connection_edge_send_command(NULL, TO_CIRCUIT(introcirc),
RELAY_COMMAND_INTRODUCE1,
payload, payload_len,
introcirc->cpath->prev)<0) {
@@ -151,22 +153,21 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
}
/* Now, we wait for an ACK or NAK on this circuit. */
- introcirc->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
+ introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
return 0;
err:
- circuit_mark_for_close(introcirc, END_CIRC_AT_ORIGIN);
- circuit_mark_for_close(rendcirc, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_AT_ORIGIN);
return -1;
}
/** Called when a rendezvous circuit is open; sends a establish
* rendezvous circuit as appropriate. */
void
-rend_client_rendcirc_has_opened(circuit_t *circ)
+rend_client_rendcirc_has_opened(origin_circuit_t *circ)
{
- tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
- tor_assert(CIRCUIT_IS_ORIGIN(circ));
+ tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
log_info(LD_REND,"rendcirc is open");
@@ -179,17 +180,17 @@ rend_client_rendcirc_has_opened(circuit_t *circ)
/** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell.
*/
int
-rend_client_introduction_acked(circuit_t *circ,
+rend_client_introduction_acked(origin_circuit_t *circ,
const char *request, size_t request_len)
{
circuit_t *rendcirc;
(void) request; // XXXX Use this.
- if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
+ if (circ->_base.purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
log_warn(LD_PROTOCOL,
"Received REND_INTRODUCE_ACK on unexpected circuit %d.",
- circ->n_circ_id);
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circ->_base.n_circ_id);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return -1;
}
@@ -203,40 +204,40 @@ rend_client_introduction_acked(circuit_t *circ,
*/
log_info(LD_REND,"Received ack. Telling rend circ...");
rendcirc = circuit_get_by_rend_query_and_purpose(
- circ->rend_query, CIRCUIT_PURPOSE_C_REND_READY);
+ circ->_base.rend_query, CIRCUIT_PURPOSE_C_REND_READY);
if (rendcirc) { /* remember the ack */
rendcirc->purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
} else {
log_info(LD_REND,"...Found no rend circ. Dropping on the floor.");
}
/* close the circuit: we won't need it anymore. */
- circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED;
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED;
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
} else {
/* It's a NAK; the introduction point didn't relay our request. */
- circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
+ circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
/* Remove this intro point from the set of viable introduction
* points. If any remain, extend to a new one and try again.
* If none remain, refetch the service descriptor.
*/
if (rend_client_remove_intro_point(circ->build_state->chosen_exit,
- circ->rend_query) > 0) {
+ circ->_base.rend_query) > 0) {
/* There are introduction points left. Re-extend the circuit to
* another intro point and try again. */
extend_info_t *extend_info;
int result;
- extend_info = rend_client_get_random_intro(circ->rend_query);
+ extend_info = rend_client_get_random_intro(circ->_base.rend_query);
if (!extend_info) {
log_warn(LD_REND, "No introduction points left for %s. Closing.",
- escaped_safe_str(circ->rend_query));
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ escaped_safe_str(circ->_base.rend_query));
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return -1;
}
log_info(LD_REND,
"Got nack for %s from %s. Re-extending circ %d, "
"this time to %s.",
- escaped_safe_str(circ->rend_query),
- circ->build_state->chosen_exit->nickname, circ->n_circ_id,
+ escaped_safe_str(circ->_base.rend_query),
+ circ->build_state->chosen_exit->nickname, circ->_base.n_circ_id,
extend_info->nickname);
result = circuit_extend_to_new_exit(circ, extend_info);
extend_info_free(extend_info);
@@ -340,38 +341,38 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query)
* the circuit to C_REND_READY.
*/
int
-rend_client_rendezvous_acked(circuit_t *circ, const char *request,
+rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
size_t request_len)
{
(void) request;
(void) request_len;
/* we just got an ack for our establish-rendezvous. switch purposes. */
- if (circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
+ if (circ->_base.purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
log_warn(LD_PROTOCOL,"Got a rendezvous ack when we weren't expecting one. "
"Closing circ.");
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return -1;
}
log_info(LD_REND,"Got rendezvous ack. This circuit is now ready for "
"rendezvous.");
- circ->purpose = CIRCUIT_PURPOSE_C_REND_READY;
+ circ->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY;
return 0;
}
/** Bob sent us a rendezvous cell; join the circuits. */
int
-rend_client_receive_rendezvous(circuit_t *circ, const char *request,
+rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
size_t request_len)
{
crypt_path_t *hop;
char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN];
- if ((circ->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
- circ->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)
+ if ((circ->_base.purpose != CIRCUIT_PURPOSE_C_REND_READY &&
+ circ->_base.purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)
|| !circ->build_state->pending_final_cpath) {
log_warn(LD_PROTOCOL,"Got rendezvous2 cell from hidden service, but not "
"expecting it. Closing.");
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return -1;
}
@@ -405,7 +406,7 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request,
hop->dh_handshake_state = NULL;
/* All is well. Extend the circuit. */
- circ->purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
+ circ->_base.purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
hop->state = CPATH_STATE_OPEN;
/* set the windows to default. these are the windows
* that alice thinks bob has.
@@ -417,7 +418,7 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request,
circ->build_state->pending_final_cpath = NULL; /* prevent double-free */
return 0;
err:
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
return -1;
}
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index 1d5ce9c848..ab38e9f3a6 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -432,34 +432,41 @@ void
rend_process_relay_cell(circuit_t *circ, int command, size_t length,
const char *payload)
{
+ or_circuit_t *or_circ = NULL;
+ origin_circuit_t *origin_circ = NULL;
int r;
+ if (CIRCUIT_IS_ORIGIN(circ))
+ origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ else
+ or_circ = TO_OR_CIRCUIT(circ);
+
switch (command) {
case RELAY_COMMAND_ESTABLISH_INTRO:
- r = rend_mid_establish_intro(circ,payload,length);
+ r = rend_mid_establish_intro(or_circ,payload,length);
break;
case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
- r = rend_mid_establish_rendezvous(circ,payload,length);
+ r = rend_mid_establish_rendezvous(or_circ,payload,length);
break;
case RELAY_COMMAND_INTRODUCE1:
- r = rend_mid_introduce(circ,payload,length);
+ r = rend_mid_introduce(or_circ,payload,length);
break;
case RELAY_COMMAND_INTRODUCE2:
- r = rend_service_introduce(circ,payload,length);
+ r = rend_service_introduce(origin_circ,payload,length);
break;
case RELAY_COMMAND_INTRODUCE_ACK:
- r = rend_client_introduction_acked(circ,payload,length);
+ r = rend_client_introduction_acked(origin_circ,payload,length);
break;
case RELAY_COMMAND_RENDEZVOUS1:
- r = rend_mid_rendezvous(circ,payload,length);
+ r = rend_mid_rendezvous(or_circ,payload,length);
break;
case RELAY_COMMAND_RENDEZVOUS2:
- r = rend_client_receive_rendezvous(circ,payload,length);
+ r = rend_client_receive_rendezvous(origin_circ,payload,length);
break;
case RELAY_COMMAND_INTRO_ESTABLISHED:
- r = rend_service_intro_established(circ,payload,length);
+ r = rend_service_intro_established(origin_circ,payload,length);
break;
case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
- r = rend_client_rendezvous_acked(circ,payload,length);
+ r = rend_client_rendezvous_acked(origin_circ,payload,length);
break;
default:
tor_assert(0);
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index c1252289bc..21189eb2ce 100644
--- a/src/or/rendmid.c
+++ b/src/or/rendmid.c
@@ -15,7 +15,7 @@ const char rendmid_c_id[] =
* setting the circuit's purpose and service pk digest.
*/
int
-rend_mid_establish_intro(circuit_t *circ, const char *request,
+rend_mid_establish_intro(or_circuit_t *circ, const char *request,
size_t request_len)
{
crypto_pk_env_t *pk = NULL;
@@ -31,7 +31,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
"Received an ESTABLISH_INTRO request on circuit %d",
circ->p_circ_id);
- if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
+ if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Rejecting ESTABLISH_INTRO on non-OR or non-edge circuit.");
reason = END_CIRC_REASON_TORPROTOCOL;
@@ -89,13 +89,13 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
c = NULL;
while ((c = circuit_get_next_by_pk_and_purpose(
c,pk_digest,CIRCUIT_PURPOSE_INTRO_POINT))) {
- log_info(LD_REND, "Replacing old circuit %d for service %s",
- c->p_circ_id, safe_str(serviceid));
+ log_info(LD_REND, "Replacing old circuit for service %s",
+ safe_str(serviceid));
circuit_mark_for_close(c, END_CIRC_REASON_REQUESTED);
}
/* Acknowledge the request. */
- if (connection_edge_send_command(NULL,circ,
+ if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
RELAY_COMMAND_INTRO_ESTABLISHED,
"", 0, NULL)<0) {
log_info(LD_GENERAL, "Couldn't send INTRO_ESTABLISHED cell.");
@@ -103,8 +103,8 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
}
/* Now, set up this circuit. */
- circ->purpose = CIRCUIT_PURPOSE_INTRO_POINT;
- memcpy(circ->rend_pk_digest, pk_digest, DIGEST_LEN);
+ circ->_base.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
+ memcpy(circ->_base.rend_pk_digest, pk_digest, DIGEST_LEN);
log_info(LD_REND,
"Established introduction point on circuit %d for service %s",
@@ -116,7 +116,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
reason = END_CIRC_REASON_TORPROTOCOL;
err:
if (pk) crypto_free_pk_env(pk);
- circuit_mark_for_close(circ, reason);
+ circuit_mark_for_close(TO_CIRCUIT(circ), reason);
return -1;
}
@@ -125,20 +125,23 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
* INTRODUCE2 cell.
*/
int
-rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
+rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
{
circuit_t *intro_circ;
char serviceid[REND_SERVICE_ID_LEN+1];
char nak_body[1];
- if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
+ if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
log_warn(LD_PROTOCOL,
"Rejecting INTRODUCE1 on non-OR or non-edge circuit %d.",
circ->p_circ_id);
goto err;
}
- /* change to MAX_HEX_NICKNAME_LEN once 0.0.9.x is obsolete */
+ /* We could change this to MAX_HEX_NICKNAME_LEN now that 0.0.9.x is
+ * obsolete; however, there isn't much reason to do so, and we're going
+ * to revise this protocol anyway.
+ */
if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+
DH_KEY_LEN+CIPHER_KEY_LEN+PKCS1_OAEP_PADDING_OVERHEAD)) {
log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %d; "
@@ -152,7 +155,7 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
/* The first 20 bytes are all we look at: they have a hash of Bob's PK. */
intro_circ = circuit_get_next_by_pk_and_purpose(
NULL, request, CIRCUIT_PURPOSE_INTRO_POINT);
- if (!intro_circ) {
+ if (!intro_circ || CIRCUIT_IS_ORIGIN(intro_circ)) {
log_info(LD_REND,
"No intro circ found for INTRODUCE1 cell (%s) from circuit %d; "
"responding with nack.",
@@ -163,7 +166,8 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
log_info(LD_REND,
"Sending introduction request for service %s "
"from circ %d to circ %d",
- safe_str(serviceid), circ->p_circ_id, intro_circ->p_circ_id);
+ safe_str(serviceid), circ->p_circ_id,
+ TO_OR_CIRCUIT(intro_circ)->p_circ_id);
/* Great. Now we just relay the cell down the circuit. */
if (connection_edge_send_command(NULL, intro_circ,
@@ -174,10 +178,11 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
goto err;
}
/* And sent an ack down Alice's circuit. Empty body means succeeded. */
- if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK,
+ if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
+ RELAY_COMMAND_INTRODUCE_ACK,
NULL,0,NULL)) {
log_warn(LD_GENERAL, "Unable to send INTRODUCE_ACK cell to Tor client.");
- circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return -1;
}
@@ -185,11 +190,12 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
err:
/* Send the client an NACK */
nak_body[0] = 1;
- if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK,
+ if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
+ RELAY_COMMAND_INTRODUCE_ACK,
nak_body, 1, NULL)) {
log_warn(LD_GENERAL, "Unable to send NAK to Tor client.");
/* Is this right? */
- circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
}
return -1;
}
@@ -198,13 +204,13 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
* rendezvous cookie.
*/
int
-rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
+rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
size_t request_len)
{
char hexid[9];
int reason = END_CIRC_REASON_TORPROTOCOL;
- if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
+ if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
log_warn(LD_PROTOCOL,
"Tried to establish rendezvous on non-OR or non-edge circuit.");
goto err;
@@ -222,7 +228,7 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
}
/* Acknowledge the request. */
- if (connection_edge_send_command(NULL,circ,
+ if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
"", 0, NULL)<0) {
log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
@@ -230,8 +236,8 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
goto err;
}
- circ->purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
- memcpy(circ->rend_cookie, request, REND_COOKIE_LEN);
+ circ->_base.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
+ memcpy(circ->_base.rend_cookie, request, REND_COOKIE_LEN);
base16_encode(hexid,9,request,4);
@@ -241,7 +247,7 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
return 0;
err:
- circuit_mark_for_close(circ, reason);
+ circuit_mark_for_close(TO_CIRCUIT(circ), reason);
return -1;
}
@@ -250,9 +256,10 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
* connecting the two circuits.
*/
int
-rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
+rend_mid_rendezvous(or_circuit_t *circ, const char *request,
+ size_t request_len)
{
- circuit_t *rend_circ;
+ or_circuit_t *rend_circ;
char hexid[9];
int reason = END_CIRC_REASON_INTERNAL;
base16_encode(hexid,9,request,request_len<4?request_len:4);
@@ -263,7 +270,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
circ->p_circ_id, hexid);
}
- if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
+ if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
log_info(LD_REND,
"Tried to complete rendezvous on non-OR or non-edge circuit %d.",
circ->p_circ_id);
@@ -289,7 +296,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
}
/* Send the RENDEZVOUS2 cell to Alice. */
- if (connection_edge_send_command(NULL, rend_circ,
+ if (connection_edge_send_command(NULL, TO_CIRCUIT(rend_circ),
RELAY_COMMAND_RENDEZVOUS2,
request+REND_COOKIE_LEN,
request_len-REND_COOKIE_LEN, NULL)) {
@@ -304,16 +311,16 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
"Completing rendezvous: circuit %d joins circuit %d (cookie %s)",
circ->p_circ_id, rend_circ->p_circ_id, hexid);
- circ->purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
- rend_circ->purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
- memset(circ->rend_cookie, 0, REND_COOKIE_LEN);
+ circ->_base.purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
+ rend_circ->_base.purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
+ memset(circ->_base.rend_cookie, 0, REND_COOKIE_LEN);
rend_circ->rend_splice = circ;
circ->rend_splice = rend_circ;
return 0;
err:
- circuit_mark_for_close(circ, reason);
+ circuit_mark_for_close(TO_CIRCUIT(circ), reason);
return -1;
}
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index ce3ca478c7..0dd417c7ad 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -11,8 +11,8 @@ const char rendservice_c_id[] =
#include "or.h"
-static circuit_t *find_intro_circuit(routerinfo_t *router,
- const char *pk_digest);
+static origin_circuit_t *find_intro_circuit(routerinfo_t *router,
+ const char *pk_digest);
/** Represents the mapping from a virtual port of a rendezvous service to
* a real port on some IP.
@@ -285,7 +285,7 @@ static void
rend_service_update_descriptor(rend_service_t *service)
{
rend_service_descriptor_t *d;
- circuit_t *circ;
+ origin_circuit_t *circ;
int i,n;
routerinfo_t *router;
@@ -310,7 +310,7 @@ rend_service_update_descriptor(rend_service_t *service)
continue;
}
circ = find_intro_circuit(router, service->pk_digest);
- if (circ && circ->purpose == CIRCUIT_PURPOSE_S_INTRO) {
+ if (circ && circ->_base.purpose == CIRCUIT_PURPOSE_S_INTRO) {
/* We have an entirely established intro circuit. */
d->intro_points[d->n_intro_points] = tor_strdup(router->nickname);
d->intro_point_extend_info[d->n_intro_points] =
@@ -410,7 +410,7 @@ rend_service_requires_uptime(rend_service_t *service)
* rendezvous point.
*/
int
-rend_service_introduce(circuit_t *circuit, const char *request,
+rend_service_introduce(origin_circuit_t *circuit, const char *request,
size_t request_len)
{
char *ptr, *r_cookie;
@@ -421,21 +421,21 @@ rend_service_introduce(circuit_t *circuit, const char *request,
int r, i;
size_t len, keylen;
crypto_dh_env_t *dh = NULL;
- circuit_t *launched = NULL;
+ origin_circuit_t *launched = NULL;
crypt_path_t *cpath = NULL;
char serviceid[REND_SERVICE_ID_LEN+1];
char hexcookie[9];
int circ_needs_uptime;
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
- circuit->rend_pk_digest,10);
+ circuit->_base.rend_pk_digest,10);
log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %d.",
- escaped(serviceid), circuit->n_circ_id);
+ escaped(serviceid), circuit->_base.n_circ_id);
- if (circuit->purpose != CIRCUIT_PURPOSE_S_INTRO) {
+ if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) {
log_warn(LD_PROTOCOL,
"Got an INTRODUCE2 over a non-introduction circuit %d.",
- circuit->n_circ_id);
+ circuit->_base.n_circ_id);
return -1;
}
@@ -443,7 +443,7 @@ rend_service_introduce(circuit_t *circuit, const char *request,
if (request_len < DIGEST_LEN+REND_COOKIE_LEN+(MAX_NICKNAME_LEN+1)+
DH_KEY_LEN+42) {
log_warn(LD_PROTOCOL, "Got a truncated INTRODUCE2 cell on circ %d.",
- circuit->n_circ_id);
+ circuit->_base.n_circ_id);
return -1;
}
@@ -454,7 +454,7 @@ rend_service_introduce(circuit_t *circuit, const char *request,
escaped(serviceid));
return -1;
}
- if (memcmp(circuit->rend_pk_digest, request, DIGEST_LEN)) {
+ if (memcmp(circuit->_base.rend_pk_digest, request, DIGEST_LEN)) {
base32_encode(serviceid, REND_SERVICE_ID_LEN+1, request, 10);
log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).",
escaped(serviceid));
@@ -589,11 +589,11 @@ rend_service_introduce(circuit_t *circuit, const char *request,
extend_info->nickname, hexcookie, serviceid);
tor_assert(launched->build_state);
/* Fill in the circuit's state. */
- memcpy(launched->rend_pk_digest, circuit->rend_pk_digest,
+ memcpy(launched->_base.rend_pk_digest, circuit->_base.rend_pk_digest,
DIGEST_LEN);
- memcpy(launched->rend_cookie, r_cookie, REND_COOKIE_LEN);
- strlcpy(launched->rend_query, service->service_id,
- sizeof(launched->rend_query));
+ memcpy(launched->_base.rend_cookie, r_cookie, REND_COOKIE_LEN);
+ strlcpy(launched->_base.rend_query, service->service_id,
+ sizeof(launched->_base.rend_query));
launched->build_state->pending_final_cpath = cpath =
tor_malloc_zero(sizeof(crypt_path_t));
cpath->magic = CRYPT_PATH_MAGIC;
@@ -609,7 +609,8 @@ rend_service_introduce(circuit_t *circuit, const char *request,
return 0;
err:
if (dh) crypto_dh_free(dh);
- if (launched) circuit_mark_for_close(launched, END_CIRC_AT_ORIGIN);
+ if (launched)
+ circuit_mark_for_close(TO_CIRCUIT(launched), END_CIRC_AT_ORIGIN);
if (extend_info) extend_info_free(extend_info);
return -1;
}
@@ -618,12 +619,12 @@ rend_service_introduce(circuit_t *circuit, const char *request,
* than the last hop: launches a new circuit to the same rendezvous point.
*/
void
-rend_service_relaunch_rendezvous(circuit_t *oldcirc)
+rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
{
- circuit_t *newcirc;
+ origin_circuit_t *newcirc;
cpath_build_state_t *newstate, *oldstate;
- tor_assert(oldcirc->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
+ tor_assert(oldcirc->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
if (!oldcirc->build_state ||
oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
@@ -662,9 +663,12 @@ rend_service_relaunch_rendezvous(circuit_t *oldcirc)
newstate->pending_final_cpath = oldstate->pending_final_cpath;
oldstate->pending_final_cpath = NULL;
- memcpy(newcirc->rend_query, oldcirc->rend_query, REND_SERVICE_ID_LEN+1);
- memcpy(newcirc->rend_pk_digest, oldcirc->rend_pk_digest, DIGEST_LEN);
- memcpy(newcirc->rend_cookie, oldcirc->rend_cookie, REND_COOKIE_LEN);
+ memcpy(newcirc->_base.rend_query, oldcirc->_base.rend_query,
+ REND_SERVICE_ID_LEN+1);
+ memcpy(newcirc->_base.rend_pk_digest, oldcirc->_base.rend_pk_digest,
+ DIGEST_LEN);
+ memcpy(newcirc->_base.rend_cookie, oldcirc->_base.rend_cookie,
+ REND_COOKIE_LEN);
}
/** Launch a circuit to serve as an introduction point for the service
@@ -674,7 +678,7 @@ static int
rend_service_launch_establish_intro(rend_service_t *service,
const char *nickname)
{
- circuit_t *launched;
+ origin_circuit_t *launched;
log_info(LD_REND,
"Launching circuit to introduction point %s for service %s",
@@ -691,11 +695,11 @@ rend_service_launch_establish_intro(rend_service_t *service,
nickname);
return -1;
}
- strlcpy(launched->rend_query, service->service_id,
- sizeof(launched->rend_query));
- memcpy(launched->rend_pk_digest, service->pk_digest, DIGEST_LEN);
+ strlcpy(launched->_base.rend_query, service->service_id,
+ sizeof(launched->_base.rend_query));
+ memcpy(launched->_base.rend_pk_digest, service->pk_digest, DIGEST_LEN);
- if (launched->state == CIRCUIT_STATE_OPEN)
+ if (launched->_base.state == CIRCUIT_STATE_OPEN)
rend_service_intro_has_opened(launched);
return 0;
}
@@ -704,7 +708,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
* sends a RELAY_ESTABLISH_INTRO cell.
*/
void
-rend_service_intro_has_opened(circuit_t *circuit)
+rend_service_intro_has_opened(origin_circuit_t *circuit)
{
rend_service_t *service;
size_t len;
@@ -713,23 +717,22 @@ rend_service_intro_has_opened(circuit_t *circuit)
char auth[DIGEST_LEN + 9];
char serviceid[REND_SERVICE_ID_LEN+1];
- tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
- tor_assert(CIRCUIT_IS_ORIGIN(circuit));
+ tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
tor_assert(circuit->cpath);
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
- circuit->rend_pk_digest,10);
+ circuit->_base.rend_pk_digest,10);
- service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
+ service = rend_service_get_by_pk_digest(circuit->_base.rend_pk_digest);
if (!service) {
log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.",
- serviceid, circuit->n_circ_id);
+ serviceid, circuit->_base.n_circ_id);
goto err;
}
log_info(LD_REND,
"Established circuit %d as introduction point for service %s",
- circuit->n_circ_id, serviceid);
+ circuit->_base.n_circ_id, serviceid);
/* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
len = crypto_pk_asn1_encode(service->private_key, buf+2,
@@ -748,47 +751,48 @@ rend_service_intro_has_opened(circuit_t *circuit)
}
len += r;
- if (connection_edge_send_command(NULL, circuit,RELAY_COMMAND_ESTABLISH_INTRO,
+ if (connection_edge_send_command(NULL, TO_CIRCUIT(circuit),
+ RELAY_COMMAND_ESTABLISH_INTRO,
buf, len, circuit->cpath->prev)<0) {
log_info(LD_GENERAL,
"Couldn't send introduction request for service %s on circuit %d",
- serviceid, circuit->n_circ_id);
+ serviceid, circuit->_base.n_circ_id);
goto err;
}
return;
err:
- circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
}
/** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
* live introduction point, and note that the service descriptor is
* now out-of-date.*/
int
-rend_service_intro_established(circuit_t *circuit, const char *request,
+rend_service_intro_established(origin_circuit_t *circuit, const char *request,
size_t request_len)
{
rend_service_t *service;
(void) request;
(void) request_len;
- if (circuit->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
+ if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
log_warn(LD_PROTOCOL,
"received INTRO_ESTABLISHED cell on non-intro circuit.");
goto err;
}
- service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
+ service = rend_service_get_by_pk_digest(circuit->_base.rend_pk_digest);
if (!service) {
log_warn(LD_REND, "Unknown service on introduction circuit %d.",
- circuit->n_circ_id);
+ circuit->_base.n_circ_id);
goto err;
}
service->desc_is_dirty = time(NULL);
- circuit->purpose = CIRCUIT_PURPOSE_S_INTRO;
+ circuit->_base.purpose = CIRCUIT_PURPOSE_S_INTRO;
return 0;
err:
- circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
return -1;
}
@@ -796,7 +800,7 @@ rend_service_intro_established(circuit_t *circuit, const char *request,
* RELAY_COMMAND_RENDEZVOUS1 cell.
*/
void
-rend_service_rendezvous_has_opened(circuit_t *circuit)
+rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
{
rend_service_t *service;
char buf[RELAY_PAYLOAD_SIZE];
@@ -804,22 +808,22 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
char serviceid[REND_SERVICE_ID_LEN+1];
char hexcookie[9];
- tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
+ tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
tor_assert(circuit->cpath);
tor_assert(circuit->build_state);
hop = circuit->build_state->pending_final_cpath;
tor_assert(hop);
- base16_encode(hexcookie,9,circuit->rend_cookie,4);
+ base16_encode(hexcookie,9,circuit->_base.rend_cookie,4);
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
- circuit->rend_pk_digest,10);
+ circuit->_base.rend_pk_digest,10);
log_info(LD_REND,
"Done building circuit %d to rendezvous with "
"cookie %s for service %s",
- circuit->n_circ_id, hexcookie, serviceid);
+ circuit->_base.n_circ_id, hexcookie, serviceid);
- service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
+ service = rend_service_get_by_pk_digest(circuit->_base.rend_pk_digest);
if (!service) {
log_warn(LD_GENERAL, "Internal error: unrecognized service ID on "
"introduction circuit.");
@@ -827,7 +831,7 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
}
/* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
- memcpy(buf, circuit->rend_cookie, REND_COOKIE_LEN);
+ memcpy(buf, circuit->_base.rend_cookie, REND_COOKIE_LEN);
if (crypto_dh_get_public(hop->dh_handshake_state,
buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
log_warn(LD_GENERAL,"Couldn't get DH public key.");
@@ -837,7 +841,8 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
DIGEST_LEN);
/* Send the cell */
- if (connection_edge_send_command(NULL, circuit, RELAY_COMMAND_RENDEZVOUS1,
+ if (connection_edge_send_command(NULL, TO_CIRCUIT(circuit),
+ RELAY_COMMAND_RENDEZVOUS1,
buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
circuit->cpath->prev)<0) {
log_warn(LD_GENERAL, "Couldn't send RENDEZVOUS1 cell.");
@@ -859,11 +864,11 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
/* Change the circuit purpose. */
- circuit->purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
+ circuit->_base.purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
return;
err:
- circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
}
/*
@@ -874,28 +879,31 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
* <b>router</b> for the service whose public key is <b>pk_digest</b>. Return
* NULL if no such service is found.
*/
-static circuit_t *
+static origin_circuit_t *
find_intro_circuit(routerinfo_t *router, const char *pk_digest)
{
circuit_t *circ = NULL;
+ cpath_build_state_t *build_state = NULL;
tor_assert(router);
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
CIRCUIT_PURPOSE_S_INTRO))) {
- tor_assert(circ->cpath);
- if (!strcasecmp(circ->build_state->chosen_exit->nickname,
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
+ build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
+ if (!strcasecmp(build_state->chosen_exit->nickname,
router->nickname)) {
- return circ;
+ return TO_ORIGIN_CIRCUIT(circ);
}
}
circ = NULL;
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
- tor_assert(circ->cpath);
- if (!strcasecmp(circ->build_state->chosen_exit->nickname,
+ tor_assert(CIRCUIT_IS_ORIGIN(circ));
+ build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
+ if (!strcasecmp(build_state->chosen_exit->nickname,
router->nickname)) {
- return circ;
+ return TO_ORIGIN_CIRCUIT(circ);
}
}
return NULL;
@@ -1088,7 +1096,7 @@ rend_service_dump_stats(int severity)
routerinfo_t *router;
rend_service_t *service;
char *nickname;
- circuit_t *circ;
+ origin_circuit_t *circ;
for (i=0; i < smartlist_len(rend_service_list); ++i) {
service = smartlist_get(rend_service_list, i);
@@ -1108,7 +1116,7 @@ rend_service_dump_stats(int severity)
continue;
}
log(severity, LD_GENERAL, " Intro point at %s: circuit is %s",nickname,
- circuit_state_to_string(circ->state));
+ circuit_state_to_string(circ->_base.state));
}
}
}
@@ -1119,22 +1127,23 @@ rend_service_dump_stats(int severity)
* or 0 for success.
*/
int
-rend_service_set_connection_addr_port(connection_t *conn, circuit_t *circ)
+rend_service_set_connection_addr_port(connection_t *conn,
+ origin_circuit_t *circ)
{
rend_service_t *service;
int i;
rend_service_port_config_t *p;
char serviceid[REND_SERVICE_ID_LEN+1];
- tor_assert(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
+ tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
log_debug(LD_REND,"beginning to hunt for addr/port");
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
- circ->rend_pk_digest,10);
- service = rend_service_get_by_pk_digest(circ->rend_pk_digest);
+ circ->_base.rend_pk_digest,10);
+ service = rend_service_get_by_pk_digest(circ->_base.rend_pk_digest);
if (!service) {
log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
"rendezvous circuit %d; closing.",
- serviceid, circ->n_circ_id);
+ serviceid, circ->_base.n_circ_id);
return -1;
}
for (i = 0; i < smartlist_len(service->ports); ++i) {