[tor-commits] [tor/master] Split channel_t into channel_t and channel_listener_t; get rid of that big union
andrea at torproject.org
andrea at torproject.org
Thu Oct 11 02:05:23 UTC 2012
commit 3f4b95b1a32787464b5877c7d21474801d4b944c
Author: Andrea Shepard <andrea at torproject.org>
Date: Tue Oct 9 00:51:33 2012 -0700
Split channel_t into channel_t and channel_listener_t; get rid of that big union
---
src/or/channel.c | 2123 ++++++++++++++++++++++++++++------------------
src/or/channel.h | 419 ++++++----
src/or/channeltls.c | 241 +++---
src/or/channeltls.h | 4 +-
src/or/circuitbuild.c | 31 +-
src/or/circuitlist.c | 19 +-
src/or/circuituse.c | 5 +-
src/or/command.c | 17 +-
src/or/command.h | 2 +-
src/or/connection_edge.c | 3 +-
src/or/connection_or.c | 14 +-
src/or/main.c | 2 +
src/or/or.h | 65 ++-
src/or/relay.c | 68 +-
14 files changed, 1788 insertions(+), 1225 deletions(-)
diff --git a/src/or/channel.c b/src/or/channel.c
index 57b9e4f..278daa6 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -55,12 +55,18 @@ static smartlist_t *all_channels = NULL;
/* All channel_t instances not in ERROR or CLOSED states */
static smartlist_t *active_channels = NULL;
-/* All channel_t instances in LISTENING state */
-static smartlist_t *listening_channels = NULL;
-
/* All channel_t instances in ERROR or CLOSED states */
static smartlist_t *finished_channels = NULL;
+/* All channel_listener_t instances */
+static smartlist_t *all_listeners = NULL;
+
+/* All channel_listener_t instances in LISTENING state */
+static smartlist_t *active_listeners = NULL;
+
+/* All channel_listener_t instances in LISTENING state */
+static smartlist_t *finished_listeners = NULL;
+
/* Counter for ID numbers */
static uint64_t n_channels_allocated = 0;
@@ -89,6 +95,11 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
ssize_t num_cells);
static void channel_force_free(channel_t *chan);
static void
+channel_free_list(smartlist_t *channels, int mark_for_close);
+static void
+channel_listener_free_list(smartlist_t *channels, int mark_for_close);
+static void channel_listener_force_free(channel_listener_t *chan_l);
+static void
channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q);
/***********************************
@@ -108,7 +119,6 @@ channel_state_is_valid(channel_state_t state)
case CHANNEL_STATE_CLOSED:
case CHANNEL_STATE_CLOSING:
case CHANNEL_STATE_ERROR:
- case CHANNEL_STATE_LISTENING:
case CHANNEL_STATE_MAINT:
case CHANNEL_STATE_OPENING:
case CHANNEL_STATE_OPEN:
@@ -123,6 +133,30 @@ channel_state_is_valid(channel_state_t state)
}
/**
+ * Indicate whether a given channel listener state is valid
+ */
+
+int
+channel_listener_state_is_valid(channel_listener_state_t state)
+{
+ int is_valid;
+
+ switch (state) {
+ case CHANNEL_LISTENER_STATE_CLOSED:
+ case CHANNEL_LISTENER_STATE_LISTENING:
+ case CHANNEL_LISTENER_STATE_CLOSING:
+ case CHANNEL_LISTENER_STATE_ERROR:
+ is_valid = 1;
+ break;
+ case CHANNEL_LISTENER_STATE_LAST:
+ default:
+ is_valid = 0;
+ }
+
+ return is_valid;
+}
+
+/**
* Indicate whether a channel state transition is valid
*
* This function takes two channel states and indicates whether a
@@ -137,8 +171,7 @@ channel_state_can_transition(channel_state_t from, channel_state_t to)
switch (from) {
case CHANNEL_STATE_CLOSED:
- is_valid = (to == CHANNEL_STATE_LISTENING ||
- to == CHANNEL_STATE_OPENING);
+ is_valid = (to == CHANNEL_STATE_OPENING);
break;
case CHANNEL_STATE_CLOSING:
is_valid = (to == CHANNEL_STATE_CLOSED ||
@@ -147,10 +180,6 @@ channel_state_can_transition(channel_state_t from, channel_state_t to)
case CHANNEL_STATE_ERROR:
is_valid = 0;
break;
- case CHANNEL_STATE_LISTENING:
- is_valid = (to == CHANNEL_STATE_CLOSING ||
- to == CHANNEL_STATE_ERROR);
- break;
case CHANNEL_STATE_MAINT:
is_valid = (to == CHANNEL_STATE_CLOSING ||
to == CHANNEL_STATE_ERROR ||
@@ -175,6 +204,43 @@ channel_state_can_transition(channel_state_t from, channel_state_t to)
}
/**
+ * Indicate whether a channel listener state transition is valid
+ *
+ * This function takes two channel listener states and indicates whether a
+ * transition between them is permitted (see the state definitions and
+ * transition table in or.h at the channel_listener_state_t typedef).
+ */
+
+int
+channel_listener_state_can_transition(channel_listener_state_t from,
+ channel_listener_state_t to)
+{
+ int is_valid;
+
+ switch (from) {
+ case CHANNEL_LISTENER_STATE_CLOSED:
+ is_valid = (to == CHANNEL_LISTENER_STATE_LISTENING);
+ break;
+ case CHANNEL_LISTENER_STATE_CLOSING:
+ is_valid = (to == CHANNEL_LISTENER_STATE_CLOSED ||
+ to == CHANNEL_LISTENER_STATE_ERROR);
+ break;
+ case CHANNEL_LISTENER_STATE_ERROR:
+ is_valid = 0;
+ break;
+ case CHANNEL_LISTENER_STATE_LISTENING:
+ is_valid = (to == CHANNEL_LISTENER_STATE_CLOSING ||
+ to == CHANNEL_LISTENER_STATE_ERROR);
+ break;
+ case CHANNEL_LISTENER_STATE_LAST:
+ default:
+ is_valid = 0;
+ }
+
+ return is_valid;
+}
+
+/**
* Return a human-readable description for a channel state
*/
@@ -193,9 +259,6 @@ channel_state_to_string(channel_state_t state)
case CHANNEL_STATE_ERROR:
descr = "channel error";
break;
- case CHANNEL_STATE_LISTENING:
- descr = "listening";
- break;
case CHANNEL_STATE_MAINT:
descr = "temporarily suspended for maintenance";
break;
@@ -213,6 +276,36 @@ channel_state_to_string(channel_state_t state)
return descr;
}
+/**
+ * Return a human-readable description for a channel listenier state
+ */
+
+const char *
+channel_listener_state_to_string(channel_listener_state_t state)
+{
+ const char *descr;
+
+ switch (state) {
+ case CHANNEL_LISTENER_STATE_CLOSED:
+ descr = "closed";
+ break;
+ case CHANNEL_LISTENER_STATE_CLOSING:
+ descr = "closing";
+ break;
+ case CHANNEL_LISTENER_STATE_ERROR:
+ descr = "channel listener error";
+ break;
+ case CHANNEL_LISTENER_STATE_LISTENING:
+ descr = "listening";
+ break;
+ case CHANNEL_LISTENER_STATE_LAST:
+ default:
+ descr = "unknown or invalid channel listener state";
+ }
+
+ return descr;
+}
+
/***************************************
* Channel registration/unregistration *
***************************************/
@@ -232,20 +325,12 @@ channel_register(channel_t *chan)
/* No-op if already registered */
if (chan->registered) return;
- if (chan->is_listener) {
- log_debug(LD_CHANNEL,
- "Registering listener channel %p (ID " U64_FORMAT ") "
- "in state %s (%d)",
- chan, U64_PRINTF_ARG(chan->global_identifier),
- channel_state_to_string(chan->state), chan->state);
- } else {
- log_debug(LD_CHANNEL,
- "Registering cell channel %p (ID " U64_FORMAT ") "
- "in state %s (%d) with digest %s",
- chan, U64_PRINTF_ARG(chan->global_identifier),
- channel_state_to_string(chan->state), chan->state,
- hex_str(chan->u.cell_chan.identity_digest, DIGEST_LEN));
- }
+ log_debug(LD_CHANNEL,
+ "Registering channel %p (ID " U64_FORMAT ") "
+ "in state %s (%d) with digest %s",
+ chan, U64_PRINTF_ARG(chan->global_identifier),
+ channel_state_to_string(chan->state), chan->state,
+ hex_str(chan->identity_digest, DIGEST_LEN));
/* Make sure we have all_channels, then add it */
if (!all_channels) all_channels = smartlist_new();
@@ -262,25 +347,17 @@ channel_register(channel_t *chan)
if (!active_channels) active_channels = smartlist_new();
smartlist_add(active_channels, chan);
- /* Is it a listener? */
- if (chan->is_listener &&
- chan->state == CHANNEL_STATE_LISTENING) {
- /* Put it in the listening list, creating it if necessary */
- if (!listening_channels) listening_channels = smartlist_new();
- smartlist_add(listening_channels, chan);
- } else if (chan->state != CHANNEL_STATE_CLOSING) {
- if (!(chan->is_listener)) {
- /* It should have a digest set */
- if (!tor_digest_is_zero(chan->u.cell_chan.identity_digest)) {
- /* Yeah, we're good, add it to the map */
- channel_add_to_digest_map(chan);
- } else {
- log_info(LD_CHANNEL,
- "Channel %p (global ID " U64_FORMAT ") "
- "in state %s (%d) registered with no identity digest",
- chan, U64_PRINTF_ARG(chan->global_identifier),
- channel_state_to_string(chan->state), chan->state);
- }
+ if (chan->state != CHANNEL_STATE_CLOSING) {
+ /* It should have a digest set */
+ if (!tor_digest_is_zero(chan->identity_digest)) {
+ /* Yeah, we're good, add it to the map */
+ channel_add_to_digest_map(chan);
+ } else {
+ log_info(LD_CHANNEL,
+ "Channel %p (global ID " U64_FORMAT ") "
+ "in state %s (%d) registered with no identity digest",
+ chan, U64_PRINTF_ARG(chan->global_identifier),
+ channel_state_to_string(chan->state), chan->state);
}
}
}
@@ -312,12 +389,6 @@ channel_unregister(channel_t *chan)
} else {
/* Get it out of the active list */
if (active_channels) smartlist_remove(active_channels, chan);
-
- /* Is it listening? */
- if (chan->state == CHANNEL_STATE_LISTENING) {
- /* Get it out of the listening list */
- if (listening_channels) smartlist_remove(listening_channels, chan);
- }
}
/* Get it out of all_channels */
@@ -326,17 +397,88 @@ channel_unregister(channel_t *chan)
/* Mark it as unregistered */
chan->registered = 0;
- if (!(chan->is_listener)) {
- /* Should it be in the digest map? */
- if (!tor_digest_is_zero(chan->u.cell_chan.identity_digest) &&
- !(chan->state == CHANNEL_STATE_LISTENING ||
- chan->state == CHANNEL_STATE_CLOSING ||
- chan->state == CHANNEL_STATE_CLOSED ||
- chan->state == CHANNEL_STATE_ERROR)) {
- /* Remove it */
- channel_remove_from_digest_map(chan);
- }
+ /* Should it be in the digest map? */
+ if (!tor_digest_is_zero(chan->identity_digest) &&
+ !(chan->state == CHANNEL_STATE_CLOSING ||
+ chan->state == CHANNEL_STATE_CLOSED ||
+ chan->state == CHANNEL_STATE_ERROR)) {
+ /* Remove it */
+ channel_remove_from_digest_map(chan);
+ }
+}
+
+/**
+ * Register a channel listener
+ *
+ * This function registers a newly created channel listner in the global
+ * lists/maps of active channel listeners.
+ */
+
+void
+channel_listener_register(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l);
+
+ /* No-op if already registered */
+ if (chan_l->registered) return;
+
+ log_debug(LD_CHANNEL,
+ "Registering channel listener %p (ID " U64_FORMAT ") "
+ "in state %s (%d)",
+ chan_l, U64_PRINTF_ARG(chan_l->global_identifier),
+ channel_listener_state_to_string(chan_l->state),
+ chan_l->state);
+
+ /* Make sure we have all_channels, then add it */
+ if (!all_listeners) all_listeners = smartlist_new();
+ smartlist_add(all_listeners, chan_l);
+
+ /* Is it finished? */
+ if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR) {
+ /* Put it in the finished list, creating it if necessary */
+ if (!finished_listeners) finished_listeners = smartlist_new();
+ smartlist_add(finished_listeners, chan_l);
+ } else {
+ /* Put it in the active list, creating it if necessary */
+ if (!active_listeners) active_listeners = smartlist_new();
+ smartlist_add(active_listeners, chan_l);
+ }
+
+ /* Mark it as registered */
+ chan_l->registered = 1;
+}
+
+/**
+ * Unregister a channel listener
+ *
+ * This function removes a channel listener from the global lists and maps
+ * and is used when freeing a closed/errored channel listener.
+ */
+
+void
+channel_listener_unregister(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l);
+
+ /* No-op if not registered */
+ if (!(chan_l->registered)) return;
+
+ /* Is it finished? */
+ if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR) {
+ /* Get it out of the finished list */
+ if (finished_listeners) smartlist_remove(finished_listeners, chan_l);
+ } else {
+ /* Get it out of the active list */
+ if (active_listeners) smartlist_remove(active_listeners, chan_l);
}
+
+ /* Get it out of all_channels */
+ if (all_listeners) smartlist_remove(all_listeners, chan_l);
+
+ /* Mark it as unregistered */
+ chan_l->registered = 0;
}
/*********************************
@@ -357,34 +499,31 @@ channel_add_to_digest_map(channel_t *chan)
channel_t *tmp;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
/* Assert that the state makes sense */
- tor_assert(!(chan->state == CHANNEL_STATE_LISTENING ||
- chan->state == CHANNEL_STATE_CLOSING ||
+ tor_assert(!(chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED ||
chan->state == CHANNEL_STATE_ERROR));
/* Assert that there is a digest */
- tor_assert(!tor_digest_is_zero(chan->u.cell_chan.identity_digest));
+ tor_assert(!tor_digest_is_zero(chan->identity_digest));
/* Allocate the identity map if we have to */
if (!channel_identity_map) channel_identity_map = digestmap_new();
/* Insert it */
tmp = digestmap_set(channel_identity_map,
- chan->u.cell_chan.identity_digest,
+ chan->identity_digest,
chan);
if (tmp) {
- tor_assert(!(tmp->is_listener));
/* There already was one, this goes at the head of the list */
- chan->u.cell_chan.next_with_same_id = tmp;
- chan->u.cell_chan.prev_with_same_id = NULL;
- tmp->u.cell_chan.prev_with_same_id = chan;
+ chan->next_with_same_id = tmp;
+ chan->prev_with_same_id = NULL;
+ tmp->prev_with_same_id = chan;
} else {
/* First with this digest */
- chan->u.cell_chan.next_with_same_id = NULL;
- chan->u.cell_chan.prev_with_same_id = NULL;
+ chan->next_with_same_id = NULL;
+ chan->prev_with_same_id = NULL;
}
log_debug(LD_CHANNEL,
@@ -392,7 +531,7 @@ channel_add_to_digest_map(channel_t *chan)
"to identity map in state %s (%d) with digest %s",
chan, U64_PRINTF_ARG(chan->global_identifier),
channel_state_to_string(chan->state), chan->state,
- hex_str(chan->u.cell_chan.identity_digest, DIGEST_LEN));
+ hex_str(chan->identity_digest, DIGEST_LEN));
}
/**
@@ -408,10 +547,9 @@ channel_remove_from_digest_map(channel_t *chan)
channel_t *tmp, *head;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
/* Assert that there is a digest */
- tor_assert(!tor_digest_is_zero(chan->u.cell_chan.identity_digest));
+ tor_assert(!tor_digest_is_zero(chan->identity_digest));
/* Make sure we have a map */
if (!channel_identity_map) {
@@ -424,72 +562,62 @@ channel_remove_from_digest_map(channel_t *chan)
"with digest %s from identity map, but didn't have any identity "
"map",
chan, U64_PRINTF_ARG(chan->global_identifier),
- hex_str(chan->u.cell_chan.identity_digest, DIGEST_LEN));
+ hex_str(chan->identity_digest, DIGEST_LEN));
/* Clear out its next/prev pointers */
- if (chan->u.cell_chan.next_with_same_id) {
- tor_assert(!(chan->u.cell_chan.next_with_same_id->is_listener));
- chan->u.cell_chan.next_with_same_id->u.cell_chan.prev_with_same_id
- = chan->u.cell_chan.prev_with_same_id;
+ if (chan->next_with_same_id) {
+ chan->next_with_same_id->prev_with_same_id = chan->prev_with_same_id;
}
- if (chan->u.cell_chan.prev_with_same_id) {
- tor_assert(!(chan->u.cell_chan.prev_with_same_id->is_listener));
- chan->u.cell_chan.prev_with_same_id->u.cell_chan.next_with_same_id
- = chan->u.cell_chan.next_with_same_id;
+ if (chan->prev_with_same_id) {
+ chan->prev_with_same_id->next_with_same_id = chan->next_with_same_id;
}
- chan->u.cell_chan.next_with_same_id = NULL;
- chan->u.cell_chan.prev_with_same_id = NULL;
+ chan->next_with_same_id = NULL;
+ chan->prev_with_same_id = NULL;
return;
}
/* Look for it in the map */
- tmp = digestmap_get(channel_identity_map, chan->u.cell_chan.identity_digest);
+ tmp = digestmap_get(channel_identity_map, chan->identity_digest);
if (tmp) {
/* Okay, it's here */
head = tmp; /* Keep track of list head */
/* Look for this channel */
while (tmp && tmp != chan) {
- tor_assert(!(tmp->is_listener));
- tmp = tmp->u.cell_chan.next_with_same_id;
+ tmp = tmp->next_with_same_id;
}
if (tmp == chan) {
/* Found it, good */
- if (chan->u.cell_chan.next_with_same_id) {
- tor_assert(!(chan->u.cell_chan.next_with_same_id->is_listener));
- chan->u.cell_chan.next_with_same_id->u.cell_chan.prev_with_same_id
- = chan->u.cell_chan.prev_with_same_id;
+ if (chan->next_with_same_id) {
+ chan->next_with_same_id->prev_with_same_id = chan->prev_with_same_id;
}
/* else we're the tail of the list */
- if (chan->u.cell_chan.prev_with_same_id) {
- tor_assert(!(chan->u.cell_chan.prev_with_same_id->is_listener));
+ if (chan->prev_with_same_id) {
/* We're not the head of the list, so we can *just* unlink */
- chan->u.cell_chan.prev_with_same_id->u.cell_chan.next_with_same_id
- = chan->u.cell_chan.next_with_same_id;
+ chan->prev_with_same_id->next_with_same_id = chan->next_with_same_id;
} else {
/* We're the head, so we have to point the digest map entry at our
* next if we have one, or remove it if we're also the tail */
- if (chan->u.cell_chan.next_with_same_id) {
- tor_assert(!(chan->u.cell_chan.next_with_same_id->is_listener));
+ if (chan->next_with_same_id) {
digestmap_set(channel_identity_map,
- chan->u.cell_chan.identity_digest,
- chan->u.cell_chan.next_with_same_id);
+ chan->identity_digest,
+ chan->next_with_same_id);
} else {
digestmap_remove(channel_identity_map,
- chan->u.cell_chan.identity_digest);
+ chan->identity_digest);
}
}
/* NULL out its next/prev pointers, and we're finished */
- chan->u.cell_chan.next_with_same_id = NULL;
- chan->u.cell_chan.prev_with_same_id = NULL;
+ chan->next_with_same_id = NULL;
+ chan->prev_with_same_id = NULL;
log_debug(LD_CHANNEL,
"Removed channel %p (global ID " U64_FORMAT ") from "
"identity map in state %s (%d) with digest %s",
chan, U64_PRINTF_ARG(chan->global_identifier),
channel_state_to_string(chan->state), chan->state,
- hex_str(chan->u.cell_chan.identity_digest, DIGEST_LEN));
+ hex_str(chan->identity_digest, DIGEST_LEN));
} else {
/* This is not good */
log_warn(LD_BUG,
@@ -497,20 +625,16 @@ channel_remove_from_digest_map(channel_t *chan)
"with digest %s from identity map, but couldn't find it in "
"the list for that digest",
chan, U64_PRINTF_ARG(chan->global_identifier),
- hex_str(chan->u.cell_chan.identity_digest, DIGEST_LEN));
+ hex_str(chan->identity_digest, DIGEST_LEN));
/* Unlink it and hope for the best */
- if (chan->u.cell_chan.next_with_same_id) {
- tor_assert(!(chan->u.cell_chan.next_with_same_id->is_listener));
- chan->u.cell_chan.next_with_same_id->u.cell_chan.prev_with_same_id
- = chan->u.cell_chan.prev_with_same_id;
+ if (chan->next_with_same_id) {
+ chan->next_with_same_id->prev_with_same_id = chan->prev_with_same_id;
}
- if (chan->u.cell_chan.prev_with_same_id) {
- tor_assert(!(chan->u.cell_chan.prev_with_same_id->is_listener));
- chan->u.cell_chan.prev_with_same_id->u.cell_chan.next_with_same_id
- = chan->u.cell_chan.next_with_same_id;
+ if (chan->prev_with_same_id) {
+ chan->prev_with_same_id->next_with_same_id = chan->next_with_same_id;
}
- chan->u.cell_chan.next_with_same_id = NULL;
- chan->u.cell_chan.prev_with_same_id = NULL;
+ chan->next_with_same_id = NULL;
+ chan->prev_with_same_id = NULL;
}
} else {
/* Shouldn't happen */
@@ -519,19 +643,16 @@ channel_remove_from_digest_map(channel_t *chan)
"digest %s from identity map, but couldn't find any with "
"that digest",
chan, U64_PRINTF_ARG(chan->global_identifier),
- hex_str(chan->u.cell_chan.identity_digest, DIGEST_LEN));
+ hex_str(chan->identity_digest, DIGEST_LEN));
/* Clear out its next/prev pointers */
- if (chan->u.cell_chan.next_with_same_id) {
- tor_assert(!(chan->u.cell_chan.next_with_same_id->is_listener));
- chan->u.cell_chan.next_with_same_id->u.cell_chan.prev_with_same_id
- = chan->u.cell_chan.prev_with_same_id;
+ if (chan->next_with_same_id) {
+ chan->next_with_same_id->prev_with_same_id = chan->prev_with_same_id;
}
- if (chan->u.cell_chan.prev_with_same_id) {
- chan->u.cell_chan.prev_with_same_id->u.cell_chan.next_with_same_id
- = chan->u.cell_chan.next_with_same_id;
+ if (chan->prev_with_same_id) {
+ chan->prev_with_same_id->next_with_same_id = chan->next_with_same_id;
}
- chan->u.cell_chan.next_with_same_id = NULL;
- chan->u.cell_chan.prev_with_same_id = NULL;
+ chan->next_with_same_id = NULL;
+ chan->prev_with_same_id = NULL;
}
}
@@ -599,9 +720,8 @@ channel_t *
channel_next_with_digest(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return chan->u.cell_chan.next_with_same_id;
+ return chan->next_with_same_id;
}
/**
@@ -614,19 +734,13 @@ channel_next_with_digest(channel_t *chan)
channel_t *
channel_prev_with_digest(channel_t *chan)
{
- channel_t *rv = NULL;
-
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- if (chan->u.cell_chan.prev_with_same_id)
- rv = chan->u.cell_chan.prev_with_same_id;
-
- return rv;
+ return chan->prev_with_same_id;
}
/**
- * Initialize a cell channel
+ * Initialize a channel
*
* This function should be called by subclasses to set up some per-channel
* variables. I.e., this is the superclass constructor. Before this, the
@@ -634,47 +748,41 @@ channel_prev_with_digest(channel_t *chan)
*/
void
-channel_init_for_cells(channel_t *chan)
+channel_init(channel_t *chan)
{
tor_assert(chan);
/* Assign an ID and bump the counter */
chan->global_identifier = n_channels_allocated++;
- /* Mark as a non-listener */
- chan->is_listener = 0;
-
/* Init timestamp */
- chan->u.cell_chan.timestamp_last_added_nonpadding = time(NULL);
+ chan->timestamp_last_added_nonpadding = time(NULL);
/* Init next_circ_id */
- chan->u.cell_chan.next_circ_id = crypto_rand_int(1 << 15);
+ chan->next_circ_id = crypto_rand_int(1 << 15);
/* Timestamp it */
channel_timestamp_created(chan);
}
/**
- * Initialize a listener channel
+ * Initialize a channel listener
*
* This function should be called by subclasses to set up some per-channel
* variables. I.e., this is the superclass constructor. Before this, the
- * channel should be allocated with tor_malloc_zero().
+ * channel listener should be allocated with tor_malloc_zero().
*/
void
-channel_init_listener(channel_t *chan)
+channel_init_listener(channel_listener_t *chan_l)
{
- tor_assert(chan);
+ tor_assert(chan_l);
/* Assign an ID and bump the counter */
- chan->global_identifier = n_channels_allocated++;
-
- /* Mark as a listener */
- chan->is_listener = 1;
+ chan_l->global_identifier = n_channels_allocated++;
/* Timestamp it */
- channel_timestamp_created(chan);
+ channel_listener_timestamp_created(chan_l);
}
/**
@@ -696,13 +804,11 @@ channel_free(channel_t *chan)
/* Call a free method if there is one */
if (chan->free) chan->free(chan);
- if (!(chan->is_listener)) {
- channel_clear_remote_end(chan);
+ channel_clear_remote_end(chan);
- if (chan->u.cell_chan.active_circuit_pqueue) {
- smartlist_free(chan->u.cell_chan.active_circuit_pqueue);
- chan->u.cell_chan.active_circuit_pqueue = NULL;
- }
+ if (chan->active_circuit_pqueue) {
+ smartlist_free(chan->active_circuit_pqueue);
+ chan->active_circuit_pqueue = NULL;
}
/* We're in CLOSED or ERROR, so the cell queue is already empty */
@@ -711,7 +817,35 @@ channel_free(channel_t *chan)
}
/**
- * Free a channel and skip the state/reigstration asserts; this internal-
+ * Free a channel listener; nothing outside of channel.c and subclasses
+ * should call this - it frees channel listeners after they have closed and
+ * been unregistered.
+ */
+
+void
+channel_listener_free(channel_listener_t *chan_l)
+{
+ if (!chan_l) return;
+
+ /* It must be closed or errored */
+ tor_assert(chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR);
+ /* It must be deregistered */
+ tor_assert(!(chan_l->registered));
+
+ /* Call a free method if there is one */
+ if (chan_l->free) chan_l->free(chan_l);
+
+ /*
+ * We're in CLOSED or ERROR, so the incoming channel queue is already
+ * empty.
+ */
+
+ tor_free(chan_l);
+}
+
+/**
+ * Free a channel and skip the state/registration asserts; this internal-
* use-only function should be called only from channel_free_all() when
* shutting down the Tor process.
*/
@@ -724,96 +858,111 @@ channel_force_free(channel_t *chan)
/* Call a free method if there is one */
if (chan->free) chan->free(chan);
- if (chan->is_listener) {
- /*
- * The incoming list just gets emptied and freed; we request close on
- * any channels we find there, but since we got called while shutting
- * down they will get deregistered and freed elsewhere anyway.
- */
- if (chan->u.listener.incoming_list) {
- SMARTLIST_FOREACH_BEGIN(chan->u.listener.incoming_list,
- channel_t *, qchan) {
- channel_mark_for_close(qchan);
- } SMARTLIST_FOREACH_END(qchan);
-
- smartlist_free(chan->u.listener.incoming_list);
- chan->u.listener.incoming_list = NULL;
- }
- } else {
- channel_clear_remote_end(chan);
- smartlist_free(chan->u.cell_chan.active_circuit_pqueue);
-
- /* We might still have a cell queue; kill it */
- if (chan->u.cell_chan.incoming_queue) {
- SMARTLIST_FOREACH_BEGIN(chan->u.cell_chan.incoming_queue,
- cell_queue_entry_t *, q) {
- tor_free(q);
- } SMARTLIST_FOREACH_END(q);
-
- smartlist_free(chan->u.cell_chan.incoming_queue);
- chan->u.cell_chan.incoming_queue = NULL;
- }
+ channel_clear_remote_end(chan);
+ smartlist_free(chan->active_circuit_pqueue);
+
+ /* We might still have a cell queue; kill it */
+ if (chan->incoming_queue) {
+ SMARTLIST_FOREACH_BEGIN(chan->incoming_queue,
+ cell_queue_entry_t *, q) {
+ tor_free(q);
+ } SMARTLIST_FOREACH_END(q);
+
+ smartlist_free(chan->incoming_queue);
+ chan->incoming_queue = NULL;
+ }
- /* Outgoing cell queue is similar, but we can have to free packed cells */
- if (chan->u.cell_chan.outgoing_queue) {
- SMARTLIST_FOREACH_BEGIN(chan->u.cell_chan.outgoing_queue,
- cell_queue_entry_t *, q) {
- if (q->type == CELL_QUEUE_PACKED) {
- if (q->u.packed.packed_cell) {
- packed_cell_free(q->u.packed.packed_cell);
- }
+ /* Outgoing cell queue is similar, but we can have to free packed cells */
+ if (chan->outgoing_queue) {
+ SMARTLIST_FOREACH_BEGIN(chan->outgoing_queue,
+ cell_queue_entry_t *, q) {
+ if (q->type == CELL_QUEUE_PACKED) {
+ if (q->u.packed.packed_cell) {
+ packed_cell_free(q->u.packed.packed_cell);
}
- tor_free(q);
- } SMARTLIST_FOREACH_END(q);
+ }
+ tor_free(q);
+ } SMARTLIST_FOREACH_END(q);
- smartlist_free(chan->u.cell_chan.outgoing_queue);
- chan->u.cell_chan.outgoing_queue = NULL;
- }
+ smartlist_free(chan->outgoing_queue);
+ chan->outgoing_queue = NULL;
}
tor_free(chan);
}
/**
- * Return the current registered listener for a channel
+ * Free a channel listener and skip the state/reigstration asserts; this
+ * internal-use-only function should be called only from channel_free_all()
+ * when shutting down the Tor process.
+ */
+
+static void
+channel_listener_force_free(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l);
+
+ /* Call a free method if there is one */
+ if (chan_l->free) chan_l->free(chan_l);
+
+ /*
+ * The incoming list just gets emptied and freed; we request close on
+ * any channels we find there, but since we got called while shutting
+ * down they will get deregistered and freed elsewhere anyway.
+ */
+ if (chan_l->incoming_list) {
+ SMARTLIST_FOREACH_BEGIN(chan_l->incoming_list,
+ channel_t *, qchan) {
+ channel_mark_for_close(qchan);
+ } SMARTLIST_FOREACH_END(qchan);
+
+ smartlist_free(chan_l->incoming_list);
+ chan_l->incoming_list = NULL;
+ }
+
+ tor_free(chan_l);
+}
+
+/**
+ * Return the current registered listener for a channel listener
*
* This function returns a function pointer to the current registered
- * handler for new incoming channels on a listener channel.
+ * handler for new incoming channels on a channel listener.
*/
channel_listener_fn_ptr
-channel_get_listener_fn(channel_t *chan)
+channel_listener_get_listener_fn(channel_listener_t *chan_l)
{
- tor_assert(chan);
- tor_assert(chan->is_listener);
+ tor_assert(chan_l);
- if (chan->state == CHANNEL_STATE_LISTENING)
- return chan->u.listener.listener;
+ if (chan_l->state == CHANNEL_LISTENER_STATE_LISTENING)
+ return chan_l->listener;
return NULL;
}
/**
- * Set the listener for a channel
+ * Set the listener for a channel listener
*
- * This function sets the handler for new incoming channels on a listener
- * channel.
+ * This function sets the handler for new incoming channels on a channel
+ * listener.
*/
void
-channel_set_listener_fn(channel_t *chan,
- channel_listener_fn_ptr listener)
+channel_listener_set_listener_fn(channel_listener_t *chan_l,
+ channel_listener_fn_ptr listener)
{
- tor_assert(chan);
- tor_assert(chan->is_listener);
- tor_assert(chan->state == CHANNEL_STATE_LISTENING);
+ tor_assert(chan_l);
+ tor_assert(chan_l->state == CHANNEL_LISTENER_STATE_LISTENING);
log_debug(LD_CHANNEL,
- "Setting listener callback for channel %p to %p",
- chan, listener);
+ "Setting listener callback for channel listener %p "
+ "(global ID " U64_FORMAT ") to %p",
+ chan_l, U64_PRINTF_ARG(chan_l->global_identifier),
+ listener);
- chan->u.listener.listener = listener;
- if (chan->u.listener.listener) channel_process_incoming(chan);
+ chan_l->listener = listener;
+ if (chan_l->listener) channel_listener_process_incoming(chan_l);
}
/**
@@ -827,12 +976,11 @@ channel_cell_handler_fn_ptr
channel_get_cell_handler(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
if (chan->state == CHANNEL_STATE_OPENING ||
chan->state == CHANNEL_STATE_OPEN ||
chan->state == CHANNEL_STATE_MAINT)
- return chan->u.cell_chan.cell_handler;
+ return chan->cell_handler;
return NULL;
}
@@ -848,12 +996,11 @@ channel_var_cell_handler_fn_ptr
channel_get_var_cell_handler(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
if (chan->state == CHANNEL_STATE_OPENING ||
chan->state == CHANNEL_STATE_OPEN ||
chan->state == CHANNEL_STATE_MAINT)
- return chan->u.cell_chan.var_cell_handler;
+ return chan->var_cell_handler;
return NULL;
}
@@ -875,7 +1022,6 @@ channel_set_cell_handlers(channel_t *chan,
int try_again = 0;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(chan->state == CHANNEL_STATE_OPENING ||
chan->state == CHANNEL_STATE_OPEN ||
chan->state == CHANNEL_STATE_MAINT);
@@ -889,20 +1035,20 @@ channel_set_cell_handlers(channel_t *chan,
/* Should we try the queue? */
if (cell_handler &&
- cell_handler != chan->u.cell_chan.cell_handler) try_again = 1;
+ cell_handler != chan->cell_handler) try_again = 1;
if (var_cell_handler &&
- var_cell_handler != chan->u.cell_chan.var_cell_handler) try_again = 1;
+ var_cell_handler != chan->var_cell_handler) try_again = 1;
/* Change them */
- chan->u.cell_chan.cell_handler = cell_handler;
- chan->u.cell_chan.var_cell_handler = var_cell_handler;
+ chan->cell_handler = cell_handler;
+ chan->var_cell_handler = var_cell_handler;
/* Re-run the queue if we have one and there's any reason to */
- if (chan->u.cell_chan.incoming_queue &&
- (smartlist_len(chan->u.cell_chan.incoming_queue) > 0) &&
+ if (chan->incoming_queue &&
+ (smartlist_len(chan->incoming_queue) > 0) &&
try_again &&
- (chan->u.cell_chan.cell_handler ||
- chan->u.cell_chan.var_cell_handler)) channel_process_cells(chan);
+ (chan->cell_handler ||
+ chan->var_cell_handler)) channel_process_cells(chan);
}
/**
@@ -925,8 +1071,9 @@ channel_mark_for_close(channel_t *chan)
chan->state == CHANNEL_STATE_ERROR) return;
log_debug(LD_CHANNEL,
- "Closing channel %p by request",
- chan);
+ "Closing channel %p (global ID " U64_FORMAT ") "
+ "by request",
+ chan, U64_PRINTF_ARG(chan->global_identifier));
/* Note closing by request from above */
chan->reason_for_closing = CHANNEL_CLOSE_REQUESTED;
@@ -946,6 +1093,47 @@ channel_mark_for_close(channel_t *chan)
}
/**
+ * Mark a channel listener for closure
+ *
+ * This function tries to close a channel_listener_t; it will go into the
+ * CLOSING state, and eventually the lower layer should put it into the CLOSED
+ * or ERROR state. Then, channel_run_cleanup() will eventually free it.
+ */
+
+void
+channel_listener_mark_for_close(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l != NULL);
+ tor_assert(chan_l->close != NULL);
+
+ /* If it's already in CLOSING, CLOSED or ERROR, this is a no-op */
+ if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSING ||
+ chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR) return;
+
+ log_debug(LD_CHANNEL,
+ "Closing channel listener %p (global ID " U64_FORMAT ") "
+ "by request",
+ chan_l, U64_PRINTF_ARG(chan_l->global_identifier));
+
+ /* Note closing by request from above */
+ chan_l->reason_for_closing = CHANNEL_LISTENER_CLOSE_REQUESTED;
+
+ /* Change state to CLOSING */
+ channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSING);
+
+ /* Tell the lower layer */
+ chan_l->close(chan_l);
+
+ /*
+ * It's up to the lower layer to change state to CLOSED or ERROR when we're
+ * ready; we'll try to free channels that are in the finished list from
+ * channel_run_cleanup(). The lower layer should do this by calling
+ * channel_listener_closed().
+ */
+}
+
+/**
* Close a channel from the lower layer
*
* Notify the channel code that the channel is being closed due to a non-error
@@ -964,8 +1152,9 @@ channel_close_from_lower_layer(channel_t *chan)
chan->state == CHANNEL_STATE_ERROR) return;
log_debug(LD_CHANNEL,
- "Closing channel %p due to lower-layer event",
- chan);
+ "Closing channel %p (global ID " U64_FORMAT ") "
+ "due to lower-layer event",
+ chan, U64_PRINTF_ARG(chan->global_identifier));
/* Note closing by event from below */
chan->reason_for_closing = CHANNEL_CLOSE_FROM_BELOW;
@@ -975,6 +1164,36 @@ channel_close_from_lower_layer(channel_t *chan)
}
/**
+ * Close a channel listener from the lower layer
+ *
+ * Notify the channel code that the channel listener is being closed due to a
+ * non-error condition in the lower layer. This does not call the close()
+ * method, since the lower layer already knows.
+ */
+
+void
+channel_listener_close_from_lower_layer(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l != NULL);
+
+ /* If it's already in CLOSING, CLOSED or ERROR, this is a no-op */
+ if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSING ||
+ chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR) return;
+
+ log_debug(LD_CHANNEL,
+ "Closing channel listener %p (global ID " U64_FORMAT ") "
+ "due to lower-layer event",
+ chan_l, U64_PRINTF_ARG(chan_l->global_identifier));
+
+ /* Note closing by event from below */
+ chan_l->reason_for_closing = CHANNEL_LISTENER_CLOSE_FROM_BELOW;
+
+ /* Change state to CLOSING */
+ channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSING);
+}
+
+/**
* Notify that the channel is being closed due to an error condition
*
* This function is called by the lower layer implementing the transport
@@ -1004,6 +1223,37 @@ channel_close_for_error(channel_t *chan)
}
/**
+ * Notify that the channel listener is being closed due to an error condition
+ *
+ * This function is called by the lower layer implementing the transport
+ * when a channel listener must be closed due to an error condition. This
+ * does not call the channel listener's close method, since the lower layer
+ * already knows.
+ */
+
+void
+channel_listener_close_for_error(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l != NULL);
+
+ /* If it's already in CLOSING, CLOSED or ERROR, this is a no-op */
+ if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSING ||
+ chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR) return;
+
+ log_debug(LD_CHANNEL,
+ "Closing channel listener %p (global ID " U64_FORMAT ") "
+ "due to lower-layer error",
+ chan_l, U64_PRINTF_ARG(chan_l->global_identifier));
+
+ /* Note closing by event from below */
+ chan_l->reason_for_closing = CHANNEL_LISTENER_CLOSE_FOR_ERROR;
+
+ /* Change state to CLOSING */
+ channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSING);
+}
+
+/**
* Notify that the lower layer is finished closing the channel
*
* This function should be called by the lower layer when a channel
@@ -1039,6 +1289,33 @@ channel_closed(channel_t *chan)
}
/**
+ * Notify that the lower layer is finished closing the channel listener
+ *
+ * This function should be called by the lower layer when a channel listener
+ * is finished closing and it should be regarded as inactive and
+ * freed by the channel code.
+ */
+
+void
+channel_listener_closed(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l);
+ tor_assert(chan_l->state == CHANNEL_LISTENER_STATE_CLOSING ||
+ chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR);
+
+ /* No-op if already inactive */
+ if (chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR) return;
+
+ if (chan_l->reason_for_closing != CHANNEL_LISTENER_CLOSE_FOR_ERROR) {
+ channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSED);
+ } else {
+ channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_ERROR);
+ }
+}
+
+/**
* Clear the identity_digest of a channel
*
* This function clears the identity digest of the remote endpoint for a
@@ -1051,7 +1328,6 @@ channel_clear_identity_digest(channel_t *chan)
int state_not_in_map;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
log_debug(LD_CHANNEL,
"Clearing remote endpoint digest on channel %p with "
@@ -1059,18 +1335,17 @@ channel_clear_identity_digest(channel_t *chan)
chan, U64_PRINTF_ARG(chan->global_identifier));
state_not_in_map =
- (chan->state == CHANNEL_STATE_LISTENING ||
- chan->state == CHANNEL_STATE_CLOSING ||
+ (chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED ||
chan->state == CHANNEL_STATE_ERROR);
if (!state_not_in_map && chan->registered &&
- !tor_digest_is_zero(chan->u.cell_chan.identity_digest))
+ !tor_digest_is_zero(chan->identity_digest))
/* if it's registered get it out of the digest map */
channel_remove_from_digest_map(chan);
- memset(chan->u.cell_chan.identity_digest, 0,
- sizeof(chan->u.cell_chan.identity_digest));
+ memset(chan->identity_digest, 0,
+ sizeof(chan->identity_digest));
}
/**
@@ -1087,7 +1362,6 @@ channel_set_identity_digest(channel_t *chan,
int was_in_digest_map, should_be_in_digest_map, state_not_in_map;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
log_debug(LD_CHANNEL,
"Setting remote endpoint digest on channel %p with "
@@ -1097,14 +1371,13 @@ channel_set_identity_digest(channel_t *chan,
hex_str(identity_digest, DIGEST_LEN) : "(null)");
state_not_in_map =
- (chan->state == CHANNEL_STATE_LISTENING ||
- chan->state == CHANNEL_STATE_CLOSING ||
+ (chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED ||
chan->state == CHANNEL_STATE_ERROR);
was_in_digest_map =
!state_not_in_map &&
chan->registered &&
- !tor_digest_is_zero(chan->u.cell_chan.identity_digest);
+ !tor_digest_is_zero(chan->identity_digest);
should_be_in_digest_map =
!state_not_in_map &&
chan->registered &&
@@ -1118,12 +1391,12 @@ channel_set_identity_digest(channel_t *chan,
channel_remove_from_digest_map(chan);
if (identity_digest) {
- memcpy(chan->u.cell_chan.identity_digest,
+ memcpy(chan->identity_digest,
identity_digest,
- sizeof(chan->u.cell_chan.identity_digest));
+ sizeof(chan->identity_digest));
} else {
- memset(chan->u.cell_chan.identity_digest, 0,
- sizeof(chan->u.cell_chan.identity_digest));
+ memset(chan->identity_digest, 0,
+ sizeof(chan->identity_digest));
}
/* Put it in the digest map if we should */
@@ -1144,7 +1417,6 @@ channel_clear_remote_end(channel_t *chan)
int state_not_in_map;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
log_debug(LD_CHANNEL,
"Clearing remote endpoint identity on channel %p with "
@@ -1152,19 +1424,18 @@ channel_clear_remote_end(channel_t *chan)
chan, U64_PRINTF_ARG(chan->global_identifier));
state_not_in_map =
- (chan->state == CHANNEL_STATE_LISTENING ||
- chan->state == CHANNEL_STATE_CLOSING ||
+ (chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED ||
chan->state == CHANNEL_STATE_ERROR);
if (!state_not_in_map && chan->registered &&
- !tor_digest_is_zero(chan->u.cell_chan.identity_digest))
+ !tor_digest_is_zero(chan->identity_digest))
/* if it's registered get it out of the digest map */
channel_remove_from_digest_map(chan);
- memset(chan->u.cell_chan.identity_digest, 0,
- sizeof(chan->u.cell_chan.identity_digest));
- tor_free(chan->u.cell_chan.nickname);
+ memset(chan->identity_digest, 0,
+ sizeof(chan->identity_digest));
+ tor_free(chan->nickname);
}
/**
@@ -1182,7 +1453,6 @@ channel_set_remote_end(channel_t *chan,
int was_in_digest_map, should_be_in_digest_map, state_not_in_map;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
log_debug(LD_CHANNEL,
"Setting remote endpoint identity on channel %p with "
@@ -1193,14 +1463,13 @@ channel_set_remote_end(channel_t *chan,
hex_str(identity_digest, DIGEST_LEN) : "(null)");
state_not_in_map =
- (chan->state == CHANNEL_STATE_LISTENING ||
- chan->state == CHANNEL_STATE_CLOSING ||
+ (chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED ||
chan->state == CHANNEL_STATE_ERROR);
was_in_digest_map =
!state_not_in_map &&
chan->registered &&
- !tor_digest_is_zero(chan->u.cell_chan.identity_digest);
+ !tor_digest_is_zero(chan->identity_digest);
should_be_in_digest_map =
!state_not_in_map &&
chan->registered &&
@@ -1214,18 +1483,18 @@ channel_set_remote_end(channel_t *chan,
channel_remove_from_digest_map(chan);
if (identity_digest) {
- memcpy(chan->u.cell_chan.identity_digest,
+ memcpy(chan->identity_digest,
identity_digest,
- sizeof(chan->u.cell_chan.identity_digest));
+ sizeof(chan->identity_digest));
} else {
- memset(chan->u.cell_chan.identity_digest, 0,
- sizeof(chan->u.cell_chan.identity_digest));
+ memset(chan->identity_digest, 0,
+ sizeof(chan->identity_digest));
}
- tor_free(chan->u.cell_chan.nickname);
+ tor_free(chan->nickname);
if (nickname)
- chan->u.cell_chan.nickname = tor_strdup(nickname);
+ chan->nickname = tor_strdup(nickname);
/* Put it in the digest map if we should */
if (should_be_in_digest_map)
@@ -1275,7 +1544,6 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q)
cell_queue_entry_t *tmp = NULL;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(q);
/* Assert that the state makes sense for a cell write */
@@ -1285,31 +1553,29 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q)
/* Increment the timestamp unless it's padding */
if (!cell_queue_entry_is_padding(q)) {
- chan->u.cell_chan.timestamp_last_added_nonpadding = approx_time();
+ chan->timestamp_last_added_nonpadding = approx_time();
}
/* Can we send it right out? If so, try */
- if (!(chan->u.cell_chan.outgoing_queue &&
- (smartlist_len(chan->u.cell_chan.outgoing_queue) > 0)) &&
+ if (!(chan->outgoing_queue &&
+ (smartlist_len(chan->outgoing_queue) > 0)) &&
chan->state == CHANNEL_STATE_OPEN) {
/* Pick the right write function for this cell type and save the result */
switch (q->type) {
case CELL_QUEUE_FIXED:
- tor_assert(chan->u.cell_chan.write_cell);
+ tor_assert(chan->write_cell);
tor_assert(q->u.fixed.cell);
- result = chan->u.cell_chan.write_cell(chan, q->u.fixed.cell);
+ result = chan->write_cell(chan, q->u.fixed.cell);
break;
case CELL_QUEUE_PACKED:
- tor_assert(chan->u.cell_chan.write_packed_cell);
+ tor_assert(chan->write_packed_cell);
tor_assert(q->u.packed.packed_cell);
- result = chan->
- u.cell_chan.write_packed_cell(chan,
- q->u.packed.packed_cell);
+ result = chan->write_packed_cell(chan, q->u.packed.packed_cell);
break;
case CELL_QUEUE_VAR:
- tor_assert(chan->u.cell_chan.write_var_cell);
+ tor_assert(chan->write_var_cell);
tor_assert(q->u.var.var_cell);
- result = chan->u.cell_chan.write_var_cell(chan, q->u.var.var_cell);
+ result = chan->write_var_cell(chan, q->u.var.var_cell);
break;
default:
tor_assert(1);
@@ -1323,21 +1589,21 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q)
/* If we're here the queue is empty, so it's drained too */
channel_timestamp_drained(chan);
/* Update the counter */
- ++(chan->u.cell_chan.n_cells_xmitted);
+ ++(chan->n_cells_xmitted);
}
}
if (!sent) {
/* Not sent, queue it */
- if (!(chan->u.cell_chan.outgoing_queue))
- chan->u.cell_chan.outgoing_queue = smartlist_new();
+ if (!(chan->outgoing_queue))
+ chan->outgoing_queue = smartlist_new();
/*
* We have to copy the queue entry passed in, since the caller probably
* used the stack.
*/
tmp = tor_malloc(sizeof(*tmp));
memcpy(tmp, q, sizeof(*tmp));
- smartlist_add(chan->u.cell_chan.outgoing_queue, tmp);
+ smartlist_add(chan->outgoing_queue, tmp);
/* Try to process the queue? */
if (chan->state == CHANNEL_STATE_OPEN) channel_flush_cells(chan);
}
@@ -1432,7 +1698,7 @@ void
channel_change_state(channel_t *chan, channel_state_t to_state)
{
channel_state_t from_state;
- unsigned char was_active, is_active, was_listening, is_listening;
+ unsigned char was_active, is_active;
unsigned char was_in_id_map, is_in_id_map;
tor_assert(chan);
@@ -1442,26 +1708,13 @@ channel_change_state(channel_t *chan, channel_state_t to_state)
tor_assert(channel_state_is_valid(to_state));
tor_assert(channel_state_can_transition(chan->state, to_state));
- if (chan->is_listener) {
- tor_assert(from_state == CHANNEL_STATE_LISTENING ||
- from_state == CHANNEL_STATE_CLOSING ||
- from_state == CHANNEL_STATE_CLOSED ||
- from_state == CHANNEL_STATE_ERROR);
- tor_assert(to_state == CHANNEL_STATE_LISTENING ||
- to_state == CHANNEL_STATE_CLOSING ||
- to_state == CHANNEL_STATE_CLOSED ||
- to_state == CHANNEL_STATE_ERROR);
- } else {
- tor_assert(from_state != CHANNEL_STATE_LISTENING);
- tor_assert(to_state != CHANNEL_STATE_LISTENING);
- }
-
/* Check for no-op transitions */
if (from_state == to_state) {
log_debug(LD_CHANNEL,
- "Got no-op transition from \"%s\" to itself on channel %p",
+ "Got no-op transition from \"%s\" to itself on channel %p"
+ "(global ID " U64_FORMAT ")",
channel_state_to_string(to_state),
- chan);
+ chan, U64_PRINTF_ARG(chan->global_identifier));
return;
}
@@ -1482,8 +1735,10 @@ channel_change_state(channel_t *chan, channel_state_t to_state)
*/
log_debug(LD_CHANNEL,
- "Changing state of channel %p from \"%s\" to \"%s\"",
+ "Changing state of channel %p (global ID " U64_FORMAT
+ ") from \"%s\" to \"%s\"",
chan,
+ U64_PRINTF_ARG(chan->global_identifier),
channel_state_to_string(chan->state),
channel_state_to_string(to_state));
@@ -1509,28 +1764,12 @@ channel_change_state(channel_t *chan, channel_state_t to_state)
smartlist_add(active_channels, chan);
}
- was_listening = (from_state == CHANNEL_STATE_LISTENING);
- is_listening = (to_state == CHANNEL_STATE_LISTENING);
-
- /* Need to put on listening list? */
- if (!was_listening && is_listening) {
- if (!listening_channels) listening_channels = smartlist_new();
- smartlist_add(listening_channels, chan);
- }
- /* Need to remove from listening list? */
- else if (was_listening && !is_listening) {
- if (listening_channels) smartlist_remove(listening_channels, chan);
- }
-
- if (!(chan->is_listener) &&
- !tor_digest_is_zero(chan->u.cell_chan.identity_digest)) {
+ if (!tor_digest_is_zero(chan->identity_digest)) {
/* Now we need to handle the identity map */
- was_in_id_map = !(from_state == CHANNEL_STATE_LISTENING ||
- from_state == CHANNEL_STATE_CLOSING ||
+ was_in_id_map = !(from_state == CHANNEL_STATE_CLOSING ||
from_state == CHANNEL_STATE_CLOSED ||
from_state == CHANNEL_STATE_ERROR);
- is_in_id_map = !(to_state == CHANNEL_STATE_LISTENING ||
- to_state == CHANNEL_STATE_CLOSING ||
+ is_in_id_map = !(to_state == CHANNEL_STATE_CLOSING ||
to_state == CHANNEL_STATE_CLOSED ||
to_state == CHANNEL_STATE_ERROR);
@@ -1541,30 +1780,110 @@ channel_change_state(channel_t *chan, channel_state_t to_state)
}
/* Tell circuits if we opened and stuff */
- if (to_state == CHANNEL_STATE_OPEN) channel_do_open_actions(chan);
+ if (to_state == CHANNEL_STATE_OPEN) {
+ channel_do_open_actions(chan);
- if (!(chan->is_listener) &&
- to_state == CHANNEL_STATE_OPEN) {
/* Check for queued cells to process */
- if (chan->u.cell_chan.incoming_queue &&
- smartlist_len(chan->u.cell_chan.incoming_queue) > 0)
+ if (chan->incoming_queue &&
+ smartlist_len(chan->incoming_queue) > 0)
channel_process_cells(chan);
- if (chan->u.cell_chan.outgoing_queue &&
- smartlist_len(chan->u.cell_chan.outgoing_queue) > 0)
+ if (chan->outgoing_queue &&
+ smartlist_len(chan->outgoing_queue) > 0)
channel_flush_cells(chan);
} else if (to_state == CHANNEL_STATE_CLOSED ||
to_state == CHANNEL_STATE_ERROR) {
/* Assert that all queues are empty */
- if (chan->is_listener) {
- tor_assert(!(chan->u.listener.incoming_list) ||
- smartlist_len(chan->u.listener.incoming_list) == 0);
- } else {
- tor_assert(!(chan->u.cell_chan.incoming_queue) ||
- smartlist_len(chan->u.cell_chan.incoming_queue) == 0);
- tor_assert(!(chan->u.cell_chan.outgoing_queue) ||
- smartlist_len(chan->u.cell_chan.outgoing_queue) == 0);
+ tor_assert(!(chan->incoming_queue) ||
+ smartlist_len(chan->incoming_queue) == 0);
+ tor_assert(!(chan->outgoing_queue) ||
+ smartlist_len(chan->outgoing_queue) == 0);
+ }
+}
+
+/**
+ * Change channel listener state
+ *
+ * This internal and subclass use only function is used to change channel
+ * listener state, performing all transition validity checks and whatever
+ * actions are appropriate to the state transition in question.
+ */
+
+void
+channel_listener_change_state(channel_listener_t *chan_l,
+ channel_listener_state_t to_state)
+{
+ channel_listener_state_t from_state;
+ unsigned char was_active, is_active;
+
+ tor_assert(chan_l);
+ from_state = chan_l->state;
+
+ tor_assert(channel_listener_state_is_valid(from_state));
+ tor_assert(channel_listener_state_is_valid(to_state));
+ tor_assert(channel_listener_state_can_transition(chan_l->state, to_state));
+
+ /* Check for no-op transitions */
+ if (from_state == to_state) {
+ log_debug(LD_CHANNEL,
+ "Got no-op transition from \"%s\" to itself on channel "
+ "listener %p (global ID " U64_FORMAT ")",
+ channel_listener_state_to_string(to_state),
+ chan_l, U64_PRINTF_ARG(chan_l->global_identifier));
+ return;
+ }
+
+ /* If we're going to a closing or closed state, we must have a reason set */
+ if (to_state == CHANNEL_LISTENER_STATE_CLOSING ||
+ to_state == CHANNEL_LISTENER_STATE_CLOSED ||
+ to_state == CHANNEL_LISTENER_STATE_ERROR) {
+ tor_assert(chan_l->reason_for_closing != CHANNEL_LISTENER_NOT_CLOSING);
+ }
+
+ /*
+ * We need to maintain the queues here for some transitions:
+ * when we enter CHANNEL_STATE_OPEN (especially from CHANNEL_STATE_MAINT)
+ * we may have a backlog of cells to transmit, so drain the queues in
+ * that case, and when going to CHANNEL_STATE_CLOSED the subclass
+ * should have made sure to finish sending things (or gone to
+ * CHANNEL_STATE_ERROR if not possible), so we assert for that here.
+ */
+
+ log_debug(LD_CHANNEL,
+ "Changing state of channel listener %p (global ID " U64_FORMAT
+ "from \"%s\" to \"%s\"",
+ chan_l, U64_PRINTF_ARG(chan_l->global_identifier),
+ channel_listener_state_to_string(chan_l->state),
+ channel_listener_state_to_string(to_state));
+
+ chan_l->state = to_state;
+
+ /* Need to add to the right lists if the channel listener is registered */
+ if (chan_l->registered) {
+ was_active = !(from_state == CHANNEL_LISTENER_STATE_CLOSED ||
+ from_state == CHANNEL_LISTENER_STATE_ERROR);
+ is_active = !(to_state == CHANNEL_LISTENER_STATE_CLOSED ||
+ to_state == CHANNEL_LISTENER_STATE_ERROR);
+
+ /* Need to take off active list and put on finished list? */
+ if (was_active && !is_active) {
+ if (active_listeners) smartlist_remove(active_listeners, chan_l);
+ if (!finished_listeners) finished_listeners = smartlist_new();
+ smartlist_add(finished_listeners, chan_l);
+ }
+ /* Need to put on active list? */
+ else if (!was_active && is_active) {
+ if (finished_listeners) smartlist_remove(finished_listeners, chan_l);
+ if (!active_listeners) active_listeners = smartlist_new();
+ smartlist_add(active_listeners, chan_l);
}
}
+
+ if (to_state == CHANNEL_LISTENER_STATE_CLOSED ||
+ to_state == CHANNEL_LISTENER_STATE_ERROR) {
+ /* Assert that the queue is empty */
+ tor_assert(!(chan_l->incoming_list) ||
+ smartlist_len(chan_l->incoming_list) == 0);
+ }
}
/**
@@ -1586,7 +1905,6 @@ channel_flush_some_cells(channel_t *chan, ssize_t num_cells)
int num_cells_from_circs;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
if (num_cells < 0) unlimited = 1;
if (!unlimited && num_cells <= flushed) goto done;
@@ -1598,7 +1916,7 @@ channel_flush_some_cells(channel_t *chan, ssize_t num_cells)
(unlimited ? -1 : num_cells - flushed));
if (!unlimited && num_cells <= flushed) goto done;
- if (chan->u.cell_chan.active_circuits) {
+ if (chan->active_circuits) {
/* Try to get more cells from any active circuits */
num_cells_from_circs =
channel_flush_from_first_active_circuit(chan,
@@ -1633,10 +1951,9 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
cell_queue_entry_t *q = NULL;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- tor_assert(chan->u.cell_chan.write_cell);
- tor_assert(chan->u.cell_chan.write_packed_cell);
- tor_assert(chan->u.cell_chan.write_var_cell);
+ tor_assert(chan->write_cell);
+ tor_assert(chan->write_packed_cell);
+ tor_assert(chan->write_var_cell);
if (num_cells < 0) unlimited = 1;
if (!unlimited && num_cells <= flushed) return 0;
@@ -1644,15 +1961,15 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
/* If we aren't in CHANNEL_STATE_OPEN, nothing goes through */
if (chan->state == CHANNEL_STATE_OPEN) {
while ((unlimited || num_cells > flushed) &&
- (chan->u.cell_chan.outgoing_queue &&
- (smartlist_len(chan->u.cell_chan.outgoing_queue) > 0))) {
+ (chan->outgoing_queue &&
+ (smartlist_len(chan->outgoing_queue) > 0))) {
/*
* Ewww, smartlist_del_keeporder() is O(n) in list length; maybe a
* a linked list would make more sense for the queue.
*/
/* Get the head of the queue */
- q = smartlist_get(chan->u.cell_chan.outgoing_queue, 0);
+ q = smartlist_get(chan->outgoing_queue, 0);
if (q) {
/*
* Okay, we have a good queue entry, try to give it to the lower
@@ -1661,60 +1978,63 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
switch (q->type) {
case CELL_QUEUE_FIXED:
if (q->u.fixed.cell) {
- if (chan->u.cell_chan.write_cell(chan,
+ if (chan->write_cell(chan,
q->u.fixed.cell)) {
tor_free(q);
++flushed;
channel_timestamp_xmit(chan);
- ++(chan->u.cell_chan.n_cells_xmitted);
+ ++(chan->n_cells_xmitted);
}
/* Else couldn't write it; leave it on the queue */
} else {
/* This shouldn't happen */
log_info(LD_CHANNEL,
"Saw broken cell queue entry of type CELL_QUEUE_FIXED "
- "with no cell on channel %p.",
- chan);
+ "with no cell on channel %p "
+ "(global ID " U64_FORMAT ").",
+ chan, U64_PRINTF_ARG(chan->global_identifier));
/* Throw it away */
tor_free(q);
}
break;
case CELL_QUEUE_PACKED:
if (q->u.packed.packed_cell) {
- if (chan->u.cell_chan.write_packed_cell(chan,
+ if (chan->write_packed_cell(chan,
q->u.packed.packed_cell)) {
tor_free(q);
++flushed;
channel_timestamp_xmit(chan);
- ++(chan->u.cell_chan.n_cells_xmitted);
+ ++(chan->n_cells_xmitted);
}
/* Else couldn't write it; leave it on the queue */
} else {
/* This shouldn't happen */
log_info(LD_CHANNEL,
"Saw broken cell queue entry of type CELL_QUEUE_PACKED "
- "with no cell on channel %p.",
- chan);
+ "with no cell on channel %p "
+ "(global ID " U64_FORMAT ").",
+ chan, U64_PRINTF_ARG(chan->global_identifier));
/* Throw it away */
tor_free(q);
}
break;
case CELL_QUEUE_VAR:
if (q->u.var.var_cell) {
- if (chan->u.cell_chan.write_var_cell(chan,
+ if (chan->write_var_cell(chan,
q->u.var.var_cell)) {
tor_free(q);
++flushed;
channel_timestamp_xmit(chan);
- ++(chan->u.cell_chan.n_cells_xmitted);
+ ++(chan->n_cells_xmitted);
}
/* Else couldn't write it; leave it on the queue */
} else {
/* This shouldn't happen */
log_info(LD_CHANNEL,
"Saw broken cell queue entry of type CELL_QUEUE_VAR "
- "with no cell on channel %p.",
- chan);
+ "with no cell on channel %p "
+ "(global ID " U64_FORMAT ").",
+ chan, U64_PRINTF_ARG(chan->global_identifier));
/* Throw it away */
tor_free(q);
}
@@ -1722,30 +2042,31 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
default:
/* Unknown type, log and free it */
log_info(LD_CHANNEL,
- "Saw an unknown cell queue entry type %d on channel %p; "
- "ignoring it. Someone should fix this.",
- q->type, chan);
+ "Saw an unknown cell queue entry type %d on channel %p "
+ "(global ID " U64_FORMAT "; ignoring it."
+ " Someone should fix this.",
+ q->type, chan, U64_PRINTF_ARG(chan->global_identifier));
tor_free(q); /* tor_free() NULLs it out */
}
} else {
/* This shouldn't happen; log and throw it away */
log_info(LD_CHANNEL,
- "Saw a NULL entry in the outgoing cell queue on channel %p; "
- "this is definitely a bug.",
- chan);
+ "Saw a NULL entry in the outgoing cell queue on channel %p "
+ "(global ID " U64_FORMAT "); this is definitely a bug.",
+ chan, U64_PRINTF_ARG(chan->global_identifier));
/* q is already NULL, so we know to delete that queue entry */
}
/* if q got NULLed out, we used it and should remove the queue entry */
- if (!q) smartlist_del_keeporder(chan->u.cell_chan.outgoing_queue, 0);
+ if (!q) smartlist_del_keeporder(chan->outgoing_queue, 0);
/* No cell removed from list, so we can't go on any further */
else break;
}
}
/* Did we drain the queue? */
- if (!(chan->u.cell_chan.outgoing_queue) ||
- smartlist_len(chan->u.cell_chan.outgoing_queue) == 0) {
+ if (!(chan->outgoing_queue) ||
+ smartlist_len(chan->outgoing_queue) == 0) {
/* Timestamp it */
channel_timestamp_drained(chan);
}
@@ -1778,14 +2099,13 @@ int
channel_more_to_flush(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
/* Check if we have any queued */
- if (chan->u.cell_chan.incoming_queue &&
- smartlist_len(chan->u.cell_chan.incoming_queue) > 0) return 1;
+ if (chan->incoming_queue &&
+ smartlist_len(chan->incoming_queue) > 0) return 1;
/* Check if any circuits would like to queue some */
- if (chan->u.cell_chan.active_circuits) return 1;
+ if (chan->active_circuits) return 1;
/* Else no */
return 0;
@@ -1802,10 +2122,9 @@ void
channel_notify_flushed(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- if (chan->u.cell_chan.dirreq_id != 0)
- geoip_change_dirreq_state(chan->u.cell_chan.dirreq_id,
+ if (chan->dirreq_id != 0)
+ geoip_change_dirreq_state(chan->dirreq_id,
DIRREQ_TUNNELED,
DIRREQ_CHANNEL_BUFFER_FLUSHED);
}
@@ -1818,32 +2137,31 @@ channel_notify_flushed(channel_t *chan)
*/
void
-channel_process_incoming(channel_t *listener)
+channel_listener_process_incoming(channel_listener_t *listener)
{
tor_assert(listener);
- tor_assert(listener->is_listener);
+
/*
- * CHANNEL_STATE_CLOSING permitted because we drain the queue while
- * closing a listener.
+ * CHANNEL_LISTENER_STATE_CLOSING permitted because we drain the queue
+ * while closing a listener.
*/
- tor_assert(listener->state == CHANNEL_STATE_LISTENING ||
- listener->state == CHANNEL_STATE_CLOSING);
- tor_assert(listener->u.listener.listener);
+ tor_assert(listener->state == CHANNEL_LISTENER_STATE_LISTENING ||
+ listener->state == CHANNEL_LISTENER_STATE_CLOSING);
+ tor_assert(listener->listener);
log_debug(LD_CHANNEL,
- "Processing queue of incoming connections for listening "
- "channel %p (global ID " U64_FORMAT ")",
+ "Processing queue of incoming connections for channel "
+ "listener %p (global ID " U64_FORMAT ")",
listener, U64_PRINTF_ARG(listener->global_identifier));
- if (!(listener->u.listener.incoming_list)) return;
+ if (!(listener->incoming_list)) return;
- SMARTLIST_FOREACH_BEGIN(listener->u.listener.incoming_list,
+ SMARTLIST_FOREACH_BEGIN(listener->incoming_list,
channel_t *, chan) {
tor_assert(chan);
- tor_assert(!(chan->is_listener));
log_debug(LD_CHANNEL,
- "Handling incoming connection %p (" U64_FORMAT ") "
+ "Handling incoming channel %p (" U64_FORMAT ") "
"for listener %p (" U64_FORMAT ")",
chan,
U64_PRINTF_ARG(chan->global_identifier),
@@ -1851,11 +2169,11 @@ channel_process_incoming(channel_t *listener)
U64_PRINTF_ARG(listener->global_identifier));
/* Make sure this is set correctly */
channel_mark_incoming(chan);
- listener->u.listener.listener(listener, chan);
+ listener->listener(listener, chan);
} SMARTLIST_FOREACH_END(chan);
- smartlist_free(listener->u.listener.incoming_list);
- listener->u.listener.incoming_list = NULL;
+ smartlist_free(listener->incoming_list);
+ listener->incoming_list = NULL;
}
/**
@@ -1879,15 +2197,14 @@ channel_do_open_actions(channel_t *chan)
time_t now = time(NULL);
tor_assert(chan);
- tor_assert(!(chan->is_listener));
started_here = channel_is_outgoing(chan);
if (started_here) {
circuit_build_times_network_is_live(&circ_times);
- rep_hist_note_connect_succeeded(chan->u.cell_chan.identity_digest, now);
+ rep_hist_note_connect_succeeded(chan->identity_digest, now);
if (entry_guard_register_connect_status(
- chan->u.cell_chan.identity_digest, 1, 0, now) < 0) {
+ chan->identity_digest, 1, 0, now) < 0) {
/* Close any circuits pending on this channel. We leave it in state
* 'open' though, because it didn't actually *fail* -- we just
* chose not to use it. */
@@ -1897,10 +2214,10 @@ channel_do_open_actions(channel_t *chan)
circuit_n_chan_done(chan, 0);
not_using = 1;
}
- router_set_status(chan->u.cell_chan.identity_digest, 1);
+ router_set_status(chan->identity_digest, 1);
} else {
/* only report it to the geoip module if it's not a known router */
- if (!router_get_by_id_digest(chan->u.cell_chan.identity_digest)) {
+ if (!router_get_by_id_digest(chan->identity_digest)) {
if (channel_get_addr_if_possible(chan, &remote_addr)) {
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &remote_addr,
now);
@@ -1916,60 +2233,55 @@ channel_do_open_actions(channel_t *chan)
* Queue an incoming channel on a listener
*
* Internal and subclass use only function to queue an incoming channel from
- * a listening one. A subclass of channel_t should call this when a new
+ * a listener. A subclass of channel_listener_t should call this when a new
* incoming channel is created.
*/
void
-channel_queue_incoming(channel_t *listener, channel_t *incoming)
+channel_listener_queue_incoming(channel_listener_t *listener,
+ channel_t *incoming)
{
int need_to_queue = 0;
tor_assert(listener);
- tor_assert(listener->is_listener);
- tor_assert(listener->state == CHANNEL_STATE_LISTENING);
+ tor_assert(listener->state == CHANNEL_LISTENER_STATE_LISTENING);
tor_assert(incoming);
- tor_assert(!(incoming->is_listener));
- /*
- * Other states are permitted because subclass might process activity
- * on a channel at any time while it's queued, but a listener returning
- * another listener makes no sense.
- */
- tor_assert(incoming->state != CHANNEL_STATE_LISTENING);
log_debug(LD_CHANNEL,
- "Queueing incoming channel %p on listening channel %p",
- incoming, listener);
+ "Queueing incoming channel %p (global ID " U64_FORMAT ") on "
+ "channel listener %p (global ID " U64_FORMAT ")",
+ incoming, U64_PRINTF_ARG(incoming->global_identifier),
+ listener, U64_PRINTF_ARG(listener->global_identifier));
/* Do we need to queue it, or can we just call the listener right away? */
- if (!(listener->u.listener.listener)) need_to_queue = 1;
- if (listener->u.listener.incoming_list &&
- (smartlist_len(listener->u.listener.incoming_list) > 0))
+ if (!(listener->listener)) need_to_queue = 1;
+ if (listener->incoming_list &&
+ (smartlist_len(listener->incoming_list) > 0))
need_to_queue = 1;
/* If we need to queue and have no queue, create one */
- if (need_to_queue && !(listener->u.listener.incoming_list)) {
- listener->u.listener.incoming_list = smartlist_new();
+ if (need_to_queue && !(listener->incoming_list)) {
+ listener->incoming_list = smartlist_new();
}
/* Bump the counter and timestamp it */
- channel_timestamp_active(listener);
- channel_timestamp_accepted(listener);
- ++(listener->u.listener.n_accepted);
+ channel_listener_timestamp_active(listener);
+ channel_listener_timestamp_accepted(listener);
+ ++(listener->n_accepted);
/* If we don't need to queue, process it right away */
if (!need_to_queue) {
- tor_assert(listener->u.listener.listener);
- listener->u.listener.listener(listener, incoming);
+ tor_assert(listener->listener);
+ listener->listener(listener, incoming);
}
/*
* Otherwise, we need to queue; queue and then process the queue if
* we can.
*/
else {
- tor_assert(listener->u.listener.incoming_list);
- smartlist_add(listener->u.listener.incoming_list, incoming);
- if (listener->u.listener.listener) channel_process_incoming(listener);
+ tor_assert(listener->incoming_list);
+ smartlist_add(listener->incoming_list, incoming);
+ if (listener->listener) channel_listener_process_incoming(listener);
}
}
@@ -1984,7 +2296,6 @@ void
channel_process_cells(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_MAINT ||
chan->state == CHANNEL_STATE_OPEN);
@@ -1994,40 +2305,44 @@ channel_process_cells(channel_t *chan)
chan);
/* Nothing we can do if we have no registered cell handlers */
- if (!(chan->u.cell_chan.cell_handler ||
- chan->u.cell_chan.var_cell_handler)) return;
+ if (!(chan->cell_handler ||
+ chan->var_cell_handler)) return;
/* Nothing we can do if we have no cells */
- if (!(chan->u.cell_chan.incoming_queue)) return;
+ if (!(chan->incoming_queue)) return;
/*
* Process cells until we're done or find one we have no current handler
* for.
*/
- SMARTLIST_FOREACH_BEGIN(chan->u.cell_chan.incoming_queue,
+ SMARTLIST_FOREACH_BEGIN(chan->incoming_queue,
cell_queue_entry_t *, q) {
tor_assert(q);
tor_assert(q->type == CELL_QUEUE_FIXED ||
q->type == CELL_QUEUE_VAR);
if (q->type == CELL_QUEUE_FIXED &&
- chan->u.cell_chan.cell_handler) {
+ chan->cell_handler) {
/* Handle a fixed-length cell */
tor_assert(q->u.fixed.cell);
log_debug(LD_CHANNEL,
- "Processing incoming cell_t %p for channel %p",
- q->u.fixed.cell, chan);
- chan->u.cell_chan.cell_handler(chan, q->u.fixed.cell);
- SMARTLIST_DEL_CURRENT(chan->u.cell_chan.incoming_queue, q);
+ "Processing incoming cell_t %p for channel %p (global ID "
+ U64_FORMAT ")",
+ q->u.fixed.cell, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
+ chan->cell_handler(chan, q->u.fixed.cell);
+ SMARTLIST_DEL_CURRENT(chan->incoming_queue, q);
tor_free(q);
} else if (q->type == CELL_QUEUE_VAR &&
- chan->u.cell_chan.var_cell_handler) {
+ chan->var_cell_handler) {
/* Handle a variable-length cell */
tor_assert(q->u.var.var_cell);
log_debug(LD_CHANNEL,
- "Processing incoming var_cell_t %p for channel %p",
- q->u.var.var_cell, chan);
- chan->u.cell_chan.var_cell_handler(chan, q->u.var.var_cell);
- SMARTLIST_DEL_CURRENT(chan->u.cell_chan.incoming_queue, q);
+ "Processing incoming var_cell_t %p for channel %p (global ID "
+ U64_FORMAT ")",
+ q->u.var.var_cell, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
+ chan->var_cell_handler(chan, q->u.var.var_cell);
+ SMARTLIST_DEL_CURRENT(chan->incoming_queue, q);
tor_free(q);
} else {
/* Can't handle this one */
@@ -2036,9 +2351,9 @@ channel_process_cells(channel_t *chan)
} SMARTLIST_FOREACH_END(q);
/* If the list is empty, free it */
- if (smartlist_len(chan->u.cell_chan.incoming_queue) == 0 ) {
- smartlist_free(chan->u.cell_chan.incoming_queue);
- chan->u.cell_chan.incoming_queue = NULL;
+ if (smartlist_len(chan->incoming_queue) == 0 ) {
+ smartlist_free(chan->incoming_queue);
+ chan->incoming_queue = NULL;
}
}
@@ -2056,46 +2371,49 @@ channel_queue_cell(channel_t *chan, cell_t *cell)
cell_queue_entry_t *q;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(cell);
tor_assert(chan->state == CHANNEL_STATE_OPEN);
/* Do we need to queue it, or can we just call the handler right away? */
- if (!(chan->u.cell_chan.cell_handler)) need_to_queue = 1;
- if (chan->u.cell_chan.incoming_queue &&
- (smartlist_len(chan->u.cell_chan.incoming_queue) > 0))
+ if (!(chan->cell_handler)) need_to_queue = 1;
+ if (chan->incoming_queue &&
+ (smartlist_len(chan->incoming_queue) > 0))
need_to_queue = 1;
/* If we need to queue and have no queue, create one */
- if (need_to_queue && !(chan->u.cell_chan.incoming_queue)) {
- chan->u.cell_chan.incoming_queue = smartlist_new();
+ if (need_to_queue && !(chan->incoming_queue)) {
+ chan->incoming_queue = smartlist_new();
}
/* Timestamp for receiving */
channel_timestamp_recv(chan);
/* Update the counter */
- ++(chan->u.cell_chan.n_cells_recved);
+ ++(chan->n_cells_recved);
/* If we don't need to queue we can just call cell_handler */
if (!need_to_queue) {
- tor_assert(chan->u.cell_chan.cell_handler);
+ tor_assert(chan->cell_handler);
log_debug(LD_CHANNEL,
- "Directly handling incoming cell_t %p for channel %p",
- cell, chan);
- chan->u.cell_chan.cell_handler(chan, cell);
+ "Directly handling incoming cell_t %p for channel %p "
+ "(global ID " U64_FORMAT ")",
+ cell, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
+ chan->cell_handler(chan, cell);
} else {
/* Otherwise queue it and then process the queue if possible. */
- tor_assert(chan->u.cell_chan.incoming_queue);
+ tor_assert(chan->incoming_queue);
q = tor_malloc(sizeof(*q));
q->type = CELL_QUEUE_FIXED;
q->u.fixed.cell = cell;
log_debug(LD_CHANNEL,
- "Queueing incoming cell_t %p for channel %p",
- cell, chan);
- smartlist_add(chan->u.cell_chan.incoming_queue, q);
- if (chan->u.cell_chan.cell_handler ||
- chan->u.cell_chan.var_cell_handler) {
+ "Queueing incoming cell_t %p for channel %p "
+ "(global ID " U64_FORMAT ")",
+ cell, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
+ smartlist_add(chan->incoming_queue, q);
+ if (chan->cell_handler ||
+ chan->var_cell_handler) {
channel_process_cells(chan);
}
}
@@ -2115,46 +2433,49 @@ channel_queue_var_cell(channel_t *chan, var_cell_t *var_cell)
cell_queue_entry_t *q;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(var_cell);
tor_assert(chan->state == CHANNEL_STATE_OPEN);
/* Do we need to queue it, or can we just call the handler right away? */
- if (!(chan->u.cell_chan.var_cell_handler)) need_to_queue = 1;
- if (chan->u.cell_chan.incoming_queue &&
- (smartlist_len(chan->u.cell_chan.incoming_queue) > 0))
+ if (!(chan->var_cell_handler)) need_to_queue = 1;
+ if (chan->incoming_queue &&
+ (smartlist_len(chan->incoming_queue) > 0))
need_to_queue = 1;
/* If we need to queue and have no queue, create one */
- if (need_to_queue && !(chan->u.cell_chan.incoming_queue)) {
- chan->u.cell_chan.incoming_queue = smartlist_new();
+ if (need_to_queue && !(chan->incoming_queue)) {
+ chan->incoming_queue = smartlist_new();
}
/* Timestamp for receiving */
channel_timestamp_recv(chan);
/* Update the counter */
- ++(chan->u.cell_chan.n_cells_recved);
+ ++(chan->n_cells_recved);
/* If we don't need to queue we can just call cell_handler */
if (!need_to_queue) {
- tor_assert(chan->u.cell_chan.var_cell_handler);
+ tor_assert(chan->var_cell_handler);
log_debug(LD_CHANNEL,
- "Directly handling incoming var_cell_t %p for channel %p",
- var_cell, chan);
- chan->u.cell_chan.var_cell_handler(chan, var_cell);
+ "Directly handling incoming var_cell_t %p for channel %p "
+ "(global ID " U64_FORMAT ")",
+ var_cell, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
+ chan->var_cell_handler(chan, var_cell);
} else {
/* Otherwise queue it and then process the queue if possible. */
- tor_assert(chan->u.cell_chan.incoming_queue);
+ tor_assert(chan->incoming_queue);
q = tor_malloc(sizeof(*q));
q->type = CELL_QUEUE_VAR;
q->u.var.var_cell = var_cell;
log_debug(LD_CHANNEL,
- "Queueing incoming var_cell_t %p for channel %p",
- var_cell, chan);
- smartlist_add(chan->u.cell_chan.incoming_queue, q);
- if (chan->u.cell_chan.cell_handler ||
- chan->u.cell_chan.var_cell_handler) {
+ "Queueing incoming var_cell_t %p for channel %p "
+ "(global ID " U64_FORMAT ")",
+ var_cell, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
+ smartlist_add(chan->incoming_queue, q);
+ if (chan->cell_handler ||
+ chan->var_cell_handler) {
channel_process_cells(chan);
}
}
@@ -2174,13 +2495,16 @@ channel_send_destroy(circid_t circ_id, channel_t *chan, int reason)
cell_t cell;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
memset(&cell, 0, sizeof(cell_t));
cell.circ_id = circ_id;
cell.command = CELL_DESTROY;
cell.payload[0] = (uint8_t) reason;
- log_debug(LD_OR,"Sending destroy (circID %d).", circ_id);
+ log_debug(LD_OR,
+ "Sending destroy (circID %d) on channel %p "
+ "(global ID " U64_FORMAT ")",
+ circ_id, chan,
+ U64_PRINTF_ARG(chan->global_identifier));
channel_write_cell(chan, &cell);
@@ -2202,23 +2526,52 @@ channel_dumpstats(int severity)
"Dumping statistics about %d channels:",
smartlist_len(all_channels));
log(severity, LD_GENERAL,
- "%d are active, %d are listeners, and %d are done and "
- "waiting for cleanup",
+ "%d are active, and %d are done and waiting for cleanup",
(active_channels != NULL) ?
smartlist_len(active_channels) : 0,
- (listening_channels != NULL) ?
- smartlist_len(listening_channels) : 0,
(finished_channels != NULL) ?
smartlist_len(finished_channels) : 0);
- SMARTLIST_FOREACH(all_channels, channel_t *, chan,
- channel_dump_statistics(chan, severity));
+ SMARTLIST_FOREACH(all_channels, channel_t *, chan,
+ channel_dump_statistics(chan, severity));
+
+ log(severity, LD_GENERAL,
+ "Done spamming about channels now");
+ } else {
+ log(severity, LD_GENERAL,
+ "No channels to dump");
+ }
+}
+
+/**
+ * Dump channel listener statistics to the log
+ *
+ * This is called from dumpstats() in main.c and spams the log with
+ * statistics on channel listeners.
+ */
+
+void
+channel_listener_dumpstats(int severity)
+{
+ if (all_listeners && smartlist_len(all_listeners) > 0) {
+ log(severity, LD_GENERAL,
+ "Dumping statistics about %d channel listeners:",
+ smartlist_len(all_listeners));
+ log(severity, LD_GENERAL,
+ "%d are active and %d are done and waiting for cleanup",
+ (active_listeners != NULL) ?
+ smartlist_len(active_listeners) : 0,
+ (finished_listeners != NULL) ?
+ smartlist_len(finished_listeners) : 0);
+
+ SMARTLIST_FOREACH(all_listeners, channel_listener_t *, chan_l,
+ channel_listener_dump_statistics(chan_l, severity));
log(severity, LD_GENERAL,
- "Done spamming about channels now");
+ "Done spamming about channel listeners now");
} else {
log(severity, LD_GENERAL,
- "No channels to dump");
+ "No channel listeners to dump");
}
}
@@ -2250,6 +2603,91 @@ channel_run_cleanup(void)
}
/**
+ * Clean up channel listeners
+ *
+ * This gets called periodically from run_scheduled_events() in main.c;
+ * it cleans up after closed channel listeners.
+ */
+
+void
+channel_listener_run_cleanup(void)
+{
+ channel_listener_t *tmp = NULL;
+
+ /* Check if we need to do anything */
+ if (!finished_listeners || smartlist_len(finished_listeners) == 0) return;
+
+ /* Iterate through finished_channels and get rid of them */
+ SMARTLIST_FOREACH_BEGIN(finished_listeners, channel_listener_t *, curr) {
+ tmp = curr;
+ /* Remove it from the list */
+ SMARTLIST_DEL_CURRENT(finished_listeners, curr);
+ /* Also unregister it */
+ channel_listener_unregister(tmp);
+ /* ... and free it */
+ channel_listener_free(tmp);
+ } SMARTLIST_FOREACH_END(curr);
+}
+
+/**
+ * Free a list of channels for channel_free_all()
+ */
+
+static void
+channel_free_list(smartlist_t *channels, int mark_for_close)
+{
+ if (!channels) return;
+
+ SMARTLIST_FOREACH_BEGIN(channels, channel_t *, curr) {
+ /* Deregister and free it */
+ tor_assert(curr);
+ log_debug(LD_CHANNEL,
+ "Cleaning up channel %p (global ID " U64_FORMAT ") "
+ "in state %s (%d)",
+ curr, U64_PRINTF_ARG(curr->global_identifier),
+ channel_state_to_string(curr->state), curr->state);
+ channel_unregister(curr);
+ if (mark_for_close) {
+ if (!(curr->state == CHANNEL_STATE_CLOSING ||
+ curr->state == CHANNEL_STATE_CLOSED ||
+ curr->state == CHANNEL_STATE_ERROR)) {
+ channel_mark_for_close(curr);
+ }
+ channel_force_free(curr);
+ } else channel_free(curr);
+ } SMARTLIST_FOREACH_END(curr);
+}
+
+/**
+ * Free a list of channel listeners for channel_free_all()
+ */
+
+static void
+channel_listener_free_list(smartlist_t *listeners, int mark_for_close)
+{
+ if (!listeners) return;
+
+ SMARTLIST_FOREACH_BEGIN(listeners, channel_listener_t *, curr) {
+ /* Deregister and free it */
+ tor_assert(curr);
+ log_debug(LD_CHANNEL,
+ "Cleaning up channel listener %p (global ID " U64_FORMAT ") "
+ "in state %s (%d)",
+ curr, U64_PRINTF_ARG(curr->global_identifier),
+ channel_listener_state_to_string(curr->state), curr->state);
+ channel_listener_unregister(curr);
+ if (mark_for_close) {
+ if (!(curr->state == CHANNEL_LISTENER_STATE_CLOSING ||
+ curr->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ curr->state == CHANNEL_LISTENER_STATE_ERROR)) {
+ channel_listener_mark_for_close(curr);
+ }
+ channel_listener_force_free(curr);
+ } else channel_listener_free(curr);
+ } SMARTLIST_FOREACH_END(curr);
+}
+
+/**
* Close all channels and free everything
*
* This gets called from tor_free_all() in main.c to clean up on exit.
@@ -2266,91 +2704,46 @@ channel_free_all(void)
/* First, let's go for finished channels */
if (finished_channels) {
- SMARTLIST_FOREACH_BEGIN(finished_channels, channel_t *, curr) {
- /* Deregister and free it */
- tor_assert(curr);
- log_debug(LD_CHANNEL,
- "Cleaning up finished channel %p (ID " U64_FORMAT ") "
- "in state %s (%d)",
- curr, U64_PRINTF_ARG(curr->global_identifier),
- channel_state_to_string(curr->state), curr->state);
- channel_unregister(curr);
- channel_free(curr);
- } SMARTLIST_FOREACH_END(curr);
-
+ channel_free_list(finished_channels, 0);
smartlist_free(finished_channels);
finished_channels = NULL;
}
- /* Now the listeners */
- if (listening_channels) {
- SMARTLIST_FOREACH_BEGIN(listening_channels, channel_t *, curr) {
- /* Close, deregister and free it */
- tor_assert(curr);
- log_debug(LD_CHANNEL,
- "Cleaning up listening channel %p (ID " U64_FORMAT ") "
- "in state %s (%d)",
- curr, U64_PRINTF_ARG(curr->global_identifier),
- channel_state_to_string(curr->state), curr->state);
- /*
- * We have to unregister first so we don't put it in finished_channels
- * and allocate that again on close.
- */
- channel_unregister(curr);
- channel_mark_for_close(curr);
- channel_force_free(curr);
- } SMARTLIST_FOREACH_END(curr);
-
- smartlist_free(listening_channels);
- listening_channels = NULL;
+ /* Now the finished listeners */
+ if (finished_listeners) {
+ channel_listener_free_list(finished_listeners, 0);
+ smartlist_free(finished_listeners);
+ finished_listeners = NULL;
}
/* Now all active channels */
if (active_channels) {
- SMARTLIST_FOREACH_BEGIN(active_channels, channel_t *, curr) {
- /* Close, deregister and free it */
- tor_assert(curr);
- log_debug(LD_CHANNEL,
- "Cleaning up active channel %p (ID " U64_FORMAT ") "
- "in state %s (%d)",
- curr, U64_PRINTF_ARG(curr->global_identifier),
- channel_state_to_string(curr->state), curr->state);
- /*
- * We have to unregister first so we don't put it in finished_channels
- * and allocate that again on close.
- */
- channel_unregister(curr);
- channel_mark_for_close(curr);
- channel_force_free(curr);
- } SMARTLIST_FOREACH_END(curr);
-
+ channel_free_list(active_channels, 1);
smartlist_free(active_channels);
active_channels = NULL;
}
+ /* Now all active listeners */
+ if (active_listeners) {
+ channel_listener_free_list(active_listeners, 1);
+ smartlist_free(active_listeners);
+ active_listeners = NULL;
+ }
+
/* Now all channels, in case any are left over */
if (all_channels) {
- SMARTLIST_FOREACH_BEGIN(all_channels, channel_t *, curr) {
- /* Close, deregister and free it */
- tor_assert(curr);
- log_debug(LD_CHANNEL,
- "Cleaning up leftover channel %p (ID " U64_FORMAT ") "
- "in state %s (%d)",
- curr, U64_PRINTF_ARG(curr->global_identifier),
- channel_state_to_string(curr->state), curr->state);
- channel_unregister(curr);
- if (!(curr->state == CHANNEL_STATE_CLOSING ||
- curr->state == CHANNEL_STATE_CLOSED ||
- curr->state == CHANNEL_STATE_ERROR)) {
- channel_mark_for_close(curr);
- }
- channel_force_free(curr);
- } SMARTLIST_FOREACH_END(curr);
-
+ channel_free_list(all_channels, 1);
smartlist_free(all_channels);
all_channels = NULL;
}
+ /* Now all listeners, in case any are left over */
+ if (all_listeners) {
+ channel_listener_free_list(all_listeners, 1);
+ smartlist_free(all_listeners);
+ all_listeners = NULL;
+ }
+
/* Now free channel_identity_map */
if (channel_identity_map) {
log_debug(LD_CHANNEL,
@@ -2409,8 +2802,6 @@ channel_is_better(time_t now, channel_t *a, channel_t *b,
tor_assert(a);
tor_assert(b);
- tor_assert(!(a->is_listener));
- tor_assert(!(b->is_listener));
/* Check if one is canonical and the other isn't first */
a_is_canonical = channel_is_canonical(a);
@@ -2426,8 +2817,8 @@ channel_is_better(time_t now, channel_t *a, channel_t *b,
* one that has no circuits is in its grace period.
*/
- a_has_circs = (a->u.cell_chan.n_circuits > 0);
- b_has_circs = (b->u.cell_chan.n_circuits > 0);
+ a_has_circs = (a->n_circuits > 0);
+ b_has_circs = (b->n_circuits > 0);
a_grace = (forgive_new_connections &&
(now < channel_when_created(a) + NEW_CHAN_GRACE_PERIOD));
b_grace = (forgive_new_connections &&
@@ -2479,14 +2870,12 @@ channel_get_for_extend(const char *digest,
* iteration.
*/
for (; chan; chan = channel_next_with_digest(chan)) {
- tor_assert(!(chan->is_listener));
- tor_assert(tor_memeq(chan->u.cell_chan.identity_digest,
+ tor_assert(tor_memeq(chan->identity_digest,
digest, DIGEST_LEN));
if (chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED ||
- chan->state == CHANNEL_STATE_ERROR ||
- chan->state == CHANNEL_STATE_LISTENING)
+ chan->state == CHANNEL_STATE_ERROR)
continue;
/* Never return a channel on which the other end appears to be
@@ -2562,7 +2951,7 @@ channel_get_for_extend(const char *digest,
}
/**
- * Describe the transport subclass
+ * Describe the transport subclass for a channel
*
* Invoke a method to get a string description of the lower-layer
* transport for this channel.
@@ -2578,6 +2967,22 @@ channel_describe_transport(channel_t *chan)
}
/**
+ * Describe the transport subclass for a channel listener
+ *
+ * Invoke a method to get a string description of the lower-layer
+ * transport for this channel listener.
+ */
+
+const char *
+channel_listener_describe_transport(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l);
+ tor_assert(chan_l->describe_transport);
+
+ return chan_l->describe_transport(chan_l);
+}
+
+/**
* Dump channel statistics
*
* Dump statistics for one channel to the log
@@ -2598,13 +3003,10 @@ channel_dump_statistics(channel_t *chan, int severity)
log(severity, LD_GENERAL,
"Channel " U64_FORMAT " (at %p) with transport %s is in state "
- "%s (%d) and %s",
+ "%s (%d)",
U64_PRINTF_ARG(chan->global_identifier), chan,
channel_describe_transport(chan),
- channel_state_to_string(chan->state), chan->state,
- chan->is_listener ?
- "listens for incoming connections" :
- "transports cells");
+ channel_state_to_string(chan->state), chan->state);
log(severity, LD_GENERAL,
" * Channel " U64_FORMAT " was created at " U64_FORMAT
" (" U64_FORMAT " seconds ago) "
@@ -2614,204 +3016,239 @@ channel_dump_statistics(channel_t *chan, int severity)
U64_PRINTF_ARG(now - chan->timestamp_created),
U64_PRINTF_ARG(chan->timestamp_active),
U64_PRINTF_ARG(now - chan->timestamp_active));
- if (chan->is_listener) {
+
+ /* Handle digest and nickname */
+ if (!tor_digest_is_zero(chan->identity_digest)) {
+ if (chan->nickname) {
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " says it is connected "
+ "to an OR with digest %s and nickname %s",
+ U64_PRINTF_ARG(chan->global_identifier),
+ hex_str(chan->identity_digest, DIGEST_LEN),
+ chan->nickname);
+ } else {
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " says it is connected "
+ "to an OR with digest %s and no known nickname",
+ U64_PRINTF_ARG(chan->global_identifier),
+ hex_str(chan->identity_digest, DIGEST_LEN));
+ }
+ } else {
+ if (chan->nickname) {
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " does not know the digest"
+ " of the OR it is connected to, but reports its nickname is %s",
+ U64_PRINTF_ARG(chan->global_identifier),
+ chan->nickname);
+ } else {
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " does not know the digest"
+ " or the nickname of the OR it is connected to",
+ U64_PRINTF_ARG(chan->global_identifier));
+ }
+ }
+
+ /* Handle remote address and descriptions */
+ have_remote_addr = channel_get_addr_if_possible(chan, &remote_addr);
+ if (have_remote_addr) {
+ remote_addr_str = tor_dup_addr(&remote_addr);
log(severity, LD_GENERAL,
- " * Listener channel " U64_FORMAT " last accepted an incoming "
- "channel at " U64_FORMAT " (" U64_FORMAT " seconds ago) "
- "and has accepted " U64_FORMAT " channels in total",
+ " * Channel " U64_FORMAT " says its remote address"
+ " is %s, and gives a canonical description of \"%s\" and an "
+ "actual description of \"%s\"",
+ U64_PRINTF_ARG(chan->global_identifier),
+ remote_addr_str,
+ channel_get_canonical_remote_descr(chan),
+ channel_get_actual_remote_descr(chan));
+ tor_free(remote_addr_str);
+ } else {
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " does not know its remote "
+ "address, but gives a canonical description of \"%s\" and an "
+ "actual description of \"%s\"",
U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->u.listener.timestamp_accepted),
- U64_PRINTF_ARG(now - chan->u.listener.timestamp_accepted),
- U64_PRINTF_ARG(chan->u.listener.n_accepted));
+ channel_get_canonical_remote_descr(chan),
+ channel_get_actual_remote_descr(chan));
+ }
- /*
- * If it's sensible to do so, get the rate of incoming channels on this
- * listener
- */
- if (now > chan->timestamp_created &&
- chan->timestamp_created > 0 &&
- chan->u.listener.n_accepted > 0) {
- avg = (double)(chan->u.listener.n_accepted) / age;
+ /* Handle marks */
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " has these marks: %s %s %s "
+ "%s %s %s",
+ U64_PRINTF_ARG(chan->global_identifier),
+ channel_is_bad_for_new_circs(chan) ?
+ "bad_for_new_circs" : "!bad_for_new_circs",
+ channel_is_canonical(chan) ?
+ "canonical" : "!canonical",
+ channel_is_canonical_is_reliable(chan) ?
+ "is_canonical_is_reliable" :
+ "!is_canonical_is_reliable",
+ channel_is_client(chan) ?
+ "client" : "!client",
+ channel_is_local(chan) ?
+ "local" : "!local",
+ channel_is_incoming(chan) ?
+ "incoming" : "outgoing");
+
+ /* Describe queues */
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " has %d queued incoming cells"
+ " and %d queued outgoing cells",
+ U64_PRINTF_ARG(chan->global_identifier),
+ (chan->incoming_queue != NULL) ?
+ smartlist_len(chan->incoming_queue) : 0,
+ (chan->outgoing_queue != NULL) ?
+ smartlist_len(chan->outgoing_queue) : 0);
+
+ /* Describe circuits */
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " has %d active circuits out of"
+ " %d in total",
+ U64_PRINTF_ARG(chan->global_identifier),
+ (chan->active_circuit_pqueue != NULL) ?
+ smartlist_len(chan->active_circuit_pqueue) : 0,
+ chan->n_circuits);
+
+ /* Describe timestamps */
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " was last used by a "
+ "client at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
+ U64_PRINTF_ARG(chan->global_identifier),
+ U64_PRINTF_ARG(chan->timestamp_client),
+ U64_PRINTF_ARG(now - chan->timestamp_client));
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " was last drained at "
+ U64_FORMAT " (" U64_FORMAT " seconds ago)",
+ U64_PRINTF_ARG(chan->global_identifier),
+ U64_PRINTF_ARG(chan->timestamp_drained),
+ U64_PRINTF_ARG(now - chan->timestamp_drained));
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " last received a cell "
+ "at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
+ U64_PRINTF_ARG(chan->global_identifier),
+ U64_PRINTF_ARG(chan->timestamp_recv),
+ U64_PRINTF_ARG(now - chan->timestamp_recv));
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " last trasmitted a cell "
+ "at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
+ U64_PRINTF_ARG(chan->global_identifier),
+ U64_PRINTF_ARG(chan->timestamp_xmit),
+ U64_PRINTF_ARG(now - chan->timestamp_xmit));
+
+ /* Describe counters and rates */
+ log(severity, LD_GENERAL,
+ " * Channel " U64_FORMAT " has received "
+ U64_FORMAT " cells and transmitted " U64_FORMAT,
+ U64_PRINTF_ARG(chan->global_identifier),
+ U64_PRINTF_ARG(chan->n_cells_recved),
+ U64_PRINTF_ARG(chan->n_cells_xmitted));
+ if (now > chan->timestamp_created &&
+ chan->timestamp_created > 0) {
+ if (chan->n_cells_recved > 0) {
+ avg = (double)(chan->n_cells_recved) / age;
if (avg >= 1.0) {
log(severity, LD_GENERAL,
- " * Listener channel " U64_FORMAT " has averaged %f incoming "
- "channels per second",
+ " * Channel " U64_FORMAT " has averaged %f "
+ "cells received per second",
U64_PRINTF_ARG(chan->global_identifier), avg);
} else if (avg >= 0.0) {
interval = 1.0 / avg;
log(severity, LD_GENERAL,
- " * Listener channel " U64_FORMAT " has averaged %f seconds "
- "between incoming channels",
+ " * Channel " U64_FORMAT " has averaged %f "
+ "seconds between received cells",
U64_PRINTF_ARG(chan->global_identifier), interval);
}
}
- } else {
- /* Handle digest and nickname */
- if (!tor_digest_is_zero(chan->u.cell_chan.identity_digest)) {
- if (chan->u.cell_chan.nickname) {
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " says it is connected "
- "to an OR with digest %s and nickname %s",
- U64_PRINTF_ARG(chan->global_identifier),
- hex_str(chan->u.cell_chan.identity_digest, DIGEST_LEN),
- chan->u.cell_chan.nickname);
- } else {
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " says it is connected "
- "to an OR with digest %s and no known nickname",
- U64_PRINTF_ARG(chan->global_identifier),
- hex_str(chan->u.cell_chan.identity_digest, DIGEST_LEN));
- }
- } else {
- if (chan->u.cell_chan.nickname) {
+ if (chan->n_cells_xmitted > 0) {
+ avg = (double)(chan->n_cells_xmitted) / age;
+ if (avg >= 1.0) {
log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " does not know the digest"
- " of the OR it is connected to, but reports its nickname is %s",
- U64_PRINTF_ARG(chan->global_identifier),
- chan->u.cell_chan.nickname);
- } else {
+ " * Channel " U64_FORMAT " has averaged %f "
+ "cells transmitted per second",
+ U64_PRINTF_ARG(chan->global_identifier), avg);
+ } else if (avg >= 0.0) {
+ interval = 1.0 / avg;
log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " does not know the digest"
- " or the nickname of the OR it is connected to",
- U64_PRINTF_ARG(chan->global_identifier));
+ " * Channel " U64_FORMAT " has averaged %f "
+ "seconds between transmitted cells",
+ U64_PRINTF_ARG(chan->global_identifier), interval);
}
}
+ }
- /* Handle remote address and descriptions */
- have_remote_addr = channel_get_addr_if_possible(chan, &remote_addr);
- if (have_remote_addr) {
- remote_addr_str = tor_dup_addr(&remote_addr);
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " says its remote address"
- " is %s, and gives a canonical description of \"%s\" and an "
- "actual description of \"%s\"",
- U64_PRINTF_ARG(chan->global_identifier),
- remote_addr_str,
- channel_get_canonical_remote_descr(chan),
- channel_get_actual_remote_descr(chan));
- tor_free(remote_addr_str);
- } else {
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " does not know its remote "
- "address, but gives a canonical description of \"%s\" and an "
- "actual description of \"%s\"",
- U64_PRINTF_ARG(chan->global_identifier),
- channel_get_canonical_remote_descr(chan),
- channel_get_actual_remote_descr(chan));
- }
+ /* Dump anything the lower layer has to say */
+ channel_dump_transport_statistics(chan, severity);
+}
- /* Handle marks */
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " has these marks: %s %s %s "
- "%s %s %s",
- U64_PRINTF_ARG(chan->global_identifier),
- channel_is_bad_for_new_circs(chan) ?
- "bad_for_new_circs" : "!bad_for_new_circs",
- channel_is_canonical(chan) ?
- "canonical" : "!canonical",
- channel_is_canonical_is_reliable(chan) ?
- "is_canonical_is_reliable" :
- "!is_canonical_is_reliable",
- channel_is_client(chan) ?
- "client" : "!client",
- channel_is_local(chan) ?
- "local" : "!local",
- channel_is_incoming(chan) ?
- "incoming" : "outgoing");
-
- /* Describe queues */
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " has %d queued incoming cells"
- " and %d queued outgoing cells",
- U64_PRINTF_ARG(chan->global_identifier),
- (chan->u.cell_chan.incoming_queue != NULL) ?
- smartlist_len(chan->u.cell_chan.incoming_queue) : 0,
- (chan->u.cell_chan.outgoing_queue != NULL) ?
- smartlist_len(chan->u.cell_chan.outgoing_queue) : 0);
+/**
+ * Dump channel listener statistics
+ *
+ * Dump statistics for one channel listener to the log
+ */
- /* Describe circuits */
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " has %d active circuits out of"
- " %d in total",
- U64_PRINTF_ARG(chan->global_identifier),
- (chan->u.cell_chan.active_circuit_pqueue != NULL) ?
- smartlist_len(chan->u.cell_chan.active_circuit_pqueue) : 0,
- chan->u.cell_chan.n_circuits);
+void
+channel_listener_dump_statistics(channel_listener_t *chan_l, int severity)
+{
+ double avg, interval, age;
+ time_t now = time(NULL);
- /* Describe timestamps */
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " was last used by a "
- "client at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->u.cell_chan.timestamp_client),
- U64_PRINTF_ARG(now - chan->u.cell_chan.timestamp_client));
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " was last drained at "
- U64_FORMAT " (" U64_FORMAT " seconds ago)",
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->u.cell_chan.timestamp_drained),
- U64_PRINTF_ARG(now - chan->u.cell_chan.timestamp_drained));
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " last received a cell "
- "at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->u.cell_chan.timestamp_recv),
- U64_PRINTF_ARG(now - chan->u.cell_chan.timestamp_recv));
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " last trasmitted a cell "
- "at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->u.cell_chan.timestamp_xmit),
- U64_PRINTF_ARG(now - chan->u.cell_chan.timestamp_xmit));
+ tor_assert(chan_l);
- /* Describe counters and rates */
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " has received "
- U64_FORMAT " cells and transmitted " U64_FORMAT,
- U64_PRINTF_ARG(chan->global_identifier),
- U64_PRINTF_ARG(chan->u.cell_chan.n_cells_recved),
- U64_PRINTF_ARG(chan->u.cell_chan.n_cells_xmitted));
- if (now > chan->timestamp_created &&
- chan->timestamp_created > 0) {
- if (chan->u.cell_chan.n_cells_recved > 0) {
- avg = (double)(chan->u.cell_chan.n_cells_recved) / age;
- if (avg >= 1.0) {
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " has averaged %f "
- "cells received per second",
- U64_PRINTF_ARG(chan->global_identifier), avg);
- } else if (avg >= 0.0) {
- interval = 1.0 / avg;
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " has averaged %f "
- "seconds between received cells",
- U64_PRINTF_ARG(chan->global_identifier), interval);
- }
- }
- if (chan->u.cell_chan.n_cells_xmitted > 0) {
- avg = (double)(chan->u.cell_chan.n_cells_xmitted) / age;
- if (avg >= 1.0) {
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " has averaged %f "
- "cells transmitted per second",
- U64_PRINTF_ARG(chan->global_identifier), avg);
- } else if (avg >= 0.0) {
- interval = 1.0 / avg;
- log(severity, LD_GENERAL,
- " * Cell-bearing channel " U64_FORMAT " has averaged %f "
- "seconds between transmitted cells",
- U64_PRINTF_ARG(chan->global_identifier), interval);
- }
- }
+ age = (double)(now - chan_l->timestamp_created);
+
+ log(severity, LD_GENERAL,
+ "Channel listener " U64_FORMAT " (at %p) with transport %s is in "
+ "state %s (%d)",
+ U64_PRINTF_ARG(chan_l->global_identifier), chan_l,
+ channel_listener_describe_transport(chan_l),
+ channel_listener_state_to_string(chan_l->state), chan_l->state);
+ log(severity, LD_GENERAL,
+ " * Channel listener " U64_FORMAT " was created at " U64_FORMAT
+ " (" U64_FORMAT " seconds ago) "
+ "and last active at " U64_FORMAT " (" U64_FORMAT " seconds ago)",
+ U64_PRINTF_ARG(chan_l->global_identifier),
+ U64_PRINTF_ARG(chan_l->timestamp_created),
+ U64_PRINTF_ARG(now - chan_l->timestamp_created),
+ U64_PRINTF_ARG(chan_l->timestamp_active),
+ U64_PRINTF_ARG(now - chan_l->timestamp_active));
+
+ log(severity, LD_GENERAL,
+ " * Channel listener " U64_FORMAT " last accepted an incoming "
+ "channel at " U64_FORMAT " (" U64_FORMAT " seconds ago) "
+ "and has accepted " U64_FORMAT " channels in total",
+ U64_PRINTF_ARG(chan_l->global_identifier),
+ U64_PRINTF_ARG(chan_l->timestamp_accepted),
+ U64_PRINTF_ARG(now - chan_l->timestamp_accepted),
+ U64_PRINTF_ARG(chan_l->n_accepted));
+
+ /*
+ * If it's sensible to do so, get the rate of incoming channels on this
+ * listener
+ */
+ if (now > chan_l->timestamp_created &&
+ chan_l->timestamp_created > 0 &&
+ chan_l->n_accepted > 0) {
+ avg = (double)(chan_l->n_accepted) / age;
+ if (avg >= 1.0) {
+ log(severity, LD_GENERAL,
+ " * Channel listener " U64_FORMAT " has averaged %f incoming "
+ "channels per second",
+ U64_PRINTF_ARG(chan_l->global_identifier), avg);
+ } else if (avg >= 0.0) {
+ interval = 1.0 / avg;
+ log(severity, LD_GENERAL,
+ " * Channel listener " U64_FORMAT " has averaged %f seconds "
+ "between incoming channels",
+ U64_PRINTF_ARG(chan_l->global_identifier), interval);
}
}
/* Dump anything the lower layer has to say */
- channel_dump_transport_statistics(chan, severity);
+ channel_listener_dump_transport_statistics(chan_l, severity);
}
/**
- * Invoke transport-specific stats dump
+ * Invoke transport-specific stats dump for channel
*
* If there is a lower-layer statistics dump method, invoke it
*/
@@ -2825,6 +3262,21 @@ channel_dump_transport_statistics(channel_t *chan, int severity)
}
/**
+ * Invoke transport-specific stats dump for channel listener
+ *
+ * If there is a lower-layer statistics dump method, invoke it
+ */
+
+void
+channel_listener_dump_transport_statistics(channel_listener_t *chan_l,
+ int severity)
+{
+ tor_assert(chan_l);
+
+ if (chan_l->dumpstats) chan_l->dumpstats(chan_l, severity);
+}
+
+/**
* Return text description of the remote endpoint
*
* This function return a test provided by the lower layer of the remote
@@ -2836,11 +3288,10 @@ const char *
channel_get_actual_remote_descr(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- tor_assert(chan->u.cell_chan.get_remote_descr);
+ tor_assert(chan->get_remote_descr);
/* Param 1 indicates the actual description */
- return chan->u.cell_chan.get_remote_descr(chan, 1);
+ return chan->get_remote_descr(chan, 1);
}
/**
@@ -2855,11 +3306,10 @@ const char *
channel_get_canonical_remote_descr(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- tor_assert(chan->u.cell_chan.get_remote_descr);
+ tor_assert(chan->get_remote_descr);
/* Param 0 indicates the canonicalized description */
- return chan->u.cell_chan.get_remote_descr(chan, 0);
+ return chan->get_remote_descr(chan, 0);
}
/**
@@ -2873,11 +3323,10 @@ int
channel_get_addr_if_possible(channel_t *chan, tor_addr_t *addr_out)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(addr_out);
- if (chan->u.cell_chan.get_remote_addr)
- return chan->u.cell_chan.get_remote_addr(chan, addr_out);
+ if (chan->get_remote_addr)
+ return chan->get_remote_addr(chan, addr_out);
/* Else no support, method not implemented */
else return 0;
}
@@ -2895,15 +3344,14 @@ channel_has_queued_writes(channel_t *chan)
int has_writes = 0;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- tor_assert(chan->u.cell_chan.has_queued_writes);
+ tor_assert(chan->has_queued_writes);
- if (chan->u.cell_chan.outgoing_queue &&
- smartlist_len(chan->u.cell_chan.outgoing_queue) > 0) {
+ if (chan->outgoing_queue &&
+ smartlist_len(chan->outgoing_queue) > 0) {
has_writes = 1;
} else {
/* Check with the lower layer */
- has_writes = chan->u.cell_chan.has_queued_writes(chan);
+ has_writes = chan->has_queued_writes(chan);
}
return has_writes;
@@ -2920,9 +3368,8 @@ int
channel_is_bad_for_new_circs(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return chan->u.cell_chan.is_bad_for_new_circs;
+ return chan->is_bad_for_new_circs;
}
/**
@@ -2935,9 +3382,8 @@ void
channel_mark_bad_for_new_circs(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- chan->u.cell_chan.is_bad_for_new_circs = 1;
+ chan->is_bad_for_new_circs = 1;
}
/**
@@ -2952,9 +3398,8 @@ int
channel_is_client(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return chan->u.cell_chan.is_client;
+ return chan->is_client;
}
/**
@@ -2967,9 +3412,8 @@ void
channel_mark_client(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- chan->u.cell_chan.is_client = 1;
+ chan->is_client = 1;
}
/**
@@ -2983,10 +3427,9 @@ int
channel_is_canonical(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- tor_assert(chan->u.cell_chan.is_canonical);
+ tor_assert(chan->is_canonical);
- return chan->u.cell_chan.is_canonical(chan, 0);
+ return chan->is_canonical(chan, 0);
}
/**
@@ -3000,10 +3443,9 @@ int
channel_is_canonical_is_reliable(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- tor_assert(chan->u.cell_chan.is_canonical);
+ tor_assert(chan->is_canonical);
- return chan->u.cell_chan.is_canonical(chan, 1);
+ return chan->is_canonical(chan, 1);
}
/**
@@ -3017,9 +3459,8 @@ int
channel_is_incoming(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return chan->u.cell_chan.is_incoming;
+ return chan->is_incoming;
}
/**
@@ -3033,9 +3474,8 @@ void
channel_mark_incoming(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- chan->u.cell_chan.is_incoming = 1;
+ chan->is_incoming = 1;
}
/**
@@ -3052,9 +3492,8 @@ int
channel_is_local(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return chan->u.cell_chan.is_local;
+ return chan->is_local;
}
/**
@@ -3069,9 +3508,8 @@ void
channel_mark_local(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- chan->u.cell_chan.is_local = 1;
+ chan->is_local = 1;
}
/**
@@ -3086,9 +3524,8 @@ int
channel_is_outgoing(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return !(chan->u.cell_chan.is_incoming);
+ return !(chan->is_incoming);
}
/**
@@ -3102,9 +3539,8 @@ void
channel_mark_outgoing(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- chan->u.cell_chan.is_incoming = 0;
+ chan->is_incoming = 0;
}
/*********************
@@ -3112,7 +3548,7 @@ channel_mark_outgoing(channel_t *chan)
********************/
/**
- * Update the created timestamp
+ * Update the created timestamp for a channel
*
* This updates the channel's created timestamp and should only be called
* from channel_init().
@@ -3129,7 +3565,24 @@ channel_timestamp_created(channel_t *chan)
}
/**
- * Update the last active timestamp.
+ * Update the created timestamp for a channel listener
+ *
+ * This updates the channel listener's created timestamp and should only be
+ * called from channel_init_listener().
+ */
+
+void
+channel_listener_timestamp_created(channel_listener_t *chan_l)
+{
+ time_t now = time(NULL);
+
+ tor_assert(chan_l);
+
+ chan_l->timestamp_created = now;
+}
+
+/**
+ * Update the last active timestamp for a channel
*
* This function updates the channel's last active timestamp; it should be
* called by the lower layer whenever there is activity on the channel which
@@ -3150,21 +3603,36 @@ channel_timestamp_active(channel_t *chan)
}
/**
+ * Update the last active timestamp for a channel listener
+ */
+
+void
+channel_listener_timestamp_active(channel_listener_t *chan_l)
+{
+ time_t now = time(NULL);
+
+ tor_assert(chan_l);
+
+ chan_l->timestamp_active = now;
+}
+
+/**
* Update the last accepted timestamp.
*
- * This function updates the channel's last accepted timestamp; it should be
- * called whenever a new incoming channel is accepted on a listener.
+ * This function updates the channel listener's last accepted timestamp; it
+ * should be called whenever a new incoming channel is accepted on a
+ * listener.
*/
void
-channel_timestamp_accepted(channel_t *chan)
+channel_listener_timestamp_accepted(channel_listener_t *chan_l)
{
time_t now = time(NULL);
- tor_assert(chan);
- tor_assert(chan->is_listener);
+ tor_assert(chan_l);
- chan->u.listener.timestamp_accepted = now;
+ chan_l->timestamp_active = now;
+ chan_l->timestamp_accepted = now;
}
/**
@@ -3180,9 +3648,8 @@ channel_timestamp_client(channel_t *chan)
time_t now = time(NULL);
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- chan->u.cell_chan.timestamp_client = now;
+ chan->timestamp_client = now;
}
/**
@@ -3198,11 +3665,10 @@ channel_timestamp_drained(channel_t *chan)
time_t now = time(NULL);
tor_assert(chan);
- tor_assert(!(chan->is_listener));
chan->timestamp_active = now;
- chan->u.cell_chan.timestamp_drained = now;
- chan->u.cell_chan.timestamp_xmit = now;
+ chan->timestamp_drained = now;
+ chan->timestamp_xmit = now;
}
/**
@@ -3218,10 +3684,9 @@ channel_timestamp_recv(channel_t *chan)
time_t now = time(NULL);
tor_assert(chan);
- tor_assert(!(chan->is_listener));
chan->timestamp_active = now;
- chan->u.cell_chan.timestamp_recv = now;
+ chan->timestamp_recv = now;
}
/**
@@ -3236,10 +3701,9 @@ channel_timestamp_xmit(channel_t *chan)
time_t now = time(NULL);
tor_assert(chan);
- tor_assert(!(chan->is_listener));
chan->timestamp_active = now;
- chan->u.cell_chan.timestamp_xmit = now;
+ chan->timestamp_xmit = now;
}
/***************************************************************
@@ -3247,7 +3711,7 @@ channel_timestamp_xmit(channel_t *chan)
**************************************************************/
/**
- * Query created timestamp
+ * Query created timestamp for a channel
*/
time_t
@@ -3259,7 +3723,19 @@ channel_when_created(channel_t *chan)
}
/**
- * Query last active timestamp
+ * Query created timestamp for a channel listener
+ */
+
+time_t
+channel_listener_when_created(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l);
+
+ return chan_l->timestamp_created;
+}
+
+/**
+ * Query last active timestamp for a channel
*/
time_t
@@ -3271,16 +3747,27 @@ channel_when_last_active(channel_t *chan)
}
/**
- * Query last accepted timestamp
+ * Query last active timestamp for a channel listener
*/
time_t
-channel_when_last_accepted(channel_t *chan)
+channel_listener_when_last_active(channel_listener_t *chan_l)
{
- tor_assert(chan);
- tor_assert(chan->is_listener);
+ tor_assert(chan_l);
+
+ return chan_l->timestamp_active;
+}
+
+/**
+ * Query last accepted timestamp for a channel listener
+ */
+
+time_t
+channel_listener_when_last_accepted(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l);
- return chan->u.listener.timestamp_accepted;
+ return chan_l->timestamp_accepted;
}
/**
@@ -3291,9 +3778,8 @@ time_t
channel_when_last_client(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return chan->u.cell_chan.timestamp_client;
+ return chan->timestamp_client;
}
/**
@@ -3304,9 +3790,8 @@ time_t
channel_when_last_drained(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return chan->u.cell_chan.timestamp_drained;
+ return chan->timestamp_drained;
}
/**
@@ -3317,9 +3802,8 @@ time_t
channel_when_last_recv(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return chan->u.cell_chan.timestamp_recv;
+ return chan->timestamp_recv;
}
/**
@@ -3330,9 +3814,8 @@ time_t
channel_when_last_xmit(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return chan->u.cell_chan.timestamp_xmit;
+ return chan->timestamp_xmit;
}
/**
@@ -3340,12 +3823,11 @@ channel_when_last_xmit(channel_t *chan)
*/
uint64_t
-channel_count_accepted(channel_t *chan)
+channel_listener_count_accepted(channel_listener_t *chan_l)
{
- tor_assert(chan);
+ tor_assert(chan_l);
- if (chan->is_listener) return chan->u.listener.n_accepted;
- else return 0;
+ return chan_l->n_accepted;
}
/**
@@ -3357,8 +3839,7 @@ channel_count_recved(channel_t *chan)
{
tor_assert(chan);
- if (!(chan->is_listener)) return chan->u.cell_chan.n_cells_recved;
- else return 0;
+ return chan->n_cells_recved;
}
/**
@@ -3370,8 +3851,7 @@ channel_count_xmitted(channel_t *chan)
{
tor_assert(chan);
- if (!(chan->is_listener)) return chan->u.cell_chan.n_cells_xmitted;
- else return 0;
+ return chan->n_cells_xmitted;
}
/**
@@ -3385,11 +3865,10 @@ int
channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- tor_assert(chan->u.cell_chan.matches_extend_info);
+ tor_assert(chan->matches_extend_info);
tor_assert(extend_info);
- return chan->u.cell_chan.matches_extend_info(chan, extend_info);
+ return chan->matches_extend_info(chan, extend_info);
}
/**
@@ -3404,11 +3883,10 @@ channel_matches_target_addr_for_extend(channel_t *chan,
const tor_addr_t *target)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- tor_assert(chan->u.cell_chan.matches_target);
+ tor_assert(chan->matches_target);
tor_assert(target);
- return chan->u.cell_chan.matches_target(chan, target);
+ return chan->matches_target(chan, target);
}
/**
@@ -3425,7 +3903,6 @@ channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd)
crypto_pk_t *our_identity;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
started_here = channel_is_outgoing(chan);
our_identity = started_here ?
@@ -3433,12 +3910,12 @@ channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd)
if (identity_rcvd) {
if (crypto_pk_cmp_keys(our_identity, identity_rcvd) < 0) {
- chan->u.cell_chan.circ_id_type = CIRC_ID_TYPE_LOWER;
+ chan->circ_id_type = CIRC_ID_TYPE_LOWER;
} else {
- chan->u.cell_chan.circ_id_type = CIRC_ID_TYPE_HIGHER;
+ chan->circ_id_type = CIRC_ID_TYPE_HIGHER;
}
} else {
- chan->u.cell_chan.circ_id_type = CIRC_ID_TYPE_NEITHER;
+ chan->circ_id_type = CIRC_ID_TYPE_NEITHER;
}
}
diff --git a/src/or/channel.h b/src/or/channel.h
index 70ea30f..c31806c 100644
--- a/src/or/channel.h
+++ b/src/or/channel.h
@@ -12,7 +12,7 @@
#include "or.h"
/* Channel handler function pointer typedefs */
-typedef void (*channel_listener_fn_ptr)(channel_t *, channel_t *);
+typedef void (*channel_listener_fn_ptr)(channel_listener_t *, channel_t *);
typedef void (*channel_cell_handler_fn_ptr)(channel_t *, cell_t *);
typedef void (*channel_var_cell_handler_fn_ptr)(channel_t *, var_cell_t *);
@@ -37,12 +37,6 @@ struct channel_s {
/* Should we expect to see this channel in the channel lists? */
unsigned char registered:1;
- /** Set this if this channel is created in CHANNEL_STATE_LISTEN, so
- * lower-layer close methods that see the channel in CHANNEL_STATE_CLOSING
- * know.
- */
- unsigned int is_listener:1;
-
/** Why did we close?
*/
enum {
@@ -67,171 +61,210 @@ struct channel_s {
/* Optional method to dump transport-specific statistics on the channel */
void (*dumpstats)(channel_t *, int);
- union {
- struct {
- /* Registered listen handler to call on incoming connection */
- channel_listener_fn_ptr listener;
-
- /* List of pending incoming connections */
- smartlist_t *incoming_list;
-
- /* Timestamps for listeners */
- time_t timestamp_accepted;
-
- /* Counters for listeners */
- uint64_t n_accepted;
- } listener;
- struct {
- /* Registered handlers for incoming cells */
- channel_cell_handler_fn_ptr cell_handler;
- channel_var_cell_handler_fn_ptr var_cell_handler;
-
- /* Methods implemented by the lower layer */
-
- /*
- * Ask the underlying transport what the remote endpoint address is, in
- * a tor_addr_t. This is optional and subclasses may leave this NULL.
- * If they implement it, they should write the address out to the
- * provided tor_addr_t *, and return 1 if successful or 0 if no address
- * available.
- */
- int (*get_remote_addr)(channel_t *, tor_addr_t *);
- /*
- * Get a text description of the remote endpoint; canonicalized if the
- * arg is 0, or the one we originally connected to/received from if it's
- * 1.
- */
- const char * (*get_remote_descr)(channel_t *, int);
- /* Check if the lower layer has queued writes */
- int (*has_queued_writes)(channel_t *);
- /*
- * If the second param is zero, ask the lower layer if this is
- * 'canonical', for a transport-specific definition of canonical; if
- * it is 1, ask if the answer to the preceding query is safe to rely
- * on.
- */
- int (*is_canonical)(channel_t *, int);
- /* Check if this channel matches a specified extend_info_t */
- int (*matches_extend_info)(channel_t *, extend_info_t *);
- /* Check if this channel matches a target address when extending */
- int (*matches_target)(channel_t *, const tor_addr_t *);
- /* Write a cell to an open channel */
- int (*write_cell)(channel_t *, cell_t *);
- /* Write a packed cell to an open channel */
- int (*write_packed_cell)(channel_t *, packed_cell_t *);
- /* Write a variable-length cell to an open channel */
- int (*write_var_cell)(channel_t *, var_cell_t *);
-
- /*
- * Hash of the public RSA key for the other side's identity key, or
- * zeroes if the other side hasn't shown us a valid identity key.
- */
- char identity_digest[DIGEST_LEN];
- /* Nickname of the OR on the other side, or NULL if none. */
- char *nickname;
-
- /*
- * Linked list of channels with the same identity digest, for the
- * digest->channel map
- */
- channel_t *next_with_same_id, *prev_with_same_id;
-
- /* List of incoming cells to handle */
- smartlist_t *incoming_queue;
-
- /* List of queued outgoing cells */
- smartlist_t *outgoing_queue;
-
- /* Circuit stuff for use by relay.c */
-
- /*
- * Double-linked ring of circuits with queued cells waiting for room to
- * free up on this connection's outbuf. Every time we pull cells from
- * a circuit, we advance this pointer to the next circuit in the ring.
- */
- struct circuit_t *active_circuits;
- /*
- * Priority queue of cell_ewma_t for circuits with queued cells waiting
- * for room to free up on this connection's outbuf. Kept in heap order
- * according to EWMA.
- *
- * This is redundant with active_circuits; if we ever decide only to use
- * the cell_ewma algorithm for choosing circuits, we can remove
- * active_circuits.
- */
- smartlist_t *active_circuit_pqueue;
- /*
- * The tick on which the cell_ewma_ts in active_circuit_pqueue last had
- * their ewma values rescaled.
- */
- unsigned active_circuit_pqueue_last_recalibrated;
-
- /* Circuit ID generation stuff for use by circuitbuild.c */
-
- /*
- * When we send CREATE cells along this connection, which half of the
- * space should we use?
- */
- circ_id_type_t circ_id_type:2;
- /*
- * Which circ_id do we try to use next on this connection? This is
- * always in the range 0..1<<15-1.
- */
- circid_t next_circ_id;
-
- /* How many circuits use this connection as p_chan or n_chan? */
- int n_circuits;
-
- /*
- * True iff this channel shouldn't get any new circs attached to it,
- * because the connection is too old, or because there's a better one.
- * More generally, this flag is used to note an unhealthy connection;
- * for example, if a bad connection fails we shouldn't assume that the
- * router itself has a problem.
- */
- unsigned int is_bad_for_new_circs:1;
-
- /** True iff we have decided that the other end of this connection
- * is a client. Channels with this flag set should never be used
- * to satisfy an EXTEND request. */
- unsigned int is_client:1;
-
- /** Set if the channel was initiated remotely (came from a listener) */
- unsigned int is_incoming:1;
-
- /** Set by lower layer if this is local; i.e., everything it communicates
- * with for this channel returns true for is_local_addr(). This is used
- * to decide whether to declare reachability when we receive something on
- * this channel in circuitbuild.c
- */
- unsigned int is_local:1;
-
- /** Channel timestamps for cell channels */
- time_t timestamp_client; /* Client used this, according to relay.c */
- time_t timestamp_drained; /* Output queue empty */
- time_t timestamp_recv; /* Cell received from lower layer */
- time_t timestamp_xmit; /* Cell sent to lower layer */
-
- /* Timestamp for relay.c */
- time_t timestamp_last_added_nonpadding;
-
- /** Unique ID for measuring direct network status requests;vtunneled ones
- * come over a circuit_t, which has a dirreq_id field as well, but is a
- * distinct namespace. */
- uint64_t dirreq_id;
-
- /** Channel counters for cell channels */
- uint64_t n_cells_recved;
- uint64_t n_cells_xmitted;
- } cell_chan;
- } u;
+ /* Registered handlers for incoming cells */
+ channel_cell_handler_fn_ptr cell_handler;
+ channel_var_cell_handler_fn_ptr var_cell_handler;
+
+ /* Methods implemented by the lower layer */
+
+ /*
+ * Ask the underlying transport what the remote endpoint address is, in
+ * a tor_addr_t. This is optional and subclasses may leave this NULL.
+ * If they implement it, they should write the address out to the
+ * provided tor_addr_t *, and return 1 if successful or 0 if no address
+ * available.
+ */
+ int (*get_remote_addr)(channel_t *, tor_addr_t *);
+ /*
+ * Get a text description of the remote endpoint; canonicalized if the
+ * arg is 0, or the one we originally connected to/received from if it's
+ * 1.
+ */
+ const char * (*get_remote_descr)(channel_t *, int);
+ /* Check if the lower layer has queued writes */
+ int (*has_queued_writes)(channel_t *);
+ /*
+ * If the second param is zero, ask the lower layer if this is
+ * 'canonical', for a transport-specific definition of canonical; if
+ * it is 1, ask if the answer to the preceding query is safe to rely
+ * on.
+ */
+ int (*is_canonical)(channel_t *, int);
+ /* Check if this channel matches a specified extend_info_t */
+ int (*matches_extend_info)(channel_t *, extend_info_t *);
+ /* Check if this channel matches a target address when extending */
+ int (*matches_target)(channel_t *, const tor_addr_t *);
+ /* Write a cell to an open channel */
+ int (*write_cell)(channel_t *, cell_t *);
+ /* Write a packed cell to an open channel */
+ int (*write_packed_cell)(channel_t *, packed_cell_t *);
+ /* Write a variable-length cell to an open channel */
+ int (*write_var_cell)(channel_t *, var_cell_t *);
+
+ /*
+ * Hash of the public RSA key for the other side's identity key, or
+ * zeroes if the other side hasn't shown us a valid identity key.
+ */
+ char identity_digest[DIGEST_LEN];
+ /* Nickname of the OR on the other side, or NULL if none. */
+ char *nickname;
+
+ /*
+ * Linked list of channels with the same identity digest, for the
+ * digest->channel map
+ */
+ channel_t *next_with_same_id, *prev_with_same_id;
+
+ /* List of incoming cells to handle */
+ smartlist_t *incoming_queue;
+
+ /* List of queued outgoing cells */
+ smartlist_t *outgoing_queue;
+
+ /* Circuit stuff for use by relay.c */
+
+ /*
+ * Double-linked ring of circuits with queued cells waiting for room to
+ * free up on this connection's outbuf. Every time we pull cells from
+ * a circuit, we advance this pointer to the next circuit in the ring.
+ */
+ struct circuit_t *active_circuits;
+ /*
+ * Priority queue of cell_ewma_t for circuits with queued cells waiting
+ * for room to free up on this connection's outbuf. Kept in heap order
+ * according to EWMA.
+ *
+ * This is redundant with active_circuits; if we ever decide only to use
+ * the cell_ewma algorithm for choosing circuits, we can remove
+ * active_circuits.
+ */
+ smartlist_t *active_circuit_pqueue;
+ /*
+ * The tick on which the cell_ewma_ts in active_circuit_pqueue last had
+ * their ewma values rescaled.
+ */
+ unsigned active_circuit_pqueue_last_recalibrated;
+
+ /* Circuit ID generation stuff for use by circuitbuild.c */
+
+ /*
+ * When we send CREATE cells along this connection, which half of the
+ * space should we use?
+ */
+ circ_id_type_t circ_id_type:2;
+ /*
+ * Which circ_id do we try to use next on this connection? This is
+ * always in the range 0..1<<15-1.
+ */
+ circid_t next_circ_id;
+
+ /* How many circuits use this connection as p_chan or n_chan? */
+ int n_circuits;
+
+ /*
+ * True iff this channel shouldn't get any new circs attached to it,
+ * because the connection is too old, or because there's a better one.
+ * More generally, this flag is used to note an unhealthy connection;
+ * for example, if a bad connection fails we shouldn't assume that the
+ * router itself has a problem.
+ */
+ unsigned int is_bad_for_new_circs:1;
+
+ /** True iff we have decided that the other end of this connection
+ * is a client. Channels with this flag set should never be used
+ * to satisfy an EXTEND request. */
+ unsigned int is_client:1;
+
+ /** Set if the channel was initiated remotely (came from a listener) */
+ unsigned int is_incoming:1;
+
+ /** Set by lower layer if this is local; i.e., everything it communicates
+ * with for this channel returns true for is_local_addr(). This is used
+ * to decide whether to declare reachability when we receive something on
+ * this channel in circuitbuild.c
+ */
+ unsigned int is_local:1;
+
+ /** Channel timestamps for cell channels */
+ time_t timestamp_client; /* Client used this, according to relay.c */
+ time_t timestamp_drained; /* Output queue empty */
+ time_t timestamp_recv; /* Cell received from lower layer */
+ time_t timestamp_xmit; /* Cell sent to lower layer */
+
+ /* Timestamp for relay.c */
+ time_t timestamp_last_added_nonpadding;
+
+ /** Unique ID for measuring direct network status requests;vtunneled ones
+ * come over a circuit_t, which has a dirreq_id field as well, but is a
+ * distinct namespace. */
+ uint64_t dirreq_id;
+
+ /** Channel counters for cell channels */
+ uint64_t n_cells_recved;
+ uint64_t n_cells_xmitted;
+};
+
+struct channel_listener_s {
+ /* Current channel listener state */
+ channel_listener_state_t state;
+
+ /* Globally unique ID number for a channel over the lifetime of a Tor
+ * process.
+ */
+ uint64_t global_identifier;
+
+ /* Should we expect to see this channel in the channel lists? */
+ unsigned char registered:1;
+
+ /** Why did we close?
+ */
+ enum {
+ CHANNEL_LISTENER_NOT_CLOSING = 0,
+ CHANNEL_LISTENER_CLOSE_REQUESTED,
+ CHANNEL_LISTENER_CLOSE_FROM_BELOW,
+ CHANNEL_LISTENER_CLOSE_FOR_ERROR
+ } reason_for_closing;
+
+ /* Timestamps for both cell channels and listeners */
+ time_t timestamp_created; /* Channel created */
+ time_t timestamp_active; /* Any activity */
+
+ /* Methods implemented by the lower layer */
+
+ /* Free a channel */
+ void (*free)(channel_listener_t *);
+ /* Close an open channel */
+ void (*close)(channel_listener_t *);
+ /* Describe the transport subclass for this channel */
+ const char * (*describe_transport)(channel_listener_t *);
+ /* Optional method to dump transport-specific statistics on the channel */
+ void (*dumpstats)(channel_listener_t *, int);
+
+ /* Registered listen handler to call on incoming connection */
+ channel_listener_fn_ptr listener;
+
+ /* List of pending incoming connections */
+ smartlist_t *incoming_list;
+
+ /* Timestamps for listeners */
+ time_t timestamp_accepted;
+
+ /* Counters for listeners */
+ uint64_t n_accepted;
};
/* Channel state manipulations */
int channel_state_is_valid(channel_state_t state);
+int channel_listener_state_is_valid(channel_listener_state_t state);
+
int channel_state_can_transition(channel_state_t from, channel_state_t to);
+int channel_listener_state_can_transition(channel_listener_state_t from,
+ channel_listener_state_t to);
+
const char * channel_state_to_string(channel_state_t state);
+const char *
+channel_listener_state_to_string(channel_listener_state_t state);
/* Abstract channel operations */
@@ -240,12 +273,16 @@ void channel_write_cell(channel_t *chan, cell_t *cell);
void channel_write_packed_cell(channel_t *chan, packed_cell_t *cell);
void channel_write_var_cell(channel_t *chan, var_cell_t *cell);
+void channel_listener_mark_for_close(channel_listener_t *chan_l);
+
/* Channel callback registrations */
/* Listener callback */
-channel_listener_fn_ptr channel_get_listener_fn(channel_t *chan);
-void channel_set_listener_fn(channel_t *chan,
- channel_listener_fn_ptr listener);
+channel_listener_fn_ptr
+channel_listener_get_listener_fn(channel_listener_t *chan);
+
+void channel_listener_set_listener_fn(channel_listener_t *chan,
+ channel_listener_fn_ptr listener);
/* Incoming cell callbacks */
channel_cell_handler_fn_ptr channel_get_cell_handler(channel_t *chan);
@@ -258,16 +295,18 @@ void channel_set_cell_handlers(channel_t *chan,
channel_var_cell_handler_fn_ptr
var_cell_handler);
-/* Clean up closed channels periodically; called from run_scheduled_events()
- * in main.c
+/* Clean up closed channels and channel listeners periodically; these are
+ * called from run_scheduled_events() in main.c.
*/
void channel_run_cleanup(void);
+void channel_listener_run_cleanup(void);
/* Close all channels and deallocate everything */
void channel_free_all(void);
/* Dump some statistics in the log */
void channel_dumpstats(int severity);
+void channel_listener_dumpstats(int severity);
#ifdef _TOR_CHANNEL_INTERNAL
@@ -277,20 +316,29 @@ void channel_dumpstats(int severity);
* constructors.
*/
-void channel_init_for_cells(channel_t *chan);
-void channel_init_listener(channel_t *chan);
+void channel_init(channel_t *chan);
+void channel_init_listener(channel_listener_t *chan);
/* Channel registration/unregistration */
void channel_register(channel_t *chan);
void channel_unregister(channel_t *chan);
+/* Channel listener registration/unregistration */
+void channel_listener_register(channel_listener_t *chan_l);
+void channel_listener_unregister(channel_listener_t *chan_l);
+
/* Close from below */
void channel_close_from_lower_layer(channel_t *chan);
void channel_close_for_error(channel_t *chan);
void channel_closed(channel_t *chan);
+void channel_listener_close_from_lower_layer(channel_listener_t *chan_l);
+void channel_listener_close_for_error(channel_listener_t *chan_l);
+void channel_listener_closed(channel_listener_t *chan_l);
+
/* Free a channel */
void channel_free(channel_t *chan);
+void channel_listener_free(channel_listener_t *chan_l);
/* State/metadata setters */
@@ -306,17 +354,24 @@ void channel_set_remote_end(channel_t *chan,
const char *identity_digest,
const char *nickname);
+void channel_listener_change_state(channel_listener_t *chan_l,
+ channel_listener_state_t to_state);
+
/* Timestamp updates */
void channel_timestamp_created(channel_t *chan);
-void channel_timestamp_accepted(channel_t *chan);
void channel_timestamp_active(channel_t *chan);
void channel_timestamp_drained(channel_t *chan);
void channel_timestamp_recv(channel_t *chan);
void channel_timestamp_xmit(channel_t *chan);
+void channel_listener_timestamp_created(channel_listener_t *chan_l);
+void channel_listener_timestamp_active(channel_listener_t *chan_l);
+void channel_listener_timestamp_accepted(channel_listener_t *chan_l);
+
/* Incoming channel handling */
-void channel_process_incoming(channel_t *listener);
-void channel_queue_incoming(channel_t *listener, channel_t *incoming);
+void channel_listener_process_incoming(channel_listener_t *listener);
+void channel_listener_queue_incoming(channel_listener_t *listener,
+ channel_t *incoming);
/* Incoming cell handling */
void channel_process_cells(channel_t *chan);
@@ -401,19 +456,29 @@ int channel_matches_target_addr_for_extend(channel_t *chan,
void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd);
void channel_timestamp_client(channel_t *chan);
+const char * channel_listener_describe_transport(channel_listener_t *chan_l);
+void channel_listener_dump_statistics(channel_listener_t *chan_l,
+ int severity);
+void channel_listener_dump_transport_statistics(channel_listener_t *chan_l,
+ int severity);
+
/* Timestamp queries */
time_t channel_when_created(channel_t *chan);
-time_t channel_when_last_accepted(channel_t *chan);
time_t channel_when_last_active(channel_t *chan);
time_t channel_when_last_client(channel_t *chan);
time_t channel_when_last_drained(channel_t *chan);
time_t channel_when_last_recv(channel_t *chan);
time_t channel_when_last_xmit(channel_t *chan);
+time_t channel_listener_when_created(channel_listener_t *chan_l);
+time_t channel_listener_when_last_active(channel_listener_t *chan_l);
+time_t channel_listener_when_last_accepted(channel_listener_t *chan_l);
+
/* Counter queries */
-uint64_t channel_count_accepted(channel_t *chan);
uint64_t channel_count_recved(channel_t *chan);
uint64_t channel_count_xmitted(channel_t *chan);
+uint64_t channel_listener_count_accepted(channel_listener_t *chan_l);
+
#endif
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index bb90ce5..93e0636 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -42,7 +42,7 @@ uint64_t stats_n_authenticate_cells_processed = 0;
uint64_t stats_n_authorize_cells_processed = 0;
/** Active listener, if any */
-channel_tls_t *channel_tls_listener = NULL;
+channel_listener_t *channel_tls_listener = NULL;
/* channel_tls_t method declarations */
@@ -66,6 +66,12 @@ static int channel_tls_write_packed_cell_method(channel_t *chan,
static int channel_tls_write_var_cell_method(channel_t *chan,
var_cell_t *var_cell);
+/* channel_listener_tls_t method declarations */
+
+static void channel_tls_listener_close_method(channel_listener_t *chan_l);
+static const char *
+channel_tls_listener_describe_transport_method(channel_listener_t *chan_l);
+
/** Handle incoming cells for the handshake stuff here rather than
* passing them on up. */
@@ -97,20 +103,19 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
{
channel_tls_t *tlschan = tor_malloc_zero(sizeof(*tlschan));
channel_t *chan = TLS_CHAN_TO_BASE(tlschan);
- channel_init_for_cells(chan);
+ channel_init(chan);
chan->state = CHANNEL_STATE_OPENING;
chan->close = channel_tls_close_method;
chan->describe_transport = channel_tls_describe_transport_method;
- chan->u.cell_chan.get_remote_addr = channel_tls_get_remote_addr_method;
- chan->u.cell_chan.get_remote_descr = channel_tls_get_remote_descr_method;
- chan->u.cell_chan.has_queued_writes = channel_tls_has_queued_writes_method;
- chan->u.cell_chan.is_canonical = channel_tls_is_canonical_method;
- chan->u.cell_chan.matches_extend_info =
- channel_tls_matches_extend_info_method;
- chan->u.cell_chan.matches_target = channel_tls_matches_target_method;
- chan->u.cell_chan.write_cell = channel_tls_write_cell_method;
- chan->u.cell_chan.write_packed_cell = channel_tls_write_packed_cell_method;
- chan->u.cell_chan.write_var_cell = channel_tls_write_var_cell_method;
+ chan->get_remote_addr = channel_tls_get_remote_addr_method;
+ chan->get_remote_descr = channel_tls_get_remote_descr_method;
+ chan->has_queued_writes = channel_tls_has_queued_writes_method;
+ chan->is_canonical = channel_tls_is_canonical_method;
+ chan->matches_extend_info = channel_tls_matches_extend_info_method;
+ chan->matches_target = channel_tls_matches_target_method;
+ chan->write_cell = channel_tls_write_cell_method;
+ chan->write_packed_cell = channel_tls_write_packed_cell_method;
+ chan->write_var_cell = channel_tls_write_var_cell_method;
log_debug(LD_CHANNEL,
"In channel_tls_connect() for channel %p "
@@ -121,9 +126,8 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
if (is_local_addr(addr)) channel_mark_local(chan);
channel_mark_outgoing(chan);
- chan->u.cell_chan.active_circuit_pqueue = smartlist_new();
- chan->u.cell_chan.active_circuit_pqueue_last_recalibrated =
- cell_ewma_get_tick();
+ chan->active_circuit_pqueue = smartlist_new();
+ chan->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick();
/* Set up or_connection stuff */
tlschan->conn = connection_or_connect(addr, port, id_digest, tlschan);
@@ -140,7 +144,7 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
goto done;
err:
- smartlist_free(chan->u.cell_chan.active_circuit_pqueue);
+ smartlist_free(chan->active_circuit_pqueue);
tor_free(tlschan);
chan = NULL;
@@ -154,14 +158,14 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
/**
* Return the current channel_tls_t listener
*
- * Returns the current listening channel for incoming TLS connections, or
+ * Returns the current channel listener for incoming TLS connections, or
* NULL if none has been established
*/
-channel_t *
+channel_listener_t *
channel_tls_get_listener(void)
{
- return TLS_CHAN_TO_BASE(channel_tls_listener);
+ return channel_tls_listener;
}
/**
@@ -171,30 +175,29 @@ channel_tls_get_listener(void)
* and return that.
*/
-channel_t *
+channel_listener_t *
channel_tls_start_listener(void)
{
- channel_tls_t *listener;
- channel_t *lchan;
+ channel_listener_t *listener;
if (!channel_tls_listener) {
listener = tor_malloc_zero(sizeof(*listener));
- lchan = TLS_CHAN_TO_BASE(listener);
- channel_init_listener(lchan);
- lchan->state = CHANNEL_STATE_LISTENING;
- lchan->close = channel_tls_close_method;
- lchan->describe_transport = channel_tls_describe_transport_method;
+ channel_init_listener(listener);
+ listener->state = CHANNEL_LISTENER_STATE_LISTENING;
+ listener->close = channel_tls_listener_close_method;
+ listener->describe_transport =
+ channel_tls_listener_describe_transport_method;
channel_tls_listener = listener;
log_debug(LD_CHANNEL,
- "Starting TLS listener channel %p with global id " U64_FORMAT,
- lchan, U64_PRINTF_ARG(lchan->global_identifier));
+ "Starting TLS channel listener %p with global id " U64_FORMAT,
+ listener, U64_PRINTF_ARG(listener->global_identifier));
- channel_register(lchan);
- } else lchan = TLS_CHAN_TO_BASE(channel_tls_listener);
+ channel_listener_register(listener);
+ } else listener = channel_tls_listener;
- return lchan;
+ return listener;
}
/**
@@ -207,16 +210,13 @@ channel_tls_start_listener(void)
void
channel_tls_free_all(void)
{
- channel_t *base = NULL;
-
log_debug(LD_CHANNEL,
"Shutting down TLS channels...");
if (channel_tls_listener) {
- base = TLS_CHAN_TO_BASE(channel_tls_listener);
- channel_unregister(base);
- channel_mark_for_close(base);
- channel_free(base);
+ channel_listener_unregister(channel_tls_listener);
+ channel_listener_mark_for_close(channel_tls_listener);
+ channel_listener_free(channel_tls_listener);
channel_tls_listener = NULL;
}
@@ -237,19 +237,18 @@ channel_tls_handle_incoming(or_connection_t *orconn)
tor_assert(orconn);
tor_assert(!(orconn->chan));
- channel_init_for_cells(chan);
+ channel_init(chan);
chan->state = CHANNEL_STATE_OPENING;
chan->close = channel_tls_close_method;
chan->describe_transport = channel_tls_describe_transport_method;
- chan->u.cell_chan.get_remote_descr = channel_tls_get_remote_descr_method;
- chan->u.cell_chan.has_queued_writes = channel_tls_has_queued_writes_method;
- chan->u.cell_chan.is_canonical = channel_tls_is_canonical_method;
- chan->u.cell_chan.matches_extend_info =
- channel_tls_matches_extend_info_method;
- chan->u.cell_chan.matches_target = channel_tls_matches_target_method;
- chan->u.cell_chan.write_cell = channel_tls_write_cell_method;
- chan->u.cell_chan.write_packed_cell = channel_tls_write_packed_cell_method;
- chan->u.cell_chan.write_var_cell = channel_tls_write_var_cell_method;
+ chan->get_remote_descr = channel_tls_get_remote_descr_method;
+ chan->has_queued_writes = channel_tls_has_queued_writes_method;
+ chan->is_canonical = channel_tls_is_canonical_method;
+ chan->matches_extend_info = channel_tls_matches_extend_info_method;
+ chan->matches_target = channel_tls_matches_target_method;
+ chan->write_cell = channel_tls_write_cell_method;
+ chan->write_packed_cell = channel_tls_write_packed_cell_method;
+ chan->write_var_cell = channel_tls_write_var_cell_method;
/* Link the channel and orconn to each other */
tlschan->conn = orconn;
@@ -258,9 +257,8 @@ channel_tls_handle_incoming(or_connection_t *orconn)
if (is_local_addr(&(TO_CONN(orconn)->addr))) channel_mark_local(chan);
channel_mark_incoming(chan);
- chan->u.cell_chan.active_circuit_pqueue = smartlist_new();
- chan->u.cell_chan.active_circuit_pqueue_last_recalibrated =
- cell_ewma_get_tick();
+ chan->active_circuit_pqueue = smartlist_new();
+ chan->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick();
/* If we got one, we should register it */
if (chan) channel_register(chan);
@@ -285,43 +283,13 @@ channel_tls_close_method(channel_t *chan)
tor_assert(tlschan);
- if (chan->is_listener) {
- /*
- * Listeners we just go ahead and change state through to CLOSED, but
- * make sure to check if they're channel_tls_listener to NULL it out.
- */
- if (chan == TLS_CHAN_TO_BASE(channel_tls_listener))
- channel_tls_listener = NULL;
-
- if (!(chan->state == CHANNEL_STATE_CLOSING ||
- chan->state == CHANNEL_STATE_CLOSED ||
- chan->state == CHANNEL_STATE_ERROR)) {
- channel_change_state(chan, CHANNEL_STATE_CLOSING);
- }
-
- if (chan->u.listener.incoming_list) {
- SMARTLIST_FOREACH_BEGIN(chan->u.listener.incoming_list,
- channel_t *, ichan) {
- channel_mark_for_close(ichan);
- } SMARTLIST_FOREACH_END(ichan);
-
- smartlist_free(chan->u.listener.incoming_list);
- chan->u.listener.incoming_list = NULL;
- }
-
- if (!(chan->state == CHANNEL_STATE_CLOSED ||
- chan->state == CHANNEL_STATE_ERROR)) {
- channel_change_state(chan, CHANNEL_STATE_CLOSED);
- }
- } else {
- if (tlschan->conn) connection_or_close_normally(tlschan->conn, 1);
- else {
- /* Weird - we'll have to change the state ourselves, I guess */
- log_info(LD_CHANNEL,
- "Tried to close channel_tls_t %p with NULL conn",
- tlschan);
- channel_change_state(chan, CHANNEL_STATE_ERROR);
- }
+ if (tlschan->conn) connection_or_close_normally(tlschan->conn, 1);
+ else {
+ /* Weird - we'll have to change the state ourselves, I guess */
+ log_info(LD_CHANNEL,
+ "Tried to close channel_tls_t %p with NULL conn",
+ tlschan);
+ channel_change_state(chan, CHANNEL_STATE_ERROR);
}
}
@@ -342,23 +310,19 @@ channel_tls_describe_transport_method(channel_t *chan)
tor_assert(chan);
- if (chan->is_listener) {
- rv = "TLS channel (listening)";
- } else {
- tlschan = BASE_CHAN_TO_TLS(chan);
+ tlschan = BASE_CHAN_TO_TLS(chan);
- if (tlschan->conn) {
- id = TO_CONN(tlschan->conn)->global_identifier;
+ if (tlschan->conn) {
+ id = TO_CONN(tlschan->conn)->global_identifier;
- if (buf) tor_free(buf);
- tor_asprintf(&buf,
- "TLS channel (connection " U64_FORMAT ")",
- U64_PRINTF_ARG(id));
+ if (buf) tor_free(buf);
+ tor_asprintf(&buf,
+ "TLS channel (connection " U64_FORMAT ")",
+ U64_PRINTF_ARG(id));
- rv = buf;
- } else {
- rv = "TLS channel (no connection)";
- }
+ rv = buf;
+ } else {
+ rv = "TLS channel (no connection)";
}
return rv;
@@ -603,6 +567,65 @@ channel_tls_write_var_cell_method(channel_t *chan, var_cell_t *var_cell)
return 1;
}
+/*************************************************
+ * Method implementations for channel_listener_t *
+ ************************************************/
+
+/**
+ * Close a channel_listener_t
+ *
+ * This implements the close method for channel_listener_t
+ */
+
+static void
+channel_tls_listener_close_method(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l);
+
+ /*
+ * Listeners we just go ahead and change state through to CLOSED, but
+ * make sure to check if they're channel_tls_listener to NULL it out.
+ */
+ if (chan_l == channel_tls_listener)
+ channel_tls_listener = NULL;
+
+ if (!(chan_l->state == CHANNEL_LISTENER_STATE_CLOSING ||
+ chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR)) {
+ channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSING);
+ }
+
+ if (chan_l->incoming_list) {
+ SMARTLIST_FOREACH_BEGIN(chan_l->incoming_list,
+ channel_t *, ichan) {
+ channel_mark_for_close(ichan);
+ } SMARTLIST_FOREACH_END(ichan);
+
+ smartlist_free(chan_l->incoming_list);
+ chan_l->incoming_list = NULL;
+ }
+
+ if (!(chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
+ chan_l->state == CHANNEL_LISTENER_STATE_ERROR)) {
+ channel_listener_change_state(chan_l, CHANNEL_LISTENER_STATE_CLOSED);
+ }
+}
+
+/**
+ * Describe the transport for a channel_listener_t
+ *
+ * This returns the string "TLS channel (listening)" to the upper
+ * layer.
+ */
+
+static const char *
+channel_tls_listener_describe_transport_method(channel_listener_t *chan_l)
+{
+ tor_assert(chan_l);
+
+ return "TLS channel (listening)";
+}
+
/*******************************************************
* Functions for handling events on an or_connection_t *
******************************************************/
@@ -782,8 +805,6 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
return;
}
- tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
-
handshaking = (TO_CONN(conn)->state != OR_CONN_STATE_OPEN);
if (conn->_base.marked_for_close)
@@ -892,8 +913,6 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn)
return;
}
- tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
-
handshaking = (TO_CONN(conn)->state != OR_CONN_STATE_OPEN);
if (TO_CONN(conn)->marked_for_close)
@@ -1049,7 +1068,6 @@ enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan)
tor_assert(cell);
tor_assert(chan);
- tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn);
started_here = connection_or_nonopen_was_started_here(chan->conn);
@@ -1091,7 +1109,6 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
tor_assert(cell);
tor_assert(chan);
- tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn);
started_here = connection_or_nonopen_was_started_here(chan->conn);
@@ -1247,7 +1264,6 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
tor_assert(cell);
tor_assert(chan);
- tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn);
if (chan->conn->link_proto < 2) {
@@ -1386,7 +1402,7 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
safe_str_client(chan->conn->_base.address),
chan->conn->_base.port,
(int)(chan->conn->link_proto),
- hex_str(TLS_CHAN_TO_BASE(chan)->u.cell_chan.identity_digest,
+ hex_str(TLS_CHAN_TO_BASE(chan)->identity_digest,
DIGEST_LEN),
tor_addr_is_null(&my_apparent_addr) ?
"<none>" : fmt_and_decorate_addr(&my_apparent_addr));
@@ -1422,7 +1438,6 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
tor_assert(cell);
tor_assert(chan);
- tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn);
#define ERR(s) \
@@ -1515,7 +1530,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
* _trying_ to connect to an authority, not necessarily if we _did_ connect
* to one. */
if (router_digest_is_trusted_dir(
- TLS_CHAN_TO_BASE(chan)->u.cell_chan.identity_digest))
+ TLS_CHAN_TO_BASE(chan)->identity_digest))
severity = LOG_WARN;
else
severity = LOG_PROTOCOL_WARN;
@@ -1616,7 +1631,6 @@ channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan)
tor_assert(cell);
tor_assert(chan);
- tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn);
#define ERR(s) \
@@ -1714,7 +1728,6 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
tor_assert(cell);
tor_assert(chan);
- tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn);
#define ERR(s) \
diff --git a/src/or/channeltls.h b/src/or/channeltls.h
index 3b7d6a7..b38e12a 100644
--- a/src/or/channeltls.h
+++ b/src/or/channeltls.h
@@ -28,8 +28,8 @@ struct channel_tls_s {
channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port,
const char *id_digest);
-channel_t * channel_tls_get_listener(void);
-channel_t * channel_tls_start_listener(void);
+channel_listener_t * channel_tls_get_listener(void);
+channel_listener_t * channel_tls_start_listener(void);
channel_t * channel_tls_handle_incoming(or_connection_t *orconn);
/* Things for connection_or.c to call back into */
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 5ef67bd..749985f 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1711,23 +1711,22 @@ get_unique_circ_id_by_chan(channel_t *chan)
circid_t high_bit;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- if (chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_NEITHER) {
+ if (chan->circ_id_type == CIRC_ID_TYPE_NEITHER) {
log_warn(LD_BUG,
"Trying to pick a circuit ID for a connection from "
"a client with no identity.");
return 0;
}
high_bit =
- (chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
+ (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
do {
/* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a
* circID such that (high_bit|test_circ_id) is not already used. */
- test_circ_id = chan->u.cell_chan.next_circ_id++;
+ test_circ_id = chan->next_circ_id++;
if (test_circ_id == 0 || test_circ_id >= 1<<15) {
test_circ_id = 1;
- chan->u.cell_chan.next_circ_id = 2;
+ chan->next_circ_id = 2;
}
if (++attempts > 1<<15) {
/* Make sure we don't loop forever if all circ_id's are used. This
@@ -2039,11 +2038,9 @@ circuit_n_chan_done(channel_t *chan, int status)
int err_reason = 0;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
log_debug(LD_CIRC,"chan to %s/%s, status=%d",
- chan->u.cell_chan.nickname ?
- chan->u.cell_chan.nickname : "NULL",
+ chan->nickname ? chan->nickname : "NULL",
channel_get_canonical_remote_descr(chan), status);
pending_circs = smartlist_new();
@@ -2064,7 +2061,7 @@ circuit_n_chan_done(channel_t *chan, int status)
continue;
} else {
/* We expected a key. See if it's the right one. */
- if (tor_memneq(chan->u.cell_chan.identity_digest,
+ if (tor_memneq(chan->identity_digest,
circ->n_hop->identity_digest, DIGEST_LEN))
continue;
}
@@ -2247,8 +2244,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
else
control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0);
- tor_assert(!(circ->_base.n_chan->is_listener));
- node = node_get_by_id(circ->_base.n_chan->u.cell_chan.identity_digest);
+ node = node_get_by_id(circ->_base.n_chan->identity_digest);
fast = should_use_create_fast_for_circuit(circ);
if (!fast) {
/* We are an OR and we know the right onion key: we should
@@ -2487,10 +2483,8 @@ circuit_extend(cell_t *cell, circuit_t *circ)
/* Next, check if we're being asked to connect to the hop that the
* extend cell came from. There isn't any reason for that, and it can
* assist circular-path attacks. */
- tor_assert(!(TO_OR_CIRCUIT(circ)->p_chan->is_listener));
if (tor_memeq(id_digest,
- TO_OR_CIRCUIT(circ)->p_chan->
- u.cell_chan.identity_digest,
+ TO_OR_CIRCUIT(circ)->p_chan->identity_digest,
DIGEST_LEN)) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Client asked me to extend back to the previous hop.");
@@ -2733,9 +2727,8 @@ pathbias_count_first_hop(origin_circuit_t *circ)
if (!circ->has_opened) {
entry_guard_t *guard;
- tor_assert(!(circ->_base.n_chan->is_listener));
- guard = entry_guard_get_by_id_digest(
- circ->_base.n_chan->u.cell_chan.identity_digest);
+ guard =
+ entry_guard_get_by_id_digest(circ->_base.n_chan->identity_digest);
if (guard) {
if (circ->path_state == PATH_STATE_NEW_CIRC) {
circ->path_state = PATH_STATE_DID_FIRST_HOP;
@@ -2840,10 +2833,8 @@ pathbias_count_success(origin_circuit_t *circ)
/* Don't count cannibalized/reused circs for path bias */
if (!circ->has_opened) {
- tor_assert(!(circ->_base.n_chan->is_listener));
guard =
- entry_guard_get_by_id_digest(circ->_base.n_chan->
- u.cell_chan.identity_digest);
+ entry_guard_get_by_id_digest(circ->_base.n_chan->identity_digest);
if (guard) {
if (circ->path_state == PATH_STATE_DID_FIRST_HOP) {
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 68cd19e..cf6020d 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -102,8 +102,6 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
circid_t old_id, *circid_ptr;
int was_active, make_active;
- if (chan) tor_assert(!(chan->is_listener));
-
if (direction == CELL_DIRECTION_OUT) {
chan_ptr = &circ->n_chan;
circid_ptr = &circ->n_circ_id;
@@ -131,13 +129,12 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
}
if (old_chan) { /* we may need to remove it from the conn-circid map */
- tor_assert(!(old_chan->is_listener));
search.circ_id = old_id;
search.chan = old_chan;
found = HT_REMOVE(chan_circid_map, &chan_circid_map, &search);
if (found) {
tor_free(found);
- --old_chan->u.cell_chan.n_circuits;
+ --old_chan->n_circuits;
}
if (was_active && old_chan != chan)
make_circuit_inactive_on_chan(circ, old_chan);
@@ -167,7 +164,7 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
if (make_active && old_chan != chan)
make_circuit_active_on_chan(circ,chan);
- ++chan->u.cell_chan.n_circuits;
+ ++chan->n_circuits;
}
/** Set the p_conn field of a circuit <b>circ</b>, along
@@ -242,7 +239,6 @@ circuit_get_all_pending_on_channel(smartlist_t *out, channel_t *chan)
{
tor_assert(out);
tor_assert(chan);
- tor_assert(!(chan->is_listener));
if (!circuits_pending_chans)
return;
@@ -259,8 +255,8 @@ circuit_get_all_pending_on_channel(smartlist_t *out, channel_t *chan)
continue;
} else {
/* We expected a key. See if it's the right one. */
- if (tor_memneq(chan->u.cell_chan.identity_digest,
- circ->n_hop->identity_digest, DIGEST_LEN))
+ if (tor_memneq(chan->identity_digest,
+ circ->n_hop->identity_digest, DIGEST_LEN))
continue;
}
smartlist_add(out, circ);
@@ -276,14 +272,12 @@ circuit_count_pending_on_channel(channel_t *chan)
smartlist_t *sl = smartlist_new();
tor_assert(chan);
- tor_assert(!(chan->is_listener));
circuit_get_all_pending_on_channel(sl, chan);
cnt = smartlist_len(sl);
smartlist_free(sl);
log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs",
- chan->u.cell_chan.nickname ?
- chan->u.cell_chan.nickname : "NULL",
+ chan->nickname ? chan->nickname : "NULL",
channel_get_canonical_remote_descr(chan),
cnt);
return cnt;
@@ -839,7 +833,6 @@ circuit_dump_by_chan(channel_t *chan, int severity)
circuit_t *circ;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
for (circ = global_circuitlist; circ; circ = circ->next) {
circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
@@ -865,7 +858,7 @@ circuit_dump_by_chan(channel_t *chan, int severity)
if (!circ->n_chan && circ->n_hop &&
channel_matches_extend_info(chan, circ->n_hop) &&
- tor_memeq(chan->u.cell_chan.identity_digest,
+ tor_memeq(chan->identity_digest,
circ->n_hop->identity_digest, DIGEST_LEN)) {
circuit_dump_chan_details(severity, circ, chan,
(circ->state == CIRCUIT_STATE_OPEN &&
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index e4e1b8a..be79b30 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -1185,9 +1185,8 @@ circuit_build_failed(origin_circuit_t *circ)
int already_marked = 0;
if (circ->_base.n_chan) {
n_chan = circ->_base.n_chan;
- tor_assert(!(n_chan->is_listener));
- if (n_chan->u.cell_chan.is_bad_for_new_circs) {
+ if (n_chan->is_bad_for_new_circs) {
/* We only want to blame this router when a fresh healthy
* connection fails. So don't mark this router as newly failed,
* since maybe this was just an old circuit attempt that's
@@ -1201,7 +1200,7 @@ circuit_build_failed(origin_circuit_t *circ)
"Our circuit failed to get a response from the first hop "
"(%s). I'm going to try to rotate to a better connection.",
channel_get_canonical_remote_descr(n_chan));
- n_chan->u.cell_chan.is_bad_for_new_circs = 1;
+ n_chan->is_bad_for_new_circs = 1;
} else {
log_info(LD_OR,
"Our circuit died before the first hop with no connection");
diff --git a/src/or/command.c b/src/or/command.c
index 2fb70b5..e175e23 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -44,7 +44,7 @@ uint64_t stats_n_relay_cells_processed = 0;
uint64_t stats_n_destroy_cells_processed = 0;
/* Handle an incoming channel */
-static void command_handle_incoming_channel(channel_t *listener,
+static void command_handle_incoming_channel(channel_listener_t *listener,
channel_t *chan);
/* These are the main functions for processing cells */
@@ -190,7 +190,6 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
tor_assert(cell);
tor_assert(chan);
- tor_assert(!(chan->is_listener));
log_debug(LD_OR,
"Got a CREATE cell for circ_id %d on channel " U64_FORMAT
@@ -223,9 +222,9 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
* circ. */
id_is_high = cell->circ_id & (1<<15);
if ((id_is_high &&
- chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_HIGHER) ||
+ chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ||
(!id_is_high &&
- chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_LOWER)) {
+ chan->circ_id_type == CIRC_ID_TYPE_LOWER)) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received create cell with unexpected circ_id %d. Closing.",
cell->circ_id);
@@ -235,7 +234,7 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
}
if (circuit_id_in_use_on_channel(cell->circ_id, chan)) {
- const node_t *node = node_get_by_id(chan->u.cell_chan.identity_digest);
+ const node_t *node = node_get_by_id(chan->identity_digest);
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received CREATE cell (circID %d) for known circ. "
"Dropping (age %d).",
@@ -473,7 +472,7 @@ command_process_destroy_cell(cell_t *cell, channel_t *chan)
*/
static void
-command_handle_incoming_channel(channel_t *listener, channel_t *chan)
+command_handle_incoming_channel(channel_listener_t *listener, channel_t *chan)
{
tor_assert(listener);
tor_assert(chan);
@@ -500,11 +499,11 @@ command_setup_channel(channel_t *chan)
*/
void
-command_setup_listener(channel_t *listener)
+command_setup_listener(channel_listener_t *listener)
{
tor_assert(listener);
- tor_assert(listener->state == CHANNEL_STATE_LISTENING);
+ tor_assert(listener->state == CHANNEL_LISTENER_STATE_LISTENING);
- channel_set_listener_fn(listener, command_handle_incoming_channel);
+ channel_listener_set_listener_fn(listener, command_handle_incoming_channel);
}
diff --git a/src/or/command.h b/src/or/command.h
index eddce87..f9a0ef2 100644
--- a/src/or/command.h
+++ b/src/or/command.h
@@ -17,7 +17,7 @@
void command_process_cell(channel_t *chan, cell_t *cell);
void command_process_var_cell(channel_t *chan, var_cell_t *cell);
void command_setup_channel(channel_t *chan);
-void command_setup_listener(channel_t *chan);
+void command_setup_listener(channel_listener_t *chan_l);
extern uint64_t stats_n_padding_cells_processed;
extern uint64_t stats_n_create_cells_processed;
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 834f970..45f3a06 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -3070,11 +3070,10 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
return 0;
}
if (or_circ && or_circ->p_chan) {
- tor_assert(!(or_circ->p_chan->is_listener));
if (!options->AllowSingleHopExits &&
(or_circ->is_first_hop ||
(!connection_or_digest_is_known_relay(
- or_circ->p_chan->u.cell_chan.identity_digest) &&
+ or_circ->p_chan->identity_digest) &&
should_refuse_unknown_exits(options)))) {
/* Don't let clients use us as a single-hop proxy, unless the user
* has explicitly allowed that in the config. It attracts attackers
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index a3df775..bf69711 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -336,8 +336,7 @@ connection_or_get_num_circuits(or_connection_t *conn)
tor_assert(conn);
if (conn->chan) {
- tor_assert(!(TLS_CHAN_TO_BASE(conn->chan)->is_listener));
- return TLS_CHAN_TO_BASE(conn->chan)->u.cell_chan.n_circuits;
+ return TLS_CHAN_TO_BASE(conn->chan)->n_circuits;
} else return 0;
}
@@ -1001,8 +1000,6 @@ connection_or_notify_error(or_connection_t *conn,
/* Tell the controlling channel if we have one */
if (conn->chan) {
chan = TLS_CHAN_TO_BASE(conn->chan);
- /* This shouldn't ever happen in the listening state */
- tor_assert(chan->state != CHANNEL_STATE_LISTENING);
/* Don't transition if we're already in closing, closed or error */
if (!(chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED ||
@@ -1148,8 +1145,6 @@ connection_or_close_normally(or_connection_t *orconn, int flush)
else connection_mark_for_close(TO_CONN(orconn));
if (orconn->chan) {
chan = TLS_CHAN_TO_BASE(orconn->chan);
- /* This shouldn't ever happen in the listening state */
- tor_assert(chan->state != CHANNEL_STATE_LISTENING);
/* Don't transition if we're already in closing, closed or error */
if (!(chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED ||
@@ -1173,8 +1168,6 @@ connection_or_close_for_error(or_connection_t *orconn, int flush)
else connection_mark_for_close(TO_CONN(orconn));
if (orconn->chan) {
chan = TLS_CHAN_TO_BASE(orconn->chan);
- /* This shouldn't ever happen in the listening state */
- tor_assert(chan->state != CHANNEL_STATE_LISTENING);
/* Don't transition if we're already in closing, closed or error */
if (!(chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED ||
@@ -1195,7 +1188,8 @@ connection_or_close_for_error(or_connection_t *orconn, int flush)
int
connection_tls_start_handshake(or_connection_t *conn, int receiving)
{
- channel_t *chan_listener, *chan;
+ channel_listener_t *chan_listener;
+ channel_t *chan;
/* Incoming connections will need a new channel passed to the
* channel_tls_listener */
@@ -1208,7 +1202,7 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving)
command_setup_listener(chan_listener);
}
chan = channel_tls_handle_incoming(conn);
- channel_queue_incoming(chan_listener, chan);
+ channel_listener_queue_incoming(chan_listener, chan);
}
connection_or_change_state(conn, OR_CONN_STATE_TLS_HANDSHAKING);
diff --git a/src/or/main.c b/src/or/main.c
index 2a3e0e1..e0c89a9 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1539,6 +1539,7 @@ run_scheduled_events(time_t now)
/** 8c. Do channel cleanup just like for connections */
channel_run_cleanup();
+ channel_listener_run_cleanup();
/** 9. and if we're a server, check whether our DNS is telling stories to
* us. */
@@ -2172,6 +2173,7 @@ dumpstats(int severity)
} SMARTLIST_FOREACH_END(conn);
channel_dumpstats(severity);
+ channel_listener_dumpstats(severity);
log(severity, LD_NET,
"Cells processed: "U64_FORMAT" padding\n"
diff --git a/src/or/or.h b/src/or/or.h
index 4d2ab21..5987eef 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -883,6 +883,10 @@ typedef uint16_t streamid_t;
typedef struct channel_s channel_t;
+/* channel_listener_t typedef; struct channel_listener_s is in channel.h */
+
+typedef struct channel_listener_s channel_listener_t;
+
/* channel states for channel_t */
typedef enum {
@@ -892,21 +896,10 @@ typedef enum {
* Permitted transitions from:
* - CHANNEL_STATE_CLOSING
* Permitted transitions to:
- * - CHANNEL_STATE_LISTENING
* - CHANNEL_STATE_OPENING
*/
CHANNEL_STATE_CLOSED = 0,
/*
- * Listening state - channel is listening for incoming connections
- *
- * Permitted transitions from:
- * - CHANNEL_STATE_CLOSED
- * Permitted transitions to:
- * - CHANNEL_STATE_CLOSING
- * - CHANNEL_STATE_ERROR
- */
- CHANNEL_STATE_LISTENING,
- /*
* Opening state - channel is trying to connect
*
* Permitted transitions from:
@@ -957,7 +950,6 @@ typedef enum {
*
* Permitted transitions from:
* - CHANNEL_STATE_CLOSING
- * - CHANNEL_STATE_LISTENING
* - CHANNEL_STATE_MAINT
* - CHANNEL_STATE_OPENING
* - CHANNEL_STATE_OPEN
@@ -971,6 +963,55 @@ typedef enum {
CHANNEL_STATE_LAST
} channel_state_t;
+/* channel listener states for channel_listener_t */
+
+typedef enum {
+ /*
+ * Closed state - channel listener is inactive
+ *
+ * Permitted transitions from:
+ * - CHANNEL_LISTENER_STATE_CLOSING
+ * Permitted transitions to:
+ * - CHANNEL_LISTENER_STATE_LISTENING
+ */
+ CHANNEL_LISTENER_STATE_CLOSED = 0,
+ /*
+ * Listening state - channel listener is listening for incoming
+ * connections
+ *
+ * Permitted transitions from:
+ * - CHANNEL_LISTENER_STATE_CLOSED
+ * Permitted transitions to:
+ * - CHANNEL_LISTENER_STATE_CLOSING
+ * - CHANNEL_LISTENER_STATE_ERROR
+ */
+ CHANNEL_LISTENER_STATE_LISTENING,
+ /*
+ * Closing state - channel listener is shutting down
+ *
+ * Permitted transitions from:
+ * - CHANNEL_LISTENER_STATE_LISTENING
+ * Permitted transitions to:
+ * - CHANNEL_LISTENER_STATE_CLOSED,
+ * - CHANNEL_LISTENER_STATE_ERROR
+ */
+ CHANNEL_LISTENER_STATE_CLOSING,
+ /*
+ * Error state - channel listener has experienced a permanent error
+ *
+ * Permitted transitions from:
+ * - CHANNEL_STATE_CLOSING
+ * - CHANNEL_STATE_LISTENING
+ * Permitted transitions to:
+ * - None
+ */
+ CHANNEL_LISTENER_STATE_ERROR,
+ /*
+ * Placeholder for maximum state value
+ */
+ CHANNEL_LISTENER_STATE_LAST
+} channel_listener_state_t;
+
/* TLS channel stuff */
typedef struct channel_tls_s channel_tls_t;
diff --git a/src/or/relay.c b/src/or/relay.c
index 3850562..60f696c 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1096,8 +1096,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
* and linked. */
static uint64_t next_id = 0;
circ->dirreq_id = ++next_id;
- tor_assert(!(TO_OR_CIRCUIT(circ)->p_chan->is_listener));
- TO_OR_CIRCUIT(circ)->p_chan->u.cell_chan.dirreq_id = circ->dirreq_id;
+ TO_OR_CIRCUIT(circ)->p_chan->dirreq_id = circ->dirreq_id;
}
return connection_exit_begin_conn(cell, circ);
@@ -2179,23 +2178,22 @@ scale_active_circuits(channel_t *chan, unsigned cur_tick)
double factor;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
factor =
get_scale_factor(
- chan->u.cell_chan.active_circuit_pqueue_last_recalibrated,
+ chan->active_circuit_pqueue_last_recalibrated,
cur_tick);
/** Ordinarily it isn't okay to change the value of an element in a heap,
* but it's okay here, since we are preserving the order. */
SMARTLIST_FOREACH_BEGIN(
- chan->u.cell_chan.active_circuit_pqueue,
+ chan->active_circuit_pqueue,
cell_ewma_t *, e) {
tor_assert(e->last_adjusted_tick ==
- chan->u.cell_chan.active_circuit_pqueue_last_recalibrated);
+ chan->active_circuit_pqueue_last_recalibrated);
e->cell_count *= factor;
e->last_adjusted_tick = cur_tick;
} SMARTLIST_FOREACH_END(e);
- chan->u.cell_chan.active_circuit_pqueue_last_recalibrated = cur_tick;
+ chan->active_circuit_pqueue_last_recalibrated = cur_tick;
}
/** Rescale <b>ewma</b> to the same scale as <b>chan</b>, and add it to
@@ -2204,15 +2202,14 @@ static void
add_cell_ewma_to_chan(channel_t *chan, cell_ewma_t *ewma)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(ewma);
tor_assert(ewma->heap_index == -1);
scale_single_cell_ewma(
ewma,
- chan->u.cell_chan.active_circuit_pqueue_last_recalibrated);
+ chan->active_circuit_pqueue_last_recalibrated);
- smartlist_pqueue_add(chan->u.cell_chan.active_circuit_pqueue,
+ smartlist_pqueue_add(chan->active_circuit_pqueue,
compare_cell_ewma_counts,
STRUCT_OFFSET(cell_ewma_t, heap_index),
ewma);
@@ -2223,11 +2220,10 @@ static void
remove_cell_ewma_from_chan(channel_t *chan, cell_ewma_t *ewma)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(ewma);
tor_assert(ewma->heap_index != -1);
- smartlist_pqueue_remove(chan->u.cell_chan.active_circuit_pqueue,
+ smartlist_pqueue_remove(chan->active_circuit_pqueue,
compare_cell_ewma_counts,
STRUCT_OFFSET(cell_ewma_t, heap_index),
ewma);
@@ -2239,9 +2235,8 @@ static cell_ewma_t *
pop_first_cell_ewma_from_chan(channel_t *chan)
{
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- return smartlist_pqueue_pop(chan->u.cell_chan.active_circuit_pqueue,
+ return smartlist_pqueue_pop(chan->active_circuit_pqueue,
compare_cell_ewma_counts,
STRUCT_OFFSET(cell_ewma_t, heap_index));
}
@@ -2254,7 +2249,6 @@ make_circuit_active_on_chan(circuit_t *circ, channel_t *chan)
circuit_t **nextp = NULL, **prevp = NULL;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(circ);
nextp = next_circ_on_chan_p(circ, chan);
@@ -2267,11 +2261,11 @@ make_circuit_active_on_chan(circuit_t *circ, channel_t *chan)
assert_active_circuits_ok_paranoid(chan);
- if (!(chan->u.cell_chan.active_circuits)) {
- chan->u.cell_chan.active_circuits = circ;
+ if (!(chan->active_circuits)) {
+ chan->active_circuits = circ;
*prevp = *nextp = circ;
} else {
- circuit_t *head = chan->u.cell_chan.active_circuits;
+ circuit_t *head = chan->active_circuits;
circuit_t *old_tail = *prev_circ_on_chan_p(head, chan);
*next_circ_on_chan_p(old_tail, chan) = circ;
*nextp = head;
@@ -2299,7 +2293,6 @@ make_circuit_inactive_on_chan(circuit_t *circ, channel_t *chan)
circuit_t *next = NULL, *prev = NULL;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(circ);
nextp = next_circ_on_chan_p(circ, chan);
@@ -2319,12 +2312,12 @@ make_circuit_inactive_on_chan(circuit_t *circ, channel_t *chan)
tor_assert(*next_circ_on_chan_p(prev, chan) == circ);
if (next == circ) {
- chan->u.cell_chan.active_circuits = NULL;
+ chan->active_circuits = NULL;
} else {
*prev_circ_on_chan_p(next, chan) = prev;
*next_circ_on_chan_p(prev, chan) = next;
- if (chan->u.cell_chan.active_circuits == circ)
- chan->u.cell_chan.active_circuits = next;
+ if (chan->active_circuits == circ)
+ chan->active_circuits = next;
}
*prevp = *nextp = NULL;
@@ -2347,9 +2340,8 @@ channel_unlink_all_active_circs(channel_t *chan)
circuit_t *head = NULL, *cur = NULL;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- cur = head = chan->u.cell_chan.active_circuits;
+ cur = head = chan->active_circuits;
if (! head)
return;
do {
@@ -2358,12 +2350,12 @@ channel_unlink_all_active_circs(channel_t *chan)
*next_circ_on_chan_p(cur, chan) = NULL;
cur = next;
} while (cur != head);
- chan->u.cell_chan.active_circuits = NULL;
+ chan->active_circuits = NULL;
- SMARTLIST_FOREACH(chan->u.cell_chan.active_circuit_pqueue,
+ SMARTLIST_FOREACH(chan->active_circuit_pqueue,
cell_ewma_t *, e,
e->heap_index = -1);
- smartlist_clear(chan->u.cell_chan.active_circuit_pqueue);
+ smartlist_clear(chan->active_circuit_pqueue);
}
/** Block (if <b>block</b> is true) or unblock (if <b>block</b> is false)
@@ -2440,9 +2432,8 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
double ewma_increment = -1;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- circ = chan->u.cell_chan.active_circuits;
+ circ = chan->active_circuits;
if (!circ) return 0;
assert_active_circuits_ok_paranoid(chan);
@@ -2453,13 +2444,13 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
tor_gettimeofday_cached(&now_hires);
tick = cell_ewma_tick_from_timeval(&now_hires, &fractional_tick);
- if (tick != chan->u.cell_chan.active_circuit_pqueue_last_recalibrated) {
+ if (tick != chan->active_circuit_pqueue_last_recalibrated) {
scale_active_circuits(chan, tick);
}
ewma_increment = pow(ewma_scale_factor, -fractional_tick);
- cell_ewma = smartlist_get(chan->u.cell_chan.active_circuit_pqueue, 0);
+ cell_ewma = smartlist_get(chan->active_circuit_pqueue, 0);
circ = cell_ewma_to_circuit(cell_ewma);
}
@@ -2511,8 +2502,8 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
/* If we just flushed our queue and this circuit is used for a
* tunneled directory request, possibly advance its state. */
- if (queue->n == 0 && chan->u.cell_chan.dirreq_id)
- geoip_change_dirreq_state(chan->u.cell_chan.dirreq_id,
+ if (queue->n == 0 && chan->dirreq_id)
+ geoip_change_dirreq_state(chan->dirreq_id,
DIRREQ_TUNNELED,
DIRREQ_CIRC_QUEUE_FLUSHED);
@@ -2534,7 +2525,7 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
tor_assert(tmp == cell_ewma);
add_cell_ewma_to_chan(chan, cell_ewma);
}
- if (!ewma_enabled && circ != chan->u.cell_chan.active_circuits) {
+ if (!ewma_enabled && circ != chan->active_circuits) {
/* If this happens, the current circuit just got made inactive by
* a call in connection_write_to_buf(). That's nothing to worry about:
* circuit_make_inactive_on_conn() already advanced chan->active_circuits
@@ -2546,7 +2537,7 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
}
tor_assert(*next_circ_on_chan_p(circ, chan));
assert_active_circuits_ok_paranoid(chan);
- chan->u.cell_chan.active_circuits = *next_circ_on_chan_p(circ, chan);
+ chan->active_circuits = *next_circ_on_chan_p(circ, chan);
/* Is the cell queue low enough to unblock all the streams that are waiting
* to write to this circuit? */
@@ -2701,9 +2692,8 @@ assert_active_circuits_ok(channel_t *chan)
int n = 0;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
- cur = head = chan->u.cell_chan.active_circuits;
+ cur = head = chan->active_circuits;
if (! head)
return;
@@ -2723,13 +2713,13 @@ assert_active_circuits_ok(channel_t *chan)
tor_assert(ewma->is_for_p_chan);
}
tor_assert(ewma->heap_index != -1);
- tor_assert(ewma == smartlist_get(chan->u.cell_chan.active_circuit_pqueue,
+ tor_assert(ewma == smartlist_get(chan->active_circuit_pqueue,
ewma->heap_index));
n++;
cur = next;
} while (cur != head);
- tor_assert(n == smartlist_len(chan->u.cell_chan.active_circuit_pqueue));
+ tor_assert(n == smartlist_len(chan->active_circuit_pqueue));
}
/** Return 1 if we shouldn't restart reading on this circuit, even if
More information about the tor-commits
mailing list