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"
/* 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;
/* Registered handlers for incoming cells */
channel_cell_handler_fn_ptr cell_handler;
channel_var_cell_handler_fn_ptr var_cell_handler;
/* List of pending incoming connections */
smartlist_t *incoming_list;
/* Methods implemented by the lower layer */
/* Timestamps for listeners */
time_t timestamp_accepted;
/*
* 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 *);
/* 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;
/*
* 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;
/* Methods implemented by the lower layer */
/*
* Linked list of channels with the same identity digest, for the
* digest->channel map
*/
channel_t *next_with_same_id, *prev_with_same_id;
/*
* 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 *);
/* List of incoming cells to handle */
smartlist_t *incoming_queue;
/*
* 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;
/* List of queued outgoing cells */
smartlist_t *outgoing_queue;
/*
* Linked list of channels with the same identity digest, for the
* digest->channel map
*/
channel_t *next_with_same_id, *prev_with_same_id;
/* Circuit stuff for use by relay.c */
/* List of incoming cells to handle */
smartlist_t *incoming_queue;
/*
* 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;
/* List of queued outgoing cells */
smartlist_t *outgoing_queue;
/* Circuit ID generation stuff for use by circuitbuild.c */
/* Circuit stuff for use by relay.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;
/*
* 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;
/* How many circuits use this connection as p_chan or n_chan? */
int n_circuits;
/* Circuit ID generation stuff for use by circuitbuild.c */
/*
* 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;
/*
* 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;
/** 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;
/* How many circuits use this connection as p_chan or n_chan? */
int n_circuits;
/** Set if the channel was initiated remotely (came from a listener) */
unsigned int is_incoming:1;
/*
* 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;
/** 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;
/** 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;
/** 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 */
/** Set if the channel was initiated remotely (came from a listener) */
unsigned int is_incoming:1;
/* Timestamp for relay.c */
time_t timestamp_last_added_nonpadding;
/** 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;
/** 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 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 */
/** Channel counters for cell channels */
uint64_t n_cells_recved;
uint64_t n_cells_xmitted;
};
/* Timestamp for relay.c */
time_t timestamp_last_added_nonpadding;
struct channel_listener_s {
/* Current channel listener state */
channel_listener_state_t state;
/** 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;
/* Globally unique ID number for a channel over the lifetime of a Tor
* process.
*/
uint64_t global_identifier;
/** Channel counters for cell channels */
uint64_t n_cells_recved;
uint64_t n_cells_xmitted;
} cell_chan;
} u;
/* 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

View File

@ -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)";
tlschan = BASE_CHAN_TO_TLS(chan);
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));
rv = buf;
} else {
tlschan = BASE_CHAN_TO_TLS(chan);
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));
rv = buf;
} else {
rv = "TLS channel (no connection)";
}
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) \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,20 +896,9 @@ 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
*
@ -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;

View File

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