Split channel_t into channel_t and channel_listener_t; get rid of that big union

This commit is contained in:
Andrea Shepard 2012-10-09 00:51:33 -07:00
parent 6391f963fb
commit 3f4b95b1a3
14 changed files with 1771 additions and 1208 deletions

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
#include "or.h" #include "or.h"
/* Channel handler function pointer typedefs */ /* 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_cell_handler_fn_ptr)(channel_t *, cell_t *);
typedef void (*channel_var_cell_handler_fn_ptr)(channel_t *, var_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? */ /* Should we expect to see this channel in the channel lists? */
unsigned char registered:1; 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? /** Why did we close?
*/ */
enum { enum {
@ -67,21 +61,6 @@ struct channel_s {
/* Optional method to dump transport-specific statistics on the channel */ /* Optional method to dump transport-specific statistics on the channel */
void (*dumpstats)(channel_t *, int); 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 */ /* Registered handlers for incoming cells */
channel_cell_handler_fn_ptr cell_handler; channel_cell_handler_fn_ptr cell_handler;
channel_var_cell_handler_fn_ptr var_cell_handler; channel_var_cell_handler_fn_ptr var_cell_handler;
@ -223,15 +202,69 @@ struct channel_s {
/** Channel counters for cell channels */ /** Channel counters for cell channels */
uint64_t n_cells_recved; uint64_t n_cells_recved;
uint64_t n_cells_xmitted; uint64_t n_cells_xmitted;
} cell_chan; };
} u;
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 */ /* Channel state manipulations */
int channel_state_is_valid(channel_state_t state); 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_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_state_to_string(channel_state_t state);
const char *
channel_listener_state_to_string(channel_listener_state_t state);
/* Abstract channel operations */ /* Abstract channel operations */
@ -240,11 +273,15 @@ 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_packed_cell(channel_t *chan, packed_cell_t *cell);
void channel_write_var_cell(channel_t *chan, var_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 */ /* Channel callback registrations */
/* Listener callback */ /* Listener callback */
channel_listener_fn_ptr channel_get_listener_fn(channel_t *chan); channel_listener_fn_ptr
void channel_set_listener_fn(channel_t *chan, channel_listener_get_listener_fn(channel_listener_t *chan);
void channel_listener_set_listener_fn(channel_listener_t *chan,
channel_listener_fn_ptr listener); channel_listener_fn_ptr listener);
/* Incoming cell callbacks */ /* Incoming cell callbacks */
@ -258,16 +295,18 @@ void channel_set_cell_handlers(channel_t *chan,
channel_var_cell_handler_fn_ptr channel_var_cell_handler_fn_ptr
var_cell_handler); var_cell_handler);
/* Clean up closed channels periodically; called from run_scheduled_events() /* Clean up closed channels and channel listeners periodically; these are
* in main.c * called from run_scheduled_events() in main.c.
*/ */
void channel_run_cleanup(void); void channel_run_cleanup(void);
void channel_listener_run_cleanup(void);
/* Close all channels and deallocate everything */ /* Close all channels and deallocate everything */
void channel_free_all(void); void channel_free_all(void);
/* Dump some statistics in the log */ /* Dump some statistics in the log */
void channel_dumpstats(int severity); void channel_dumpstats(int severity);
void channel_listener_dumpstats(int severity);
#ifdef _TOR_CHANNEL_INTERNAL #ifdef _TOR_CHANNEL_INTERNAL
@ -277,20 +316,29 @@ void channel_dumpstats(int severity);
* constructors. * constructors.
*/ */
void channel_init_for_cells(channel_t *chan); void channel_init(channel_t *chan);
void channel_init_listener(channel_t *chan); void channel_init_listener(channel_listener_t *chan);
/* Channel registration/unregistration */ /* Channel registration/unregistration */
void channel_register(channel_t *chan); void channel_register(channel_t *chan);
void channel_unregister(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 */ /* Close from below */
void channel_close_from_lower_layer(channel_t *chan); void channel_close_from_lower_layer(channel_t *chan);
void channel_close_for_error(channel_t *chan); void channel_close_for_error(channel_t *chan);
void channel_closed(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 */ /* Free a channel */
void channel_free(channel_t *chan); void channel_free(channel_t *chan);
void channel_listener_free(channel_listener_t *chan_l);
/* State/metadata setters */ /* State/metadata setters */
@ -306,17 +354,24 @@ void channel_set_remote_end(channel_t *chan,
const char *identity_digest, const char *identity_digest,
const char *nickname); const char *nickname);
void channel_listener_change_state(channel_listener_t *chan_l,
channel_listener_state_t to_state);
/* Timestamp updates */ /* Timestamp updates */
void channel_timestamp_created(channel_t *chan); void channel_timestamp_created(channel_t *chan);
void channel_timestamp_accepted(channel_t *chan);
void channel_timestamp_active(channel_t *chan); void channel_timestamp_active(channel_t *chan);
void channel_timestamp_drained(channel_t *chan); void channel_timestamp_drained(channel_t *chan);
void channel_timestamp_recv(channel_t *chan); void channel_timestamp_recv(channel_t *chan);
void channel_timestamp_xmit(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 */ /* Incoming channel handling */
void channel_process_incoming(channel_t *listener); void channel_listener_process_incoming(channel_listener_t *listener);
void channel_queue_incoming(channel_t *listener, channel_t *incoming); void channel_listener_queue_incoming(channel_listener_t *listener,
channel_t *incoming);
/* Incoming cell handling */ /* Incoming cell handling */
void channel_process_cells(channel_t *chan); 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_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd);
void channel_timestamp_client(channel_t *chan); 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 */ /* Timestamp queries */
time_t channel_when_created(channel_t *chan); 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_active(channel_t *chan);
time_t channel_when_last_client(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_drained(channel_t *chan);
time_t channel_when_last_recv(channel_t *chan); time_t channel_when_last_recv(channel_t *chan);
time_t channel_when_last_xmit(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 */ /* Counter queries */
uint64_t channel_count_accepted(channel_t *chan);
uint64_t channel_count_recved(channel_t *chan); uint64_t channel_count_recved(channel_t *chan);
uint64_t channel_count_xmitted(channel_t *chan); uint64_t channel_count_xmitted(channel_t *chan);
uint64_t channel_listener_count_accepted(channel_listener_t *chan_l);
#endif #endif

View File

@ -42,7 +42,7 @@ uint64_t stats_n_authenticate_cells_processed = 0;
uint64_t stats_n_authorize_cells_processed = 0; uint64_t stats_n_authorize_cells_processed = 0;
/** Active listener, if any */ /** Active listener, if any */
channel_tls_t *channel_tls_listener = NULL; channel_listener_t *channel_tls_listener = NULL;
/* channel_tls_t method declarations */ /* 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, static int channel_tls_write_var_cell_method(channel_t *chan,
var_cell_t *var_cell); 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 /** Handle incoming cells for the handshake stuff here rather than
* passing them on up. */ * 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_tls_t *tlschan = tor_malloc_zero(sizeof(*tlschan));
channel_t *chan = TLS_CHAN_TO_BASE(tlschan); channel_t *chan = TLS_CHAN_TO_BASE(tlschan);
channel_init_for_cells(chan); channel_init(chan);
chan->state = CHANNEL_STATE_OPENING; chan->state = CHANNEL_STATE_OPENING;
chan->close = channel_tls_close_method; chan->close = channel_tls_close_method;
chan->describe_transport = channel_tls_describe_transport_method; chan->describe_transport = channel_tls_describe_transport_method;
chan->u.cell_chan.get_remote_addr = channel_tls_get_remote_addr_method; chan->get_remote_addr = channel_tls_get_remote_addr_method;
chan->u.cell_chan.get_remote_descr = channel_tls_get_remote_descr_method; chan->get_remote_descr = channel_tls_get_remote_descr_method;
chan->u.cell_chan.has_queued_writes = channel_tls_has_queued_writes_method; chan->has_queued_writes = channel_tls_has_queued_writes_method;
chan->u.cell_chan.is_canonical = channel_tls_is_canonical_method; chan->is_canonical = channel_tls_is_canonical_method;
chan->u.cell_chan.matches_extend_info = chan->matches_extend_info = channel_tls_matches_extend_info_method;
channel_tls_matches_extend_info_method; chan->matches_target = channel_tls_matches_target_method;
chan->u.cell_chan.matches_target = channel_tls_matches_target_method; chan->write_cell = channel_tls_write_cell_method;
chan->u.cell_chan.write_cell = channel_tls_write_cell_method; chan->write_packed_cell = channel_tls_write_packed_cell_method;
chan->u.cell_chan.write_packed_cell = channel_tls_write_packed_cell_method; chan->write_var_cell = channel_tls_write_var_cell_method;
chan->u.cell_chan.write_var_cell = channel_tls_write_var_cell_method;
log_debug(LD_CHANNEL, log_debug(LD_CHANNEL,
"In channel_tls_connect() for channel %p " "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); if (is_local_addr(addr)) channel_mark_local(chan);
channel_mark_outgoing(chan); channel_mark_outgoing(chan);
chan->u.cell_chan.active_circuit_pqueue = smartlist_new(); chan->active_circuit_pqueue = smartlist_new();
chan->u.cell_chan.active_circuit_pqueue_last_recalibrated = chan->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick();
cell_ewma_get_tick();
/* Set up or_connection stuff */ /* Set up or_connection stuff */
tlschan->conn = connection_or_connect(addr, port, id_digest, tlschan); 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; goto done;
err: err:
smartlist_free(chan->u.cell_chan.active_circuit_pqueue); smartlist_free(chan->active_circuit_pqueue);
tor_free(tlschan); tor_free(tlschan);
chan = NULL; chan = NULL;
@ -154,14 +158,14 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
/** /**
* Return the current channel_tls_t listener * 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 * NULL if none has been established
*/ */
channel_t * channel_listener_t *
channel_tls_get_listener(void) 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. * and return that.
*/ */
channel_t * channel_listener_t *
channel_tls_start_listener(void) channel_tls_start_listener(void)
{ {
channel_tls_t *listener; channel_listener_t *listener;
channel_t *lchan;
if (!channel_tls_listener) { if (!channel_tls_listener) {
listener = tor_malloc_zero(sizeof(*listener)); listener = tor_malloc_zero(sizeof(*listener));
lchan = TLS_CHAN_TO_BASE(listener); channel_init_listener(listener);
channel_init_listener(lchan); listener->state = CHANNEL_LISTENER_STATE_LISTENING;
lchan->state = CHANNEL_STATE_LISTENING; listener->close = channel_tls_listener_close_method;
lchan->close = channel_tls_close_method; listener->describe_transport =
lchan->describe_transport = channel_tls_describe_transport_method; channel_tls_listener_describe_transport_method;
channel_tls_listener = listener; channel_tls_listener = listener;
log_debug(LD_CHANNEL, log_debug(LD_CHANNEL,
"Starting TLS listener channel %p with global id " U64_FORMAT, "Starting TLS channel listener %p with global id " U64_FORMAT,
lchan, U64_PRINTF_ARG(lchan->global_identifier)); listener, U64_PRINTF_ARG(listener->global_identifier));
channel_register(lchan); channel_listener_register(listener);
} else lchan = TLS_CHAN_TO_BASE(channel_tls_listener); } else listener = channel_tls_listener;
return lchan; return listener;
} }
/** /**
@ -207,16 +210,13 @@ channel_tls_start_listener(void)
void void
channel_tls_free_all(void) channel_tls_free_all(void)
{ {
channel_t *base = NULL;
log_debug(LD_CHANNEL, log_debug(LD_CHANNEL,
"Shutting down TLS channels..."); "Shutting down TLS channels...");
if (channel_tls_listener) { if (channel_tls_listener) {
base = TLS_CHAN_TO_BASE(channel_tls_listener); channel_listener_unregister(channel_tls_listener);
channel_unregister(base); channel_listener_mark_for_close(channel_tls_listener);
channel_mark_for_close(base); channel_listener_free(channel_tls_listener);
channel_free(base);
channel_tls_listener = NULL; channel_tls_listener = NULL;
} }
@ -237,19 +237,18 @@ channel_tls_handle_incoming(or_connection_t *orconn)
tor_assert(orconn); tor_assert(orconn);
tor_assert(!(orconn->chan)); tor_assert(!(orconn->chan));
channel_init_for_cells(chan); channel_init(chan);
chan->state = CHANNEL_STATE_OPENING; chan->state = CHANNEL_STATE_OPENING;
chan->close = channel_tls_close_method; chan->close = channel_tls_close_method;
chan->describe_transport = channel_tls_describe_transport_method; chan->describe_transport = channel_tls_describe_transport_method;
chan->u.cell_chan.get_remote_descr = channel_tls_get_remote_descr_method; chan->get_remote_descr = channel_tls_get_remote_descr_method;
chan->u.cell_chan.has_queued_writes = channel_tls_has_queued_writes_method; chan->has_queued_writes = channel_tls_has_queued_writes_method;
chan->u.cell_chan.is_canonical = channel_tls_is_canonical_method; chan->is_canonical = channel_tls_is_canonical_method;
chan->u.cell_chan.matches_extend_info = chan->matches_extend_info = channel_tls_matches_extend_info_method;
channel_tls_matches_extend_info_method; chan->matches_target = channel_tls_matches_target_method;
chan->u.cell_chan.matches_target = channel_tls_matches_target_method; chan->write_cell = channel_tls_write_cell_method;
chan->u.cell_chan.write_cell = channel_tls_write_cell_method; chan->write_packed_cell = channel_tls_write_packed_cell_method;
chan->u.cell_chan.write_packed_cell = channel_tls_write_packed_cell_method; chan->write_var_cell = channel_tls_write_var_cell_method;
chan->u.cell_chan.write_var_cell = channel_tls_write_var_cell_method;
/* Link the channel and orconn to each other */ /* Link the channel and orconn to each other */
tlschan->conn = orconn; 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); if (is_local_addr(&(TO_CONN(orconn)->addr))) channel_mark_local(chan);
channel_mark_incoming(chan); channel_mark_incoming(chan);
chan->u.cell_chan.active_circuit_pqueue = smartlist_new(); chan->active_circuit_pqueue = smartlist_new();
chan->u.cell_chan.active_circuit_pqueue_last_recalibrated = chan->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick();
cell_ewma_get_tick();
/* If we got one, we should register it */ /* If we got one, we should register it */
if (chan) channel_register(chan); if (chan) channel_register(chan);
@ -285,35 +283,6 @@ channel_tls_close_method(channel_t *chan)
tor_assert(tlschan); 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); if (tlschan->conn) connection_or_close_normally(tlschan->conn, 1);
else { else {
/* Weird - we'll have to change the state ourselves, I guess */ /* Weird - we'll have to change the state ourselves, I guess */
@ -322,7 +291,6 @@ channel_tls_close_method(channel_t *chan)
tlschan); tlschan);
channel_change_state(chan, CHANNEL_STATE_ERROR); channel_change_state(chan, CHANNEL_STATE_ERROR);
} }
}
} }
/** /**
@ -342,9 +310,6 @@ channel_tls_describe_transport_method(channel_t *chan)
tor_assert(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) { if (tlschan->conn) {
@ -359,7 +324,6 @@ channel_tls_describe_transport_method(channel_t *chan)
} else { } else {
rv = "TLS channel (no connection)"; rv = "TLS channel (no connection)";
} }
}
return rv; return rv;
} }
@ -603,6 +567,65 @@ channel_tls_write_var_cell_method(channel_t *chan, var_cell_t *var_cell)
return 1; 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 * * 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; return;
} }
tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
handshaking = (TO_CONN(conn)->state != OR_CONN_STATE_OPEN); handshaking = (TO_CONN(conn)->state != OR_CONN_STATE_OPEN);
if (conn->_base.marked_for_close) 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; return;
} }
tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
handshaking = (TO_CONN(conn)->state != OR_CONN_STATE_OPEN); handshaking = (TO_CONN(conn)->state != OR_CONN_STATE_OPEN);
if (TO_CONN(conn)->marked_for_close) 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(cell);
tor_assert(chan); tor_assert(chan);
tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn); tor_assert(chan->conn);
started_here = connection_or_nonopen_was_started_here(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(cell);
tor_assert(chan); tor_assert(chan);
tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn); tor_assert(chan->conn);
started_here = connection_or_nonopen_was_started_here(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(cell);
tor_assert(chan); tor_assert(chan);
tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn); tor_assert(chan->conn);
if (chan->conn->link_proto < 2) { 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), safe_str_client(chan->conn->_base.address),
chan->conn->_base.port, chan->conn->_base.port,
(int)(chan->conn->link_proto), (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), DIGEST_LEN),
tor_addr_is_null(&my_apparent_addr) ? tor_addr_is_null(&my_apparent_addr) ?
"<none>" : fmt_and_decorate_addr(&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(cell);
tor_assert(chan); tor_assert(chan);
tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn); tor_assert(chan->conn);
#define ERR(s) \ #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 * _trying_ to connect to an authority, not necessarily if we _did_ connect
* to one. */ * to one. */
if (router_digest_is_trusted_dir( 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; severity = LOG_WARN;
else else
severity = LOG_PROTOCOL_WARN; 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(cell);
tor_assert(chan); tor_assert(chan);
tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn); tor_assert(chan->conn);
#define ERR(s) \ #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(cell);
tor_assert(chan); tor_assert(chan);
tor_assert(!(TLS_CHAN_TO_BASE(chan)->is_listener));
tor_assert(chan->conn); tor_assert(chan->conn);
#define ERR(s) \ #define ERR(s) \

View File

@ -28,8 +28,8 @@ struct channel_tls_s {
channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port, channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port,
const char *id_digest); const char *id_digest);
channel_t * channel_tls_get_listener(void); channel_listener_t * channel_tls_get_listener(void);
channel_t * channel_tls_start_listener(void); channel_listener_t * channel_tls_start_listener(void);
channel_t * channel_tls_handle_incoming(or_connection_t *orconn); channel_t * channel_tls_handle_incoming(or_connection_t *orconn);
/* Things for connection_or.c to call back into */ /* Things for connection_or.c to call back into */

View File

@ -1711,23 +1711,22 @@ get_unique_circ_id_by_chan(channel_t *chan)
circid_t high_bit; circid_t high_bit;
tor_assert(chan); 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, log_warn(LD_BUG,
"Trying to pick a circuit ID for a connection from " "Trying to pick a circuit ID for a connection from "
"a client with no identity."); "a client with no identity.");
return 0; return 0;
} }
high_bit = 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 { do {
/* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a /* 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. */ * 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) { if (test_circ_id == 0 || test_circ_id >= 1<<15) {
test_circ_id = 1; test_circ_id = 1;
chan->u.cell_chan.next_circ_id = 2; chan->next_circ_id = 2;
} }
if (++attempts > 1<<15) { if (++attempts > 1<<15) {
/* Make sure we don't loop forever if all circ_id's are used. This /* 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; int err_reason = 0;
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
log_debug(LD_CIRC,"chan to %s/%s, status=%d", log_debug(LD_CIRC,"chan to %s/%s, status=%d",
chan->u.cell_chan.nickname ? chan->nickname ? chan->nickname : "NULL",
chan->u.cell_chan.nickname : "NULL",
channel_get_canonical_remote_descr(chan), status); channel_get_canonical_remote_descr(chan), status);
pending_circs = smartlist_new(); pending_circs = smartlist_new();
@ -2064,7 +2061,7 @@ circuit_n_chan_done(channel_t *chan, int status)
continue; continue;
} else { } else {
/* We expected a key. See if it's the right one. */ /* 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)) circ->n_hop->identity_digest, DIGEST_LEN))
continue; continue;
} }
@ -2247,8 +2244,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
else else
control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0); 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->identity_digest);
node = node_get_by_id(circ->_base.n_chan->u.cell_chan.identity_digest);
fast = should_use_create_fast_for_circuit(circ); fast = should_use_create_fast_for_circuit(circ);
if (!fast) { if (!fast) {
/* We are an OR and we know the right onion key: we should /* 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 /* 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 * extend cell came from. There isn't any reason for that, and it can
* assist circular-path attacks. */ * assist circular-path attacks. */
tor_assert(!(TO_OR_CIRCUIT(circ)->p_chan->is_listener));
if (tor_memeq(id_digest, if (tor_memeq(id_digest,
TO_OR_CIRCUIT(circ)->p_chan-> TO_OR_CIRCUIT(circ)->p_chan->identity_digest,
u.cell_chan.identity_digest,
DIGEST_LEN)) { DIGEST_LEN)) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Client asked me to extend back to the previous hop."); "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) { if (!circ->has_opened) {
entry_guard_t *guard; entry_guard_t *guard;
tor_assert(!(circ->_base.n_chan->is_listener)); guard =
guard = entry_guard_get_by_id_digest( entry_guard_get_by_id_digest(circ->_base.n_chan->identity_digest);
circ->_base.n_chan->u.cell_chan.identity_digest);
if (guard) { if (guard) {
if (circ->path_state == PATH_STATE_NEW_CIRC) { if (circ->path_state == PATH_STATE_NEW_CIRC) {
circ->path_state = PATH_STATE_DID_FIRST_HOP; 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 */ /* Don't count cannibalized/reused circs for path bias */
if (!circ->has_opened) { if (!circ->has_opened) {
tor_assert(!(circ->_base.n_chan->is_listener));
guard = guard =
entry_guard_get_by_id_digest(circ->_base.n_chan-> entry_guard_get_by_id_digest(circ->_base.n_chan->identity_digest);
u.cell_chan.identity_digest);
if (guard) { if (guard) {
if (circ->path_state == PATH_STATE_DID_FIRST_HOP) { if (circ->path_state == PATH_STATE_DID_FIRST_HOP) {

View File

@ -102,8 +102,6 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
circid_t old_id, *circid_ptr; circid_t old_id, *circid_ptr;
int was_active, make_active; int was_active, make_active;
if (chan) tor_assert(!(chan->is_listener));
if (direction == CELL_DIRECTION_OUT) { if (direction == CELL_DIRECTION_OUT) {
chan_ptr = &circ->n_chan; chan_ptr = &circ->n_chan;
circid_ptr = &circ->n_circ_id; 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 */ 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.circ_id = old_id;
search.chan = old_chan; search.chan = old_chan;
found = HT_REMOVE(chan_circid_map, &chan_circid_map, &search); found = HT_REMOVE(chan_circid_map, &chan_circid_map, &search);
if (found) { if (found) {
tor_free(found); tor_free(found);
--old_chan->u.cell_chan.n_circuits; --old_chan->n_circuits;
} }
if (was_active && old_chan != chan) if (was_active && old_chan != chan)
make_circuit_inactive_on_chan(circ, old_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) if (make_active && old_chan != chan)
make_circuit_active_on_chan(circ,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 /** 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(out);
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
if (!circuits_pending_chans) if (!circuits_pending_chans)
return; return;
@ -259,7 +255,7 @@ circuit_get_all_pending_on_channel(smartlist_t *out, channel_t *chan)
continue; continue;
} else { } else {
/* We expected a key. See if it's the right one. */ /* 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)) circ->n_hop->identity_digest, DIGEST_LEN))
continue; continue;
} }
@ -276,14 +272,12 @@ circuit_count_pending_on_channel(channel_t *chan)
smartlist_t *sl = smartlist_new(); smartlist_t *sl = smartlist_new();
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
circuit_get_all_pending_on_channel(sl, chan); circuit_get_all_pending_on_channel(sl, chan);
cnt = smartlist_len(sl); cnt = smartlist_len(sl);
smartlist_free(sl); smartlist_free(sl);
log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs", log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs",
chan->u.cell_chan.nickname ? chan->nickname ? chan->nickname : "NULL",
chan->u.cell_chan.nickname : "NULL",
channel_get_canonical_remote_descr(chan), channel_get_canonical_remote_descr(chan),
cnt); cnt);
return cnt; return cnt;
@ -839,7 +833,6 @@ circuit_dump_by_chan(channel_t *chan, int severity)
circuit_t *circ; circuit_t *circ;
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
for (circ = global_circuitlist; circ; circ = circ->next) { for (circ = global_circuitlist; circ; circ = circ->next) {
circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0; 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 && if (!circ->n_chan && circ->n_hop &&
channel_matches_extend_info(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)) { circ->n_hop->identity_digest, DIGEST_LEN)) {
circuit_dump_chan_details(severity, circ, chan, circuit_dump_chan_details(severity, circ, chan,
(circ->state == CIRCUIT_STATE_OPEN && (circ->state == CIRCUIT_STATE_OPEN &&

View File

@ -1185,9 +1185,8 @@ circuit_build_failed(origin_circuit_t *circ)
int already_marked = 0; int already_marked = 0;
if (circ->_base.n_chan) { if (circ->_base.n_chan) {
n_chan = 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 /* We only want to blame this router when a fresh healthy
* connection fails. So don't mark this router as newly failed, * connection fails. So don't mark this router as newly failed,
* since maybe this was just an old circuit attempt that's * 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 " "Our circuit failed to get a response from the first hop "
"(%s). I'm going to try to rotate to a better connection.", "(%s). I'm going to try to rotate to a better connection.",
channel_get_canonical_remote_descr(n_chan)); 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 { } else {
log_info(LD_OR, log_info(LD_OR,
"Our circuit died before the first hop with no connection"); "Our circuit died before the first hop with no connection");

View File

@ -44,7 +44,7 @@ uint64_t stats_n_relay_cells_processed = 0;
uint64_t stats_n_destroy_cells_processed = 0; uint64_t stats_n_destroy_cells_processed = 0;
/* Handle an incoming channel */ /* 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); channel_t *chan);
/* These are the main functions for processing cells */ /* 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(cell);
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
log_debug(LD_OR, log_debug(LD_OR,
"Got a CREATE cell for circ_id %d on channel " U64_FORMAT "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. */ * circ. */
id_is_high = cell->circ_id & (1<<15); id_is_high = cell->circ_id & (1<<15);
if ((id_is_high && 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 && (!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, log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received create cell with unexpected circ_id %d. Closing.", "Received create cell with unexpected circ_id %d. Closing.",
cell->circ_id); 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)) { 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, log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received CREATE cell (circID %d) for known circ. " "Received CREATE cell (circID %d) for known circ. "
"Dropping (age %d).", "Dropping (age %d).",
@ -473,7 +472,7 @@ command_process_destroy_cell(cell_t *cell, channel_t *chan)
*/ */
static void 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(listener);
tor_assert(chan); tor_assert(chan);
@ -500,11 +499,11 @@ command_setup_channel(channel_t *chan)
*/ */
void void
command_setup_listener(channel_t *listener) command_setup_listener(channel_listener_t *listener)
{ {
tor_assert(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);
} }

View File

@ -17,7 +17,7 @@
void command_process_cell(channel_t *chan, cell_t *cell); void command_process_cell(channel_t *chan, cell_t *cell);
void command_process_var_cell(channel_t *chan, var_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_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_padding_cells_processed;
extern uint64_t stats_n_create_cells_processed; extern uint64_t stats_n_create_cells_processed;

View File

@ -3070,11 +3070,10 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
return 0; return 0;
} }
if (or_circ && or_circ->p_chan) { if (or_circ && or_circ->p_chan) {
tor_assert(!(or_circ->p_chan->is_listener));
if (!options->AllowSingleHopExits && if (!options->AllowSingleHopExits &&
(or_circ->is_first_hop || (or_circ->is_first_hop ||
(!connection_or_digest_is_known_relay( (!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)))) { should_refuse_unknown_exits(options)))) {
/* Don't let clients use us as a single-hop proxy, unless the user /* Don't let clients use us as a single-hop proxy, unless the user
* has explicitly allowed that in the config. It attracts attackers * has explicitly allowed that in the config. It attracts attackers

View File

@ -336,8 +336,7 @@ connection_or_get_num_circuits(or_connection_t *conn)
tor_assert(conn); tor_assert(conn);
if (conn->chan) { if (conn->chan) {
tor_assert(!(TLS_CHAN_TO_BASE(conn->chan)->is_listener)); return TLS_CHAN_TO_BASE(conn->chan)->n_circuits;
return TLS_CHAN_TO_BASE(conn->chan)->u.cell_chan.n_circuits;
} else return 0; } else return 0;
} }
@ -1001,8 +1000,6 @@ connection_or_notify_error(or_connection_t *conn,
/* Tell the controlling channel if we have one */ /* Tell the controlling channel if we have one */
if (conn->chan) { if (conn->chan) {
chan = TLS_CHAN_TO_BASE(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 */ /* Don't transition if we're already in closing, closed or error */
if (!(chan->state == CHANNEL_STATE_CLOSING || if (!(chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED || 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)); else connection_mark_for_close(TO_CONN(orconn));
if (orconn->chan) { if (orconn->chan) {
chan = TLS_CHAN_TO_BASE(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 */ /* Don't transition if we're already in closing, closed or error */
if (!(chan->state == CHANNEL_STATE_CLOSING || if (!(chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED || 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)); else connection_mark_for_close(TO_CONN(orconn));
if (orconn->chan) { if (orconn->chan) {
chan = TLS_CHAN_TO_BASE(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 */ /* Don't transition if we're already in closing, closed or error */
if (!(chan->state == CHANNEL_STATE_CLOSING || if (!(chan->state == CHANNEL_STATE_CLOSING ||
chan->state == CHANNEL_STATE_CLOSED || chan->state == CHANNEL_STATE_CLOSED ||
@ -1195,7 +1188,8 @@ connection_or_close_for_error(or_connection_t *orconn, int flush)
int int
connection_tls_start_handshake(or_connection_t *conn, int receiving) 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 /* Incoming connections will need a new channel passed to the
* channel_tls_listener */ * channel_tls_listener */
@ -1208,7 +1202,7 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving)
command_setup_listener(chan_listener); command_setup_listener(chan_listener);
} }
chan = channel_tls_handle_incoming(conn); 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); connection_or_change_state(conn, OR_CONN_STATE_TLS_HANDSHAKING);

View File

@ -1539,6 +1539,7 @@ run_scheduled_events(time_t now)
/** 8c. Do channel cleanup just like for connections */ /** 8c. Do channel cleanup just like for connections */
channel_run_cleanup(); channel_run_cleanup();
channel_listener_run_cleanup();
/** 9. and if we're a server, check whether our DNS is telling stories to /** 9. and if we're a server, check whether our DNS is telling stories to
* us. */ * us. */
@ -2172,6 +2173,7 @@ dumpstats(int severity)
} SMARTLIST_FOREACH_END(conn); } SMARTLIST_FOREACH_END(conn);
channel_dumpstats(severity); channel_dumpstats(severity);
channel_listener_dumpstats(severity);
log(severity, LD_NET, log(severity, LD_NET,
"Cells processed: "U64_FORMAT" padding\n" "Cells processed: "U64_FORMAT" padding\n"

View File

@ -883,6 +883,10 @@ typedef uint16_t streamid_t;
typedef struct channel_s channel_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 */ /* channel states for channel_t */
typedef enum { typedef enum {
@ -892,20 +896,9 @@ typedef enum {
* Permitted transitions from: * Permitted transitions from:
* - CHANNEL_STATE_CLOSING * - CHANNEL_STATE_CLOSING
* Permitted transitions to: * Permitted transitions to:
* - CHANNEL_STATE_LISTENING
* - CHANNEL_STATE_OPENING * - CHANNEL_STATE_OPENING
*/ */
CHANNEL_STATE_CLOSED = 0, 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 * Opening state - channel is trying to connect
* *
@ -957,7 +950,6 @@ typedef enum {
* *
* Permitted transitions from: * Permitted transitions from:
* - CHANNEL_STATE_CLOSING * - CHANNEL_STATE_CLOSING
* - CHANNEL_STATE_LISTENING
* - CHANNEL_STATE_MAINT * - CHANNEL_STATE_MAINT
* - CHANNEL_STATE_OPENING * - CHANNEL_STATE_OPENING
* - CHANNEL_STATE_OPEN * - CHANNEL_STATE_OPEN
@ -971,6 +963,55 @@ typedef enum {
CHANNEL_STATE_LAST CHANNEL_STATE_LAST
} channel_state_t; } 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 */ /* TLS channel stuff */
typedef struct channel_tls_s channel_tls_t; typedef struct channel_tls_s channel_tls_t;

View File

@ -1096,8 +1096,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
* and linked. */ * and linked. */
static uint64_t next_id = 0; static uint64_t next_id = 0;
circ->dirreq_id = ++next_id; circ->dirreq_id = ++next_id;
tor_assert(!(TO_OR_CIRCUIT(circ)->p_chan->is_listener)); TO_OR_CIRCUIT(circ)->p_chan->dirreq_id = circ->dirreq_id;
TO_OR_CIRCUIT(circ)->p_chan->u.cell_chan.dirreq_id = circ->dirreq_id;
} }
return connection_exit_begin_conn(cell, circ); return connection_exit_begin_conn(cell, circ);
@ -2179,23 +2178,22 @@ scale_active_circuits(channel_t *chan, unsigned cur_tick)
double factor; double factor;
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
factor = factor =
get_scale_factor( get_scale_factor(
chan->u.cell_chan.active_circuit_pqueue_last_recalibrated, chan->active_circuit_pqueue_last_recalibrated,
cur_tick); cur_tick);
/** Ordinarily it isn't okay to change the value of an element in a heap, /** 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. */ * but it's okay here, since we are preserving the order. */
SMARTLIST_FOREACH_BEGIN( SMARTLIST_FOREACH_BEGIN(
chan->u.cell_chan.active_circuit_pqueue, chan->active_circuit_pqueue,
cell_ewma_t *, e) { cell_ewma_t *, e) {
tor_assert(e->last_adjusted_tick == 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->cell_count *= factor;
e->last_adjusted_tick = cur_tick; e->last_adjusted_tick = cur_tick;
} SMARTLIST_FOREACH_END(e); } 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 /** 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) add_cell_ewma_to_chan(channel_t *chan, cell_ewma_t *ewma)
{ {
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
tor_assert(ewma); tor_assert(ewma);
tor_assert(ewma->heap_index == -1); tor_assert(ewma->heap_index == -1);
scale_single_cell_ewma( scale_single_cell_ewma(
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, compare_cell_ewma_counts,
STRUCT_OFFSET(cell_ewma_t, heap_index), STRUCT_OFFSET(cell_ewma_t, heap_index),
ewma); ewma);
@ -2223,11 +2220,10 @@ static void
remove_cell_ewma_from_chan(channel_t *chan, cell_ewma_t *ewma) remove_cell_ewma_from_chan(channel_t *chan, cell_ewma_t *ewma)
{ {
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
tor_assert(ewma); tor_assert(ewma);
tor_assert(ewma->heap_index != -1); 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, compare_cell_ewma_counts,
STRUCT_OFFSET(cell_ewma_t, heap_index), STRUCT_OFFSET(cell_ewma_t, heap_index),
ewma); ewma);
@ -2239,9 +2235,8 @@ static cell_ewma_t *
pop_first_cell_ewma_from_chan(channel_t *chan) pop_first_cell_ewma_from_chan(channel_t *chan)
{ {
tor_assert(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, compare_cell_ewma_counts,
STRUCT_OFFSET(cell_ewma_t, heap_index)); 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; circuit_t **nextp = NULL, **prevp = NULL;
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
tor_assert(circ); tor_assert(circ);
nextp = next_circ_on_chan_p(circ, chan); 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); assert_active_circuits_ok_paranoid(chan);
if (!(chan->u.cell_chan.active_circuits)) { if (!(chan->active_circuits)) {
chan->u.cell_chan.active_circuits = circ; chan->active_circuits = circ;
*prevp = *nextp = circ; *prevp = *nextp = circ;
} else { } 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); circuit_t *old_tail = *prev_circ_on_chan_p(head, chan);
*next_circ_on_chan_p(old_tail, chan) = circ; *next_circ_on_chan_p(old_tail, chan) = circ;
*nextp = head; *nextp = head;
@ -2299,7 +2293,6 @@ make_circuit_inactive_on_chan(circuit_t *circ, channel_t *chan)
circuit_t *next = NULL, *prev = NULL; circuit_t *next = NULL, *prev = NULL;
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
tor_assert(circ); tor_assert(circ);
nextp = next_circ_on_chan_p(circ, chan); 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); tor_assert(*next_circ_on_chan_p(prev, chan) == circ);
if (next == circ) { if (next == circ) {
chan->u.cell_chan.active_circuits = NULL; chan->active_circuits = NULL;
} else { } else {
*prev_circ_on_chan_p(next, chan) = prev; *prev_circ_on_chan_p(next, chan) = prev;
*next_circ_on_chan_p(prev, chan) = next; *next_circ_on_chan_p(prev, chan) = next;
if (chan->u.cell_chan.active_circuits == circ) if (chan->active_circuits == circ)
chan->u.cell_chan.active_circuits = next; chan->active_circuits = next;
} }
*prevp = *nextp = NULL; *prevp = *nextp = NULL;
@ -2347,9 +2340,8 @@ channel_unlink_all_active_circs(channel_t *chan)
circuit_t *head = NULL, *cur = NULL; circuit_t *head = NULL, *cur = NULL;
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
cur = head = chan->u.cell_chan.active_circuits; cur = head = chan->active_circuits;
if (! head) if (! head)
return; return;
do { do {
@ -2358,12 +2350,12 @@ channel_unlink_all_active_circs(channel_t *chan)
*next_circ_on_chan_p(cur, chan) = NULL; *next_circ_on_chan_p(cur, chan) = NULL;
cur = next; cur = next;
} while (cur != head); } 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, cell_ewma_t *, e,
e->heap_index = -1); 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) /** 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; double ewma_increment = -1;
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
circ = chan->u.cell_chan.active_circuits; circ = chan->active_circuits;
if (!circ) return 0; if (!circ) return 0;
assert_active_circuits_ok_paranoid(chan); 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); tor_gettimeofday_cached(&now_hires);
tick = cell_ewma_tick_from_timeval(&now_hires, &fractional_tick); 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); scale_active_circuits(chan, tick);
} }
ewma_increment = pow(ewma_scale_factor, -fractional_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); 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 /* If we just flushed our queue and this circuit is used for a
* tunneled directory request, possibly advance its state. */ * tunneled directory request, possibly advance its state. */
if (queue->n == 0 && chan->u.cell_chan.dirreq_id) if (queue->n == 0 && chan->dirreq_id)
geoip_change_dirreq_state(chan->u.cell_chan.dirreq_id, geoip_change_dirreq_state(chan->dirreq_id,
DIRREQ_TUNNELED, DIRREQ_TUNNELED,
DIRREQ_CIRC_QUEUE_FLUSHED); DIRREQ_CIRC_QUEUE_FLUSHED);
@ -2534,7 +2525,7 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
tor_assert(tmp == cell_ewma); tor_assert(tmp == cell_ewma);
add_cell_ewma_to_chan(chan, 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 /* If this happens, the current circuit just got made inactive by
* a call in connection_write_to_buf(). That's nothing to worry about: * a call in connection_write_to_buf(). That's nothing to worry about:
* circuit_make_inactive_on_conn() already advanced chan->active_circuits * 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)); tor_assert(*next_circ_on_chan_p(circ, chan));
assert_active_circuits_ok_paranoid(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 /* Is the cell queue low enough to unblock all the streams that are waiting
* to write to this circuit? */ * to write to this circuit? */
@ -2701,9 +2692,8 @@ assert_active_circuits_ok(channel_t *chan)
int n = 0; int n = 0;
tor_assert(chan); tor_assert(chan);
tor_assert(!(chan->is_listener));
cur = head = chan->u.cell_chan.active_circuits; cur = head = chan->active_circuits;
if (! head) if (! head)
return; return;
@ -2723,13 +2713,13 @@ assert_active_circuits_ok(channel_t *chan)
tor_assert(ewma->is_for_p_chan); tor_assert(ewma->is_for_p_chan);
} }
tor_assert(ewma->heap_index != -1); 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)); ewma->heap_index));
n++; n++;
cur = next; cur = next;
} while (cur != head); } 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 /** Return 1 if we shouldn't restart reading on this circuit, even if