tor-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
October 2012
- 20 participants
- 1288 discussions
commit 6391f963fb1ff9988d048397cd054b65ff5a52ff
Author: Andrea Shepard <andrea(a)torproject.org>
Date: Mon Oct 8 21:30:07 2012 -0700
Conform to existing Doxygen style
---
src/or/channel.c | 265 +++-----------------------------------------------
src/or/channeltls.c | 98 +------------------
2 files changed, 18 insertions(+), 345 deletions(-)
diff --git a/src/or/channel.c b/src/or/channel.c
index fac4017..57b9e4f 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -97,9 +97,6 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q);
/**
* Indicate whether a given channel state is valid
- *
- * @param state A channel state
- * @return A boolean value indicating whether state is a valid channel state
*/
int
@@ -131,10 +128,6 @@ channel_state_is_valid(channel_state_t state)
* This function takes two channel states and indicates whether a
* transition between them is permitted (see the state definitions and
* transition table in or.h at the channel_state_t typedef).
- *
- * @param from Proposed state to transition from
- * @param to Proposed state to transition to
- * @return A boolean value indicating whether the posposed transition is valid
*/
int
@@ -183,9 +176,6 @@ channel_state_can_transition(channel_state_t from, channel_state_t to)
/**
* Return a human-readable description for a channel state
- *
- * @param state A channel state
- * @return A pointer to a string with a human-readable description of state
*/
const char *
@@ -232,8 +222,6 @@ channel_state_to_string(channel_state_t state)
*
* This function registers a newly created channel in the global lists/maps
* of active channels.
- *
- * @param chan A pointer to an unregistered channel
*/
void
@@ -306,8 +294,6 @@ channel_register(channel_t *chan)
*
* This function removes a channel from the global lists and maps and is used
* when freeing a closed/errored channel.
- *
- * @param chan A pointer to a channel to be unregistered
*/
void
@@ -363,8 +349,6 @@ channel_unregister(channel_t *chan)
* This function adds a channel to the digest map and inserts it into the
* correct linked list if channels with that remote endpoint identity digest
* already exist.
- *
- * @param chan A pointer to a channel to add
*/
static void
@@ -416,8 +400,6 @@ channel_add_to_digest_map(channel_t *chan)
*
* This function removes a channel from the digest map and the linked list of
* channels for that digest if more than one exists.
- *
- * @param chan A pointer to a channel to remove
*/
static void
@@ -563,10 +545,6 @@ channel_remove_from_digest_map(channel_t *chan)
* This function searches for a channel by the global_identifier assigned
* at initialization time. This identifier is unique for the lifetime of the
* Tor process.
- *
- * @param global_identifier The global_identifier value to search for
- * @return A pointer to the channel with that global identifier, or NULL if
- * none exists.
*/
channel_t *
@@ -593,9 +571,6 @@ channel_find_by_global_id(uint64_t global_identifier)
* the channel digest map. It's possible that more than one channel to a
* given endpoint exists. Use channel_next_with_digest() and
* channel_prev_with_digest() to walk the list.
- *
- * @param identity_digest A digest to search for
- * @return A channel pointer, or NULL if no channel to this endpoint exists.
*/
channel_t *
@@ -614,14 +589,10 @@ channel_find_by_remote_digest(const char *identity_digest)
}
/**
- * Next channel with digest
+ * Get next channel with digest
*
* This function takes a channel and finds the next channel in the list
* with the same digest.
- *
- * @param chan Channel pointer to iterate
- * @return A pointer to the next channel after chan with the same remote
- * endpoint identity digest, or NULL if none exists.
*/
channel_t *
@@ -634,14 +605,10 @@ channel_next_with_digest(channel_t *chan)
}
/**
- * Previous channel with digest
+ * Get previous channel with digest
*
* This function takes a channel and finds the previos channel in the list
* with the same digest.
- *
- * @param chan Channel pointer to iterate
- * @return A pointer to the previous channel after chan with the same remote
- * endpoint identity digest, or NULL if none exists.
*/
channel_t *
@@ -659,13 +626,11 @@ channel_prev_with_digest(channel_t *chan)
}
/**
- * Internal-only channel init function for cell channels
+ * Initialize a cell channel
*
* This function should be called by subclasses to set up some per-channel
* variables. I.e., this is the superclass constructor. Before this, the
* channel should be allocated with tor_malloc_zero().
- *
- * @param chan Pointer to a channel to initialize.
*/
void
@@ -690,13 +655,11 @@ channel_init_for_cells(channel_t *chan)
}
/**
- * Internal-only channel init function for listener channels
+ * Initialize a listener channel
*
* This function should be called by subclasses to set up some per-channel
* variables. I.e., this is the superclass constructor. Before this, the
* channel should be allocated with tor_malloc_zero().
- *
- * @param chan Pointer to a channel to initialize.
*/
void
@@ -715,12 +678,8 @@ channel_init_listener(channel_t *chan)
}
/**
- * Internal-only channel free function
- *
- * Nothing outside of channel.c should call this; it frees channels after
- * they have closed and been unregistered.
- *
- * @param chan Channel to free
+ * Free a channel; nothing outside of channel.c and subclasses should call
+ * this - it frees channels after they have closed and been unregistered.
*/
void
@@ -752,10 +711,9 @@ channel_free(channel_t *chan)
}
/**
- * Internal-only forcible channel free function
- *
- * This is like channel_free, but doesn't do the state/registration asserts;
- * it should only be used from channel_free_all() when shutting down.
+ * Free a channel and skip the state/reigstration asserts; this internal-
+ * use-only function should be called only from channel_free_all() when
+ * shutting down the Tor process.
*/
static void
@@ -821,9 +779,6 @@ channel_force_free(channel_t *chan)
*
* This function returns a function pointer to the current registered
* handler for new incoming channels on a listener channel.
- *
- * @param chan Channel to get listener for
- * @return Function pointer to an incoming channel handler
*/
channel_listener_fn_ptr
@@ -843,9 +798,6 @@ channel_get_listener_fn(channel_t *chan)
*
* This function sets the handler for new incoming channels on a listener
* channel.
- *
- * @param chan Listener channel to set handler on
- * @param listener Function pointer to new incoming channel handler
*/
void
@@ -869,9 +821,6 @@ channel_set_listener_fn(channel_t *chan,
*
* This function gets the handler for incoming fixed-length cells installed
* on a channel.
- *
- * @param chan Channel to get the fixed-length cell handler for
- * @return A function pointer to chan's fixed-length cell handler, if any.
*/
channel_cell_handler_fn_ptr
@@ -893,9 +842,6 @@ channel_get_cell_handler(channel_t *chan)
*
* This function gets the handler for incoming variable-length cells
* installed on a channel.
- *
- * @param chan Channel to get the variable-length cell handler for
- * @return A function pointer to chan's variable-length cell handler, if any.
*/
channel_var_cell_handler_fn_ptr
@@ -918,11 +864,6 @@ channel_get_var_cell_handler(channel_t *chan)
* This function sets both the fixed-length and variable length cell handlers
* for a channel and processes any incoming cells that had been blocked in the
* queue because none were available.
- *
- * @param chan Channel to set the fixed-length cell handler for
- * @param cell_handler Function pointer to new fixed-length cell handler
- * @param var_cell_handler Function pointer to new variable-length cell
- handler
*/
void
@@ -965,13 +906,11 @@ channel_set_cell_handlers(channel_t *chan,
}
/**
- * Mark a channel to be closed
+ * Mark a channel for closure
*
* This function tries to close a channel_t; it will go into the CLOSING
* state, and eventually the lower layer should put it into the CLOSED or
* ERROR state. Then, channel_run_cleanup() will eventually free it.
- *
- * @param chan Channel to close
*/
void
@@ -1012,8 +951,6 @@ channel_mark_for_close(channel_t *chan)
* Notify the channel code that the channel is being closed due to a non-error
* condition in the lower layer. This does not call the close() method, since
* the lower layer already knows.
- *
- * @param chan Channel to notify for close
*/
void
@@ -1043,8 +980,6 @@ channel_close_from_lower_layer(channel_t *chan)
* This function is called by the lower layer implementing the transport
* when a channel must be closed due to an error condition. This does not
* call the channel's close method, since the lower layer already knows.
- *
- * @param chan Channel to notify for error
*/
void
@@ -1074,8 +1009,6 @@ channel_close_for_error(channel_t *chan)
* This function should be called by the lower layer when a channel
* is finished closing and it should be regarded as inactive and
* freed by the channel code.
- *
- * @param chan Channel to notify closure on
*/
void
@@ -1110,8 +1043,6 @@ channel_closed(channel_t *chan)
*
* This function clears the identity digest of the remote endpoint for a
* channel; this is intended for use by the lower layer.
- *
- * @param chan Channel to clear
*/
void
@@ -1147,9 +1078,6 @@ channel_clear_identity_digest(channel_t *chan)
*
* This function sets the identity digest of the remote endpoint for a
* channel; this is intended for use by the lower layer.
- *
- * @param chan Channel to clear
- * @param identity_digest New identity digest for chan
*/
void
@@ -1208,8 +1136,6 @@ channel_set_identity_digest(channel_t *chan,
*
* This function clears all the remote end info from a channel; this is
* intended for use by the lower layer.
- *
- * @param chan Channel to clear
*/
void
@@ -1246,10 +1172,6 @@ channel_clear_remote_end(channel_t *chan)
*
* This function sets new remote end info on a channel; this is intended
* for use by the lower layer.
- *
- * @chan Channel to set data on
- * @chan identity_digest New identity digest for chan
- * @chan nickname New remote nickname for chan
*/
void
@@ -1340,6 +1262,8 @@ cell_queue_entry_is_padding(cell_queue_entry_t *q)
}
/**
+ * Write to a channel based on a cell_queue_entry_t
+ *
* Given a cell_queue_entry_t filled out by the caller, try to send the cell
* and queue it if we can't.
*/
@@ -1502,9 +1426,6 @@ channel_write_var_cell(channel_t *chan, var_cell_t *var_cell)
* This internal and subclass use only function is used to change channel
* state, performing all transition validity checks and whatever actions
* are appropriate to the state transition in question.
- *
- * @param chan Channel to change state on
- * @param to_state State to change chan to
*/
void
@@ -1653,10 +1574,6 @@ channel_change_state(channel_t *chan, channel_state_t to_state)
* it will try to write up to num_cells cells from the channel's cell queue or
* from circuits active on that channel, or as many as it has available if
* num_cells == -1.
- *
- * @param chan Channel to flush from
- * @param num_cells Maximum number of cells to flush, or -1 for unlimited
- * @return Number of cells flushed
*/
#define MAX_CELLS_TO_GET_FROM_CIRCUITS_FOR_UNLIMITED 256
@@ -1701,14 +1618,10 @@ channel_flush_some_cells(channel_t *chan, ssize_t num_cells)
}
/**
- * Flush cells from just the channel's out going cell queue
+ * Flush cells from just the channel's outgoing cell queue
*
* This gets called from channel_flush_some_cells() above to flush cells
* just from the queue without trying for active_circuits.
- *
- * @param chan Channel to flush from
- * @param num_cells Maximum number of cells to flush, or -1 for unlimited
- * @return Number of cells flushed
*/
static ssize_t
@@ -1841,13 +1754,11 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
}
/**
- * Try to flush as many cells as we possibly can from the queue
+ * Flush as many cells as we possibly can from the queue
*
* This tries to flush as many cells from the queue as the lower layer
* will take. It just calls channel_flush_some_cells_from_outgoing_queue()
* in unlimited mode.
- *
- * @param chan Channel to flush
*/
void
@@ -1861,9 +1772,6 @@ channel_flush_cells(channel_t *chan)
*
* This gets used from the lower layer to check if any more cells are
* available.
- *
- * @param chan Channel to check on
- * @return 1 if cells are available, 0 otherwise
*/
int
@@ -1888,8 +1796,6 @@ channel_more_to_flush(channel_t *chan)
*
* Connection.c will call this when we've flushed the output; there's some
* dirreq-related maintenance to do.
- *
- * @param chan Channel to notify
*/
void
@@ -1909,8 +1815,6 @@ channel_notify_flushed(channel_t *chan)
*
* Use a listener's registered callback to process as many entries in the
* queue of incoming channels as possible.
- *
- * @param listener Pointer to a listening channel.
*/
void
@@ -1965,8 +1869,6 @@ channel_process_incoming(channel_t *listener)
* until there is positive confirmation that the network is operational.
* In particular, anything UDP-based should not make this transition until a
* packet is received from the other side.
- *
- * @param chan Channel that has become open
*/
void
@@ -2016,9 +1918,6 @@ channel_do_open_actions(channel_t *chan)
* Internal and subclass use only function to queue an incoming channel from
* a listening one. A subclass of channel_t should call this when a new
* incoming channel is created.
- *
- * @param listener Listening channel to queue on
- * @param incoming New incoming channel
*/
void
@@ -2079,8 +1978,6 @@ channel_queue_incoming(channel_t *listener, channel_t *incoming)
*
* Process as many queued cells as we can from the incoming
* cell queue.
- *
- * @param chan Channel to process incoming cell queue on
*/
void
@@ -2150,9 +2047,6 @@ channel_process_cells(channel_t *chan)
*
* This should be called by a channel_t subclass to queue an incoming fixed-
* length cell for processing, and process it if possible.
- *
- * @param chan Channel the cell is arriving on
- * @param cell Incoming cell to queue and process
*/
void
@@ -2212,9 +2106,6 @@ channel_queue_cell(channel_t *chan, cell_t *cell)
*
* This should be called by a channel_t subclass to queue an incoming
* variable-length cell for processing, and process it if possible.
- *
- * @param chan Channel the cell is arriving on
- * @param var_cell Incoming cell to queue and process
*/
void
@@ -2275,11 +2166,6 @@ channel_queue_var_cell(channel_t *chan, var_cell_t *var_cell)
* Write a destroy cell with circ ID <b>circ_id</b> and reason <b>reason</b>
* onto channel <b>chan</b>. Don't perform range-checking on reason:
* we may want to propagate reasons from other cells.
- *
- * @param circ_id Circuit ID to destroy
- * @param chan Channel to send on
- * @param reason Reason code
- * @return Always 0
*/
int
@@ -2302,7 +2188,7 @@ channel_send_destroy(circid_t circ_id, channel_t *chan, int reason)
}
/**
- * Channel statistics
+ * Dump channel statistics to the log
*
* This is called from dumpstats() in main.c and spams the log with
* statistics on channels.
@@ -2337,7 +2223,7 @@ channel_dumpstats(int severity)
}
/**
- * Channel cleanup
+ * Clean up channels
*
* This gets called periodically from run_scheduled_events() in main.c;
* it cleans up after closed channels.
@@ -2487,11 +2373,6 @@ channel_free_all(void)
* or make a new type including a tor_addr_t and port, so we have a
* single abstract object encapsulating all the protocol details of
* how to contact an OR.
- *
- * @param addr Address of remote node to establish a channel to
- * @param port ORport of remote OR
- * @param id_digest Identity digest of remote OR
- * @return New channel, or NULL if failure
*/
channel_t *
@@ -2510,12 +2391,6 @@ channel_connect(const tor_addr_t *addr, uint16_t port,
* number of circuits and the age are used as tie-breakers.
*
* This is based on the former connection_or_is_better() of connection_or.c
- *
- * @param now Current time to use for deciding grace period for new channels
- * @param a Channel A for comparison
- * @param b Channel B for comparison
- * @param forgive_new_connections Whether to use grace period for new channels
- * @return 1 iff a is better than b
*/
int
@@ -2576,13 +2451,6 @@ channel_is_better(time_t now, channel_t *a, channel_t *b,
* channel, set *msg_out to a message describing the channel's state
* and our next action, and set *launch_out to a boolean indicated whether
* the caller should try to launch a new channel with channel_connect().
- *
- * @param digest Endpoint digest we want
- * @param target_addr Endpoint address we want
- * @param msg_out Write out status message here if we fail
- * @param launch_out Write 1 here if caller should try to connect a new
- * channel.
- * @return Pointer to selected channel, or NULL if none available
*/
channel_t *
@@ -2869,7 +2737,6 @@ channel_dump_statistics(channel_t *chan, int severity)
(chan->u.cell_chan.active_circuit_pqueue != NULL) ?
smartlist_len(chan->u.cell_chan.active_circuit_pqueue) : 0,
chan->u.cell_chan.n_circuits);
- /* TODO better circuit info once circuit structure refactor is finished */
/* Describe timestamps */
log(severity, LD_GENERAL,
@@ -2963,9 +2830,6 @@ channel_dump_transport_statistics(channel_t *chan, int severity)
* This function return a test provided by the lower layer of the remote
* endpoint for this channel; it should specify the actual address connected
* to/from.
- *
- * @param chan Channel to describe
- * @return Pointer to string description
*/
const char *
@@ -2985,9 +2849,6 @@ channel_get_actual_remote_descr(channel_t *chan)
* This function return a test provided by the lower layer of the remote
* endpoint for this channel; it should use the known canonical address for
* this OR's identity digest if possible.
- *
- * @param chan Channel to describe
- * @return Pointer to string description
*/
const char *
@@ -3006,10 +2867,6 @@ channel_get_canonical_remote_descr(channel_t *chan)
*
* Write the remote address out to a tor_addr_t if the underlying transport
* supports this operation.
- *
- * @param chan Channel to request remote address from
- * @param addr_out Write the address out here
- * @return 1 if successful, 0 if not
*/
int
@@ -3030,9 +2887,6 @@ channel_get_addr_if_possible(channel_t *chan, tor_addr_t *addr_out)
*
* Indicate if either we have queued cells, or if not, whether the underlying
* lower-layer transport thinks it has an output queue.
- *
- * @param chan Channel to query
- * @return 1 if there are queued writes, 0 otherwise
*/
int
@@ -3060,9 +2914,6 @@ channel_has_queued_writes(channel_t *chan)
*
* This function returns the is_bad_for_new_circs flag of the specified
* channel.
- *
- * @param chan Channel to get flag on
- * @return Flag value
*/
int
@@ -3078,8 +2929,6 @@ channel_is_bad_for_new_circs(channel_t *chan)
* Mark a channel as bad for new circuits
*
* Set the is_bad_for_new_circs_flag on chan.
- *
- * @param chan Channel to mark
*/
void
@@ -3097,9 +2946,6 @@ channel_mark_bad_for_new_circs(channel_t *chan)
* This returns the client flag of a channel, which will be set if
* command_process_create_cell() in command.c thinks this is a connection
* from a client.
- *
- * @param chan Channel to query flag
- * @return Flag value
*/
int
@@ -3115,8 +2961,6 @@ channel_is_client(channel_t *chan)
* Set the client flag
*
* Mark a channel as being from a client
- *
- * @param chan Channel to mark
*/
void
@@ -3133,9 +2977,6 @@ channel_mark_client(channel_t *chan)
*
* This returns the is_canonical for a channel; this flag is determined by
* the lower layer and can't be set in a transport-independent way.
- *
- * @param chan Channel to query
- * @return Flag value
*/
int
@@ -3153,10 +2994,6 @@ channel_is_canonical(channel_t *chan)
*
* This function asks if the lower layer thinks it's safe to trust the
* result of channel_is_canonical()
- *
- * @param chan Channel to query
- * @return 1 if the lower layer thinks the is_canonical flag is reliable, 0
- * otherwise.
*/
int
@@ -3174,9 +3011,6 @@ channel_is_canonical_is_reliable(channel_t *chan)
*
* This function gets the incoming flag; this is set when a listener spawns
* a channel. If this returns true the channel was remotely initiated.
- *
- * @param chan Channel to query
- * @return Flag value
*/
int
@@ -3193,8 +3027,6 @@ channel_is_incoming(channel_t *chan)
*
* This function is called when a channel arrives on a listening channel
* to mark it as incoming.
- *
- * @param chan Channel to mark
*/
void
@@ -3214,9 +3046,6 @@ channel_mark_incoming(channel_t *chan)
* destinations it will communicate with on behalf of this channel. It's
* used to decide whether to declare the network reachable when seeing incoming
* traffic on the channel.
- *
- * @param chan Channel to query
- * @return Flag value
*/
int
@@ -3234,8 +3063,6 @@ channel_is_local(channel_t *chan)
* This internal-only function should be called by the lower layer if the
* channel is to a local address. See channel_is_local() above or the
* description of the is_local bit in channel.h
- *
- * @param chan Channel to mark
*/
void
@@ -3253,9 +3080,6 @@ channel_mark_local(channel_t *chan)
* This function gets the outgoing flag; this is the inverse of the incoming
* bit set when a listener spawns a channel. If this returns true the channel
* was locally initiated.
- *
- * @param chan Channel to query
- * @return Flag value
*/
int
@@ -3272,8 +3096,6 @@ channel_is_outgoing(channel_t *chan)
*
* This function clears the incoming flag and thus marks a channel as
* outgoing.
- *
- * @param chan Channel to mark
*/
void
@@ -3294,8 +3116,6 @@ channel_mark_outgoing(channel_t *chan)
*
* This updates the channel's created timestamp and should only be called
* from channel_init().
- *
- * @param chan Channel to update
*/
void
@@ -3317,8 +3137,6 @@ channel_timestamp_created(channel_t *chan)
* is also updated from channel_timestamp_recv() and channel_timestamp_xmit(),
* but it should be updated for things like the v3 handshake and stuff that
* produce activity only visible to the lower layer.
- *
- * @param chan Channel to update
*/
void
@@ -3336,8 +3154,6 @@ channel_timestamp_active(channel_t *chan)
*
* This function updates the channel's last accepted timestamp; it should be
* called whenever a new incoming channel is accepted on a listener.
- *
- * @param chan Channel to update
*/
void
@@ -3356,8 +3172,6 @@ channel_timestamp_accepted(channel_t *chan)
*
* This function is called by relay.c to timestamp a channel that appears to
* be used as a client.
- *
- * @param chan Channel to update
*/
void
@@ -3376,8 +3190,6 @@ channel_timestamp_client(channel_t *chan)
*
* This is called whenever we transmit a cell which leaves the outgoing cell
* queue completely empty. It also updates the xmit time and the active time.
- *
- * @param chan Channel to update
*/
void
@@ -3398,8 +3210,6 @@ channel_timestamp_drained(channel_t *chan)
*
* This is called whenever we get an incoming cell from the lower layer.
* This also updates the active timestamp.
- *
- * @param chan Channel to update
*/
void
@@ -3418,8 +3228,6 @@ channel_timestamp_recv(channel_t *chan)
* Update the xmit timestamp
* This is called whenever we pass an outgoing cell to the lower layer. This
* also updates the active timestamp.
- *
- * @param chan Channel to update
*/
void
@@ -3440,9 +3248,6 @@ channel_timestamp_xmit(channel_t *chan)
/**
* Query created timestamp
- *
- * @param chan Channel to query
- * @return Created timestamp value for chan
*/
time_t
@@ -3455,9 +3260,6 @@ channel_when_created(channel_t *chan)
/**
* Query last active timestamp
- *
- * @param chan Channel to query
- * @return Last active timestamp value for chan
*/
time_t
@@ -3470,9 +3272,6 @@ channel_when_last_active(channel_t *chan)
/**
* Query last accepted timestamp
- *
- * @param chan Channel to query
- * @return Last accepted timestamp value for chan
*/
time_t
@@ -3486,9 +3285,6 @@ channel_when_last_accepted(channel_t *chan)
/**
* Query client timestamp
- *
- * @param chan Channel to query
- * @return Client timestamp value for chan
*/
time_t
@@ -3502,9 +3298,6 @@ channel_when_last_client(channel_t *chan)
/**
* Query drained timestamp
- *
- * @param chan Channel to query
- * @return drained timestamp value for chan
*/
time_t
@@ -3518,9 +3311,6 @@ channel_when_last_drained(channel_t *chan)
/**
* Query recv timestamp
- *
- * @param chan Channel to query
- * @return Recv timestamp value for chan
*/
time_t
@@ -3534,9 +3324,6 @@ channel_when_last_recv(channel_t *chan)
/**
* Query xmit timestamp
- *
- * @param chan Channel to query
- * @return Xmit timestamp value for chan
*/
time_t
@@ -3550,9 +3337,6 @@ channel_when_last_xmit(channel_t *chan)
/**
* Query accepted counter
- *
- * @param chan Channel to query
- * @return Number of incoming channels accepted by this listener
*/
uint64_t
@@ -3566,9 +3350,6 @@ channel_count_accepted(channel_t *chan)
/**
* Query received cell counter
- *
- * @param chan Channel to query
- * @return Number of cells received by this channel
*/
uint64_t
@@ -3582,9 +3363,6 @@ channel_count_recved(channel_t *chan)
/**
* Query transmitted cell counter
- *
- * @param chan Channel to query
- * @return Number of cells transmitted by this channel
*/
uint64_t
@@ -3601,10 +3379,6 @@ channel_count_xmitted(channel_t *chan)
*
* This function calls the lower layer and asks if this channel matches a
* given extend_info_t.
- *
- * @param chan Channel to test
- * @param extend_info Pointer to extend_info_t to match
- * @return 1 if they match, 0 otherwise
*/
int
@@ -3623,10 +3397,6 @@ channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info)
*
* This function calls into the lower layer and asks if this channel thinks
* it matches a given target address for circuit extension purposes.
- *
- * @param chan Channel to test
- * @param target Address to match
- * @return 1 if they match, 0 otherwise
*/
int
@@ -3646,9 +3416,6 @@ channel_matches_target_addr_for_extend(channel_t *chan,
*
* This is called when setting up a channel and replaces the old
* connection_or_set_circid_type()
- *
- * @param chan Channel to set up
- * @param identity_rcvd Remote end's identity public key
*/
void
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index bb6ef9b..bb90ce5 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -89,11 +89,6 @@ static int enter_v3_handshake_with_cell(var_cell_t *cell,
* Launch a new OR connection to <b>addr</b>:<b>port</b> and expect to
* handshake with an OR with identity digest <b>id_digest</b>, and wrap
* it in a channel_tls_t.
- *
- * @param addr Address to connect on
- * @param port Port to connect on
- * @param id_digest Identity digest we want
- * @return The launched channel, or NULL if it failed.
*/
channel_t *
@@ -161,8 +156,6 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
*
* Returns the current listening channel for incoming TLS connections, or
* NULL if none has been established
- *
- * @return TLS listener
*/
channel_t *
@@ -176,8 +169,6 @@ channel_tls_get_listener(void)
*
* Return the current channel_tls_t listener, or start one if we haven't yet,
* and return that.
- *
- * @return TLS listener
*/
channel_t *
@@ -235,9 +226,6 @@ channel_tls_free_all(void)
/**
* Create a new channel around an incoming or_connection_t
- *
- * @param orconn New or_connection_t
- * @return A channel to queue on the TLS listener
*/
channel_t *
@@ -288,8 +276,6 @@ channel_tls_handle_incoming(or_connection_t *orconn)
* Close a channel_tls_t
*
* This implements the close method for channel_tls_t
- *
- * @param chan Channel to close
*/
static void
@@ -384,10 +370,6 @@ channel_tls_describe_transport_method(channel_t *chan)
* This implements the get_remote_addr method for channel_tls_t; copy the
* remote endpoint of the channel to addr_out and return 1 (always
* succeeds for this transport).
- *
- * @param chan Channel to query
- * @param addr_out Write the address out here
- * @return Always succeeds and returns 1
*/
static int
@@ -411,10 +393,6 @@ channel_tls_get_remote_addr_method(channel_t *chan, tor_addr_t *addr_out)
* a text description of the remote endpoint of the channel suitable for use
* in log messages. The req parameter is 0 for the canonical address or 1 for
* the actual address seen.
- *
- * @param chan Channel to query
- * @param req Request type (0 for canonical, 1 for actual)
- * @return Pointer to string containing description
*/
static const char *
@@ -461,9 +439,6 @@ channel_tls_get_remote_descr_method(channel_t *chan, int req)
*
* This implements the has_queued_writes method for channel_tls _t; it returns
* 1 iff we have queued writes on the outbuf of the underlying or_connection_t.
- *
- * @param chan Channel to query
- * @return Whether we have queued writes on the outbuf
*/
static int
@@ -486,10 +461,6 @@ channel_tls_has_queued_writes_method(channel_t *chan)
* This implements the is_canonical method for channel_tls_t; if req is zero,
* it returns whether this is a canonical channel, and if it is one it returns
* whether that can be relied upon.
- *
- * @param chan Channel to query
- * @param req Request type (0 for is_canonical, 1 for is_canonical_reliable)
- * @return Query response
*/
static int
@@ -526,10 +497,6 @@ channel_tls_is_canonical_method(channel_t *chan, int req)
*
* This implements the matches_extend_info method for channel_tls_t; the upper
* layer wants to know if this channel matches an extend_info_t.
- *
- * @param chan Channel to test
- * @param extend_info The extend_info_t to match
- * @return 1 if this channel matches, 0 otherwise
*/
static int
@@ -552,10 +519,6 @@ channel_tls_matches_extend_info_method(channel_t *chan,
* This implements the matches_target method for channel_tls _t; the upper
* layer wants to know if this channel matches a target address when extending
* a circuit.
- *
- * @param chan Channel to test
- * @param target Address to match
- * @return 1 if this channel matches, 0 otherwise
*/
static int
@@ -577,10 +540,6 @@ channel_tls_matches_target_method(channel_t *chan,
*
* This implements the write_cell method for channel_tls_t; given a
* channel_tls_t and a cell_t, transmit the cell_t.
- *
- * @param chan Channel to transmit on
- * @param cell Cell to transmit
- * @return Always succeeds and returns 1
*/
static int
@@ -602,10 +561,6 @@ channel_tls_write_cell_method(channel_t *chan, cell_t *cell)
*
* This implements the write_packed_cell method for channel_tls_t; given a
* channel_tls_t and a packed_cell_t, transmit the packed_cell_t.
- *
- * @param chan Channel to transmit on
- * @param packed_cell Cell to transmit
- * @return Always succeeds and returns 1
*/
static int
@@ -632,10 +587,6 @@ channel_tls_write_packed_cell_method(channel_t *chan,
*
* This implements the write_var_cell method for channel_tls_t; given a
* channel_tls_t and a var_cell_t, transmit the var_cell_t.
- *
- * @param chan Channel to transmit on
- * @param var_cell Cell to transmit
- * @return Always succeeds and returns 1
*/
static int
@@ -657,15 +608,10 @@ channel_tls_write_var_cell_method(channel_t *chan, var_cell_t *var_cell)
******************************************************/
/**
- * Handle orconn state changes
+ * Handle an orconn state change
*
* This function will be called by connection_or.c when the or_connection_t
* associated with this channel_tls_t changes state.
- *
- * @param chan Channel controlling the or_connection_t
- * @param conn The or_connection_t changing state
- * @param old_state The old state of conn
- * @param state The new state of conn
*/
void
@@ -712,13 +658,9 @@ channel_tls_handle_state_change_on_orconn(channel_tls_t *chan,
}
/**
- * Try to flush cells from a channel_tls_t
+ * Flush cells from a channel_tls_t
*
* Try to flush up to about num_cells cells, and return how many we flushed.
- *
- * @param chan Channel to flush
- * @param num_cells Maximum number of cells
- * @return Number of cells actually flushed
*/
ssize_t
@@ -752,9 +694,6 @@ channel_tls_flush_some_cells(channel_tls_t *chan, ssize_t num_cells)
*
* Return true if there is any more to flush on this channel (cells in queue
* or active circuits).
- *
- * @param chan Channel to test
- * @return 1 if chan has anything to flush, 0 otherwise
*/
int
@@ -778,12 +717,6 @@ channel_tls_more_to_flush(channel_tls_t *chan)
* This is a wrapper function around the actual function that processes the
* <b>cell</b> that just arrived on <b>chan</b>. Increment <b>*time</b>
* by the number of microseconds used by the call to <b>*func(cell, chan)</b>.
- *
- * @param cell Incoming cell to process
- * @param chan Channel it arrived on
- * @param time Increment this by the number of microseconds it took to handle
- * this cell
- * @param func Function pointer to cell handling function
*/
static void
@@ -820,9 +753,6 @@ channel_tls_time_process_cell(cell_t *cell, channel_tls_t *chan, int *time,
* for cell types specific to the handshake for this transport protocol and
* handles them, and queues all other cells to the channel_t layer, which
* eventually will hand them off to command.c.
- *
- * @param cell Cell to handle
- * @param conn The or_connection_t cell arrived on
*/
void
@@ -920,9 +850,6 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
* related and live below the channel_t layer, so no variable-length
* cells ever get delivered in the current implementation, but I've left
* the mechanism in place for future use.
- *
- * @param var_cell Incoming cell to handle
- * @param conn The or_connection_t var_cell arrived on
*/
void
@@ -1091,8 +1018,6 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn)
*
* Return true if <b>command</b> is a cell command that's allowed to start a
* V3 handshake.
- *
- * @param command Cell type to check
*/
static int
@@ -1115,10 +1040,6 @@ command_allowed_before_handshake(uint8_t command)
* either for a cell or a TLS handshake. Set the connection's state to
* "handshaking_v3', initializes the or_handshake_state field as needed,
* and add the cell to the hash of incoming cells.)
- *
- * @param cell Incoming cell initiating the handshake
- * @param chan Channel cell was received on
- * @return 0 on success; return -1 and mark the connection on failure.
*/
static int
@@ -1159,9 +1080,6 @@ enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan)
* negotiated. We compare the versions in the cell to the list of versions
* we support, pick the highest version we have in common, and continue the
* negotiation from there.
- *
- * @param cell Incoming VERSIONS cell
- * @param chan Channel that cell arrived on
*/
static void
@@ -1311,9 +1229,6 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan)
*
* This function is called to handle an incoming NETINFO cell; read and act
* on its contents, and set the connection state to "open".
- *
- * @param cell Incoming NETINFO cell
- * @param chan Channel that cell arrived on
*/
static void
@@ -1493,9 +1408,6 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
* store the certificates in or_handshake_state. If this is the client side
* of the connection, we then authenticate the server or mark the connection.
* If it's the server side, wait for an AUTHENTICATE cell.
- *
- * @param cell Incoming CERTS cell
- * @param chan Channel that cell arrived on
*/
static void
@@ -1694,9 +1606,6 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
* a v3 handshake, mark the channel. If the cell is well-formed but we don't
* want to authenticate, just drop it. If the cell is well-formed *and* we
* want to authenticate, send an AUTHENTICATE cell and then a NETINFO cell.
- *
- * @param cell Incoming AUTH_CHALLENGE cell to handle
- * @param chan Channel that cell arrived on
*/
static void
@@ -1794,9 +1703,6 @@ channel_tls_process_auth_challenge_cell(var_cell_t *cell, channel_tls_t *chan)
* other side of the connection successfully (because it isn't signed right,
* we didn't get a CERTS cell, etc) mark the connection. Otherwise, accept
* the identity of the router on the other side of the connection.
- *
- * @param cell Incoming AUTHENTICATE cell
- * @param chan Channel that cell arrived on
*/
static void
1
0

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

[tor/master] Refactor channel_write_cell()/channel_write_packed_cell()/channel_write_var_cell() to eliminate redundant code
by andrea@torproject.org 11 Oct '12
by andrea@torproject.org 11 Oct '12
11 Oct '12
commit 06a76d1db49d7c9c386368583928cde11b509519
Author: Andrea Shepard <andrea(a)torproject.org>
Date: Mon Oct 8 21:16:59 2012 -0700
Refactor channel_write_cell()/channel_write_packed_cell()/channel_write_var_cell() to eliminate redundant code
---
src/or/channel.c | 217 ++++++++++++++++++++++++++---------------------------
1 files changed, 106 insertions(+), 111 deletions(-)
diff --git a/src/or/channel.c b/src/or/channel.c
index 9fbfecb..fac4017 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -74,6 +74,8 @@ static uint64_t n_channels_allocated = 0;
*/
static digestmap_t *channel_identity_map = NULL;
+static int cell_queue_entry_is_padding(cell_queue_entry_t *q);
+
/* Functions to maintain the digest map */
static void channel_add_to_digest_map(channel_t *chan);
static void channel_remove_from_digest_map(channel_t *chan);
@@ -85,8 +87,9 @@ static void channel_remove_from_digest_map(channel_t *chan);
static ssize_t
channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
ssize_t num_cells);
-
static void channel_force_free(channel_t *chan);
+static void
+channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q);
/***********************************
* Channel state utility functions *
@@ -1308,39 +1311,56 @@ channel_set_remote_end(channel_t *chan,
}
/**
- * Write a cell to a channel
- *
- * Write a fixed-length cell to a channel using the write_cell() method.
- * This is equivalent to the pre-channels connection_or_write_cell_to_buf().
- *
- * @param chan Channel to write a cell to
- * @param cell Cell to write to chan
+ * Check whether a cell queue entry is padding; this is a helper function
+ * for channel_write_cell_queue_entry()
*/
-void
-channel_write_cell(channel_t *chan, cell_t *cell)
+static int
+cell_queue_entry_is_padding(cell_queue_entry_t *q)
{
- cell_queue_entry_t *q;
- int sent = 0;
+ tor_assert(q);
+
+ if (q->type == CELL_QUEUE_FIXED) {
+ if (q->u.fixed.cell) {
+ if (q->u.fixed.cell->command == CELL_PADDING ||
+ q->u.fixed.cell->command == CELL_VPADDING) {
+ return 1;
+ }
+ }
+ } else if (q->type == CELL_QUEUE_VAR) {
+ if (q->u.var.var_cell) {
+ if (q->u.var.var_cell->command == CELL_PADDING ||
+ q->u.var.var_cell->command == CELL_VPADDING) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Given a cell_queue_entry_t filled out by the caller, try to send the cell
+ * and queue it if we can't.
+ */
+
+static void
+channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q)
+{
+ int result = 0, sent = 0;
+ cell_queue_entry_t *tmp = NULL;
tor_assert(chan);
tor_assert(!(chan->is_listener));
- tor_assert(cell);
- tor_assert(chan->u.cell_chan.write_cell);
+ tor_assert(q);
/* Assert that the state makes sense for a cell write */
tor_assert(chan->state == CHANNEL_STATE_OPENING ||
chan->state == CHANNEL_STATE_OPEN ||
chan->state == CHANNEL_STATE_MAINT);
- log_debug(LD_CHANNEL,
- "Writing cell_t %p to channel %p with global ID "
- U64_FORMAT,
- cell, chan, U64_PRINTF_ARG(chan->global_identifier));
-
/* Increment the timestamp unless it's padding */
- if (!(cell->command == CELL_PADDING ||
- cell->command == CELL_VPADDING)) {
+ if (!cell_queue_entry_is_padding(q)) {
chan->u.cell_chan.timestamp_last_added_nonpadding = approx_time();
}
@@ -1348,7 +1368,31 @@ channel_write_cell(channel_t *chan, cell_t *cell)
if (!(chan->u.cell_chan.outgoing_queue &&
(smartlist_len(chan->u.cell_chan.outgoing_queue) > 0)) &&
chan->state == CHANNEL_STATE_OPEN) {
- if (chan->u.cell_chan.write_cell(chan, cell)) {
+ /* Pick the right write function for this cell type and save the result */
+ switch (q->type) {
+ case CELL_QUEUE_FIXED:
+ tor_assert(chan->u.cell_chan.write_cell);
+ tor_assert(q->u.fixed.cell);
+ result = chan->u.cell_chan.write_cell(chan, q->u.fixed.cell);
+ break;
+ case CELL_QUEUE_PACKED:
+ tor_assert(chan->u.cell_chan.write_packed_cell);
+ tor_assert(q->u.packed.packed_cell);
+ result = chan->
+ u.cell_chan.write_packed_cell(chan,
+ q->u.packed.packed_cell);
+ break;
+ case CELL_QUEUE_VAR:
+ tor_assert(chan->u.cell_chan.write_var_cell);
+ tor_assert(q->u.var.var_cell);
+ result = chan->u.cell_chan.write_var_cell(chan, q->u.var.var_cell);
+ break;
+ default:
+ tor_assert(1);
+ }
+
+ /* Check if we got it out */
+ if (result > 0) {
sent = 1;
/* Timestamp for transmission */
channel_timestamp_xmit(chan);
@@ -1363,39 +1407,56 @@ channel_write_cell(channel_t *chan, cell_t *cell)
/* Not sent, queue it */
if (!(chan->u.cell_chan.outgoing_queue))
chan->u.cell_chan.outgoing_queue = smartlist_new();
- q = tor_malloc(sizeof(*q));
- q->type = CELL_QUEUE_FIXED;
- q->u.fixed.cell = cell;
- smartlist_add(chan->u.cell_chan.outgoing_queue, q);
+ /*
+ * We have to copy the queue entry passed in, since the caller probably
+ * used the stack.
+ */
+ tmp = tor_malloc(sizeof(*tmp));
+ memcpy(tmp, q, sizeof(*tmp));
+ smartlist_add(chan->u.cell_chan.outgoing_queue, tmp);
/* Try to process the queue? */
if (chan->state == CHANNEL_STATE_OPEN) channel_flush_cells(chan);
}
}
/**
+ * Write a cell to a channel
+ *
+ * Write a fixed-length cell to a channel using the write_cell() method.
+ * This is equivalent to the pre-channels connection_or_write_cell_to_buf().
+ */
+
+void
+channel_write_cell(channel_t *chan, cell_t *cell)
+{
+ cell_queue_entry_t q;
+
+ tor_assert(chan);
+ tor_assert(cell);
+
+ log_debug(LD_CHANNEL,
+ "Writing cell_t %p to channel %p with global ID "
+ U64_FORMAT,
+ cell, chan, U64_PRINTF_ARG(chan->global_identifier));
+
+ q.type = CELL_QUEUE_FIXED;
+ q.u.fixed.cell = cell;
+ channel_write_cell_queue_entry(chan, &q);
+}
+
+/**
* Write a packed cell to a channel
*
* Write a packed cell to a channel using the write_cell() method.
- *
- * @param chan Channel to write a cell to
- * @param packed_cell Cell to write to chan
*/
void
channel_write_packed_cell(channel_t *chan, packed_cell_t *packed_cell)
{
- cell_queue_entry_t *q;
- int sent = 0;
+ cell_queue_entry_t q;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(packed_cell);
- tor_assert(chan->u.cell_chan.write_packed_cell);
-
- /* Assert that the state makes sense for a cell write */
- tor_assert(chan->state == CHANNEL_STATE_OPENING ||
- chan->state == CHANNEL_STATE_OPEN ||
- chan->state == CHANNEL_STATE_MAINT);
log_debug(LD_CHANNEL,
"Writing packed_cell_t %p to channel %p with global ID "
@@ -1403,35 +1464,9 @@ channel_write_packed_cell(channel_t *chan, packed_cell_t *packed_cell)
packed_cell, chan,
U64_PRINTF_ARG(chan->global_identifier));
- /* Increment the timestamp */
- chan->u.cell_chan.timestamp_last_added_nonpadding = approx_time();
-
- /* Can we send it right out? If so, try */
- if (!(chan->u.cell_chan.outgoing_queue &&
- (smartlist_len(chan->u.cell_chan.outgoing_queue) > 0)) &&
- chan->state == CHANNEL_STATE_OPEN) {
- if (chan->u.cell_chan.write_packed_cell(chan, packed_cell)) {
- sent = 1;
- /* Timestamp for transmission */
- channel_timestamp_xmit(chan);
- /* If we're here the queue is empty, so it's drained too */
- channel_timestamp_drained(chan);
- /* Update the counter */
- ++(chan->u.cell_chan.n_cells_xmitted);
- }
- }
-
- if (!sent) {
- /* Not sent, queue it */
- if (!(chan->u.cell_chan.outgoing_queue))
- chan->u.cell_chan.outgoing_queue = smartlist_new();
- q = tor_malloc(sizeof(*q));
- q->type = CELL_QUEUE_PACKED;
- q->u.packed.packed_cell = packed_cell;
- smartlist_add(chan->u.cell_chan.outgoing_queue, q);
- /* Try to process the queue? */
- if (chan->state == CHANNEL_STATE_OPEN) channel_flush_cells(chan);
- }
+ q.type = CELL_QUEUE_PACKED;
+ q.u.packed.packed_cell = packed_cell;
+ channel_write_cell_queue_entry(chan, &q);
}
/**
@@ -1440,26 +1475,15 @@ channel_write_packed_cell(channel_t *chan, packed_cell_t *packed_cell)
* Write a variable-length cell to a channel using the write_cell() method.
* This is equivalent to the pre-channels
* connection_or_write_var_cell_to_buf().
- *
- * @param chan Channel to write a cell to
- * @param var_cell Cell to write to chan
*/
void
channel_write_var_cell(channel_t *chan, var_cell_t *var_cell)
{
- cell_queue_entry_t *q;
- int sent = 0;
+ cell_queue_entry_t q;
tor_assert(chan);
- tor_assert(!(chan->is_listener));
tor_assert(var_cell);
- tor_assert(chan->u.cell_chan.write_var_cell);
-
- /* Assert that the state makes sense for a cell write */
- tor_assert(chan->state == CHANNEL_STATE_OPENING ||
- chan->state == CHANNEL_STATE_OPEN ||
- chan->state == CHANNEL_STATE_MAINT);
log_debug(LD_CHANNEL,
"Writing var_cell_t %p to channel %p with global ID "
@@ -1467,38 +1491,9 @@ channel_write_var_cell(channel_t *chan, var_cell_t *var_cell)
var_cell, chan,
U64_PRINTF_ARG(chan->global_identifier));
- /* Increment the timestamp unless it's padding */
- if (!(var_cell->command == CELL_PADDING ||
- var_cell->command == CELL_VPADDING)) {
- chan->u.cell_chan.timestamp_last_added_nonpadding = approx_time();
- }
-
- /* Can we send it right out? If so, then try */
- if (!(chan->u.cell_chan.outgoing_queue &&
- (smartlist_len(chan->u.cell_chan.outgoing_queue) > 0)) &&
- chan->state == CHANNEL_STATE_OPEN) {
- if (chan->u.cell_chan.write_var_cell(chan, var_cell)) {
- sent = 1;
- /* Timestamp for transmission */
- channel_timestamp_xmit(chan);
- /* If we're here the queue is empty, so it's drained too */
- channel_timestamp_drained(chan);
- /* Update the counter */
- ++(chan->u.cell_chan.n_cells_xmitted);
- }
- }
-
- if (!sent) {
- /* Not sent, queue it */
- if (!(chan->u.cell_chan.outgoing_queue))
- chan->u.cell_chan.outgoing_queue = smartlist_new();
- q = tor_malloc(sizeof(*q));
- q->type = CELL_QUEUE_VAR;
- q->u.var.var_cell = var_cell;
- smartlist_add(chan->u.cell_chan.outgoing_queue, q);
- /* Try to process the queue? */
- if (chan->state == CHANNEL_STATE_OPEN) channel_flush_cells(chan);
- }
+ q.type = CELL_QUEUE_VAR;
+ q.u.var.var_cell = var_cell;
+ channel_write_cell_queue_entry(chan, &q);
}
/**
1
0

11 Oct '12
commit bddfb9ffa85a0fe73545fb231a0847c4101758c1
Author: Andrea Shepard <andrea(a)torproject.org>
Date: Tue Oct 9 14:16:51 2012 -0700
Add magic number for type-checking channel casts
---
src/or/channel.h | 3 +++
src/or/channeltls.c | 37 +++++++++++++++++++++++++++++++++++--
src/or/channeltls.h | 11 +++++++++--
3 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/src/or/channel.h b/src/or/channel.h
index c31806c..27fba8f 100644
--- a/src/or/channel.h
+++ b/src/or/channel.h
@@ -26,6 +26,9 @@ typedef void (*channel_var_cell_handler_fn_ptr)(channel_t *, var_cell_t *);
*/
struct channel_s {
+ /* Magic number for type-checking cast macros */
+ uint32_t magic;
+
/* Current channel state */
channel_state_t state;
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 339663e..5d6a7a9 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -102,8 +102,9 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
const char *id_digest)
{
channel_tls_t *tlschan = tor_malloc_zero(sizeof(*tlschan));
- channel_t *chan = TLS_CHAN_TO_BASE(tlschan);
+ channel_t *chan = &(tlschan->_base);
channel_init(chan);
+ chan->magic = TLS_CHAN_MAGIC;
chan->state = CHANNEL_STATE_OPENING;
chan->close = channel_tls_close_method;
chan->describe_transport = channel_tls_describe_transport_method;
@@ -233,12 +234,13 @@ channel_t *
channel_tls_handle_incoming(or_connection_t *orconn)
{
channel_tls_t *tlschan = tor_malloc_zero(sizeof(*tlschan));
- channel_t *chan = TLS_CHAN_TO_BASE(tlschan);
+ channel_t *chan = &(tlschan->_base);
tor_assert(orconn);
tor_assert(!(orconn->chan));
channel_init(chan);
+ chan->magic = TLS_CHAN_MAGIC;
chan->state = CHANNEL_STATE_OPENING;
chan->close = channel_tls_close_method;
chan->describe_transport = channel_tls_describe_transport_method;
@@ -267,6 +269,37 @@ channel_tls_handle_incoming(or_connection_t *orconn)
return chan;
}
+/*********
+ * Casts *
+ ********/
+
+/**
+ * Cast a channel_tls_t to a channel_t.
+ */
+
+channel_t *
+channel_tls_to_base(channel_tls_t *tlschan)
+{
+ if (!tlschan) return NULL;
+
+ return &(tlschan->_base);
+}
+
+/**
+ * Cast a channel_t to a channel_tls_t, with appropriate type-checking
+ * asserts.
+ */
+
+channel_tls_t *
+channel_tls_from_base(channel_t *chan)
+{
+ if (!chan) return NULL;
+
+ tor_assert(chan->magic == TLS_CHAN_MAGIC);
+
+ return (channel_tls_t *)(chan);
+}
+
/********************************************
* Method implementations for channel_tls_t *
*******************************************/
diff --git a/src/or/channeltls.h b/src/or/channeltls.h
index b38e12a..ca2fc88 100644
--- a/src/or/channeltls.h
+++ b/src/or/channeltls.h
@@ -12,8 +12,10 @@
#include "or.h"
#include "channel.h"
-#define BASE_CHAN_TO_TLS(c) ((channel_tls_t *)(c))
-#define TLS_CHAN_TO_BASE(c) ((channel_t *)(c))
+#define BASE_CHAN_TO_TLS(c) (channel_tls_from_base((c)))
+#define TLS_CHAN_TO_BASE(c) (channel_tls_to_base((c)))
+
+#define TLS_CHAN_MAGIC 0x8a192427U
#ifdef _TOR_CHANNEL_INTERNAL
@@ -32,6 +34,11 @@ 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);
+/* Casts */
+
+channel_t * channel_tls_to_base(channel_tls_t *tlschan);
+channel_tls_t * channel_tls_from_base(channel_t *chan);
+
/* Things for connection_or.c to call back into */
ssize_t channel_tls_flush_some_cells(channel_tls_t *chan, ssize_t num_cells);
int channel_tls_more_to_flush(channel_tls_t *chan);
1
0

[tor/master] Use circuitmux_t in channels and when relaying cells
by andrea@torproject.org 11 Oct '12
by andrea@torproject.org 11 Oct '12
11 Oct '12
commit b208539b8047a12fb2f1f794c9932fddd577dfdb
Author: Andrea Shepard <andrea(a)torproject.org>
Date: Fri Sep 21 14:46:22 2012 -0700
Use circuitmux_t in channels and when relaying cells
---
src/or/channel.c | 49 ++++++---
src/or/channel.h | 33 ++-----
src/or/channeltls.c | 17 ++-
src/or/circuitlist.c | 38 ++++++-
src/or/connection_or.c | 2 +-
src/or/or.h | 42 ++++++--
src/or/relay.c | 283 +++++++++++++++++++++++-------------------------
src/or/relay.h | 7 +-
8 files changed, 258 insertions(+), 213 deletions(-)
diff --git a/src/or/channel.c b/src/or/channel.c
index 334f843..8241556 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -19,6 +19,7 @@
#include "circuitbuild.h"
#include "circuitlist.h"
#include "connection_or.h" /* For var_cell_free() */
+#include "circuitmux.h"
#include "geoip.h"
#include "nodelist.h"
#include "relay.h"
@@ -813,9 +814,10 @@ channel_free(channel_t *chan)
channel_clear_remote_end(chan);
- if (chan->active_circuit_pqueue) {
- smartlist_free(chan->active_circuit_pqueue);
- chan->active_circuit_pqueue = NULL;
+ if (chan->cmux) {
+ circuitmux_detach_all_circuits(chan->cmux);
+ circuitmux_free(chan->cmux);
+ chan->cmux = NULL;
}
/* We're in CLOSED or ERROR, so the cell queue is already empty */
@@ -866,7 +868,6 @@ channel_force_free(channel_t *chan)
if (chan->free) chan->free(chan);
channel_clear_remote_end(chan);
- smartlist_free(chan->active_circuit_pqueue);
/* We might still have a cell queue; kill it */
if (chan->incoming_queue) {
@@ -2031,12 +2032,13 @@ channel_flush_some_cells(channel_t *chan, ssize_t num_cells)
(unlimited ? -1 : num_cells - flushed));
if (!unlimited && num_cells <= flushed) goto done;
- if (chan->active_circuits) {
+ if (circuitmux_num_cells(chan->cmux) > 0) {
/* Try to get more cells from any active circuits */
- num_cells_from_circs =
- channel_flush_from_first_active_circuit(chan,
- (unlimited ? MAX_CELLS_TO_GET_FROM_CIRCUITS_FOR_UNLIMITED :
- (num_cells - flushed)));
+ num_cells_from_circs = channel_flush_from_first_active_circuit(
+ chan,
+ (unlimited ?
+ MAX_CELLS_TO_GET_FROM_CIRCUITS_FOR_UNLIMITED :
+ (num_cells - flushed)));
/* If it claims we got some, process the queue again */
if (num_cells_from_circs > 0) {
@@ -2227,7 +2229,7 @@ channel_more_to_flush(channel_t *chan)
smartlist_len(chan->incoming_queue) > 0) return 1;
/* Check if any circuits would like to queue some */
- if (chan->active_circuits) return 1;
+ if (circuitmux_num_cells(chan->cmux) > 0) return 1;
/* Else no */
return 0;
@@ -2935,8 +2937,8 @@ channel_is_better(time_t now, channel_t *a, channel_t *b,
* one that has no circuits is in its grace period.
*/
- a_has_circs = (a->n_circuits > 0);
- b_has_circs = (b->n_circuits > 0);
+ a_has_circs = (channel_num_circuits(a) > 0);
+ b_has_circs = (channel_num_circuits(b) > 0);
a_grace = (forgive_new_connections &&
(now < channel_when_created(a) + NEW_CHAN_GRACE_PERIOD));
b_grace = (forgive_new_connections &&
@@ -3223,9 +3225,10 @@ channel_dump_statistics(channel_t *chan, int severity)
" * Channel " U64_FORMAT " has %d active circuits out of"
" %d in total",
U64_PRINTF_ARG(chan->global_identifier),
- (chan->active_circuit_pqueue != NULL) ?
- smartlist_len(chan->active_circuit_pqueue) : 0,
- chan->n_circuits);
+ (chan->cmux != NULL) ?
+ circuitmux_num_active_circuits(chan->cmux) : 0,
+ (chan->cmux != NULL) ?
+ circuitmux_num_circuits(chan->cmux) : 0);
/* Describe timestamps */
log(severity, LD_GENERAL,
@@ -4008,6 +4011,22 @@ channel_matches_target_addr_for_extend(channel_t *chan,
}
/**
+ * Return the total number of circuits used by a channel
+ *
+ * @param chan Channel to query
+ * @return Number of circuits using this as n_chan or p_chan
+ */
+
+unsigned int
+channel_num_circuits(channel_t *chan)
+{
+ tor_assert(chan);
+
+ return chan->num_n_circuits +
+ chan->num_p_circuits;
+}
+
+/**
* Set up circuit ID generation
*
* This is called when setting up a channel and replaces the old
diff --git a/src/or/channel.h b/src/or/channel.h
index 27fba8f..4d3db41 100644
--- a/src/or/channel.h
+++ b/src/or/channel.h
@@ -10,6 +10,7 @@
#define _TOR_CHANNEL_H
#include "or.h"
+#include "circuitmux.h"
/* Channel handler function pointer typedefs */
typedef void (*channel_listener_fn_ptr)(channel_listener_t *, channel_t *);
@@ -99,7 +100,7 @@ struct channel_s {
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 */
+ /* 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 *);
@@ -124,29 +125,8 @@ struct channel_s {
/* List of queued outgoing cells */
smartlist_t *outgoing_queue;
- /* Circuit stuff for use by relay.c */
-
- /*
- * Double-linked ring of circuits with queued cells waiting for room to
- * free up on this connection's outbuf. Every time we pull cells from
- * a circuit, we advance this pointer to the next circuit in the ring.
- */
- struct circuit_t *active_circuits;
- /*
- * Priority queue of cell_ewma_t for circuits with queued cells waiting
- * for room to free up on this connection's outbuf. Kept in heap order
- * according to EWMA.
- *
- * This is redundant with active_circuits; if we ever decide only to use
- * the cell_ewma algorithm for choosing circuits, we can remove
- * active_circuits.
- */
- smartlist_t *active_circuit_pqueue;
- /*
- * The tick on which the cell_ewma_ts in active_circuit_pqueue last had
- * their ewma values rescaled.
- */
- unsigned active_circuit_pqueue_last_recalibrated;
+ /* Circuit mux for circuits sending on this channel */
+ circuitmux_t *cmux;
/* Circuit ID generation stuff for use by circuitbuild.c */
@@ -161,8 +141,8 @@ struct channel_s {
*/
circid_t next_circ_id;
- /* How many circuits use this connection as p_chan or n_chan? */
- int n_circuits;
+ /* For how many circuits are we n_chan? What about p_chan? */
+ unsigned int num_n_circuits, num_p_circuits;
/*
* True iff this channel shouldn't get any new circs attached to it,
@@ -456,6 +436,7 @@ void channel_mark_client(channel_t *chan);
int channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info);
int channel_matches_target_addr_for_extend(channel_t *chan,
const tor_addr_t *target);
+unsigned int channel_num_circuits(channel_t *chan);
void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd);
void channel_timestamp_client(channel_t *chan);
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 5d6a7a9..036d14f 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -16,6 +16,7 @@
#include "or.h"
#include "channel.h"
#include "channeltls.h"
+#include "circuitmux.h"
#include "config.h"
#include "connection.h"
#include "connection_or.h"
@@ -127,8 +128,11 @@ 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->active_circuit_pqueue = smartlist_new();
- chan->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick();
+ chan->cmux = circuitmux_alloc();
+ /* TODO get rid of this and set policy once we have them
+ chan->cmux->active_circuit_pqueue_last_recalibrated =
+ cell_ewma_get_tick();
+ */
/* Set up or_connection stuff */
tlschan->conn = connection_or_connect(addr, port, id_digest, tlschan);
@@ -146,7 +150,7 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
goto done;
err:
- smartlist_free(chan->active_circuit_pqueue);
+ circuitmux_free(chan->cmux);
tor_free(tlschan);
chan = NULL;
@@ -260,8 +264,11 @@ 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->active_circuit_pqueue = smartlist_new();
- chan->active_circuit_pqueue_last_recalibrated = cell_ewma_get_tick();
+ chan->cmux = circuitmux_alloc();
+ /* TODO set cmux policy
+ chan->active_circuit_pqueue_last_recalibrated =
+ cell_ewma_get_tick();
+ */
/* If we got one, we should register it */
if (chan) channel_register(chan);
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index cf6020d..bec3dc8 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -134,10 +134,20 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
found = HT_REMOVE(chan_circid_map, &chan_circid_map, &search);
if (found) {
tor_free(found);
- --old_chan->n_circuits;
+ if (direction == CELL_DIRECTION_OUT) {
+ /* One fewer circuits use old_chan as n_chan */
+ --(old_chan->num_n_circuits);
+ } else {
+ /* One fewer circuits use old_chan as p_chan */
+ --(old_chan->num_p_circuits);
+ }
+ }
+
+ /* If we're changing channels, detach the circuit */
+ if (old_chan != chan) {
+ tor_assert(old_chan->cmux);
+ circuitmux_detach_circuit(old_chan->cmux, circ);
}
- if (was_active && old_chan != chan)
- make_circuit_inactive_on_chan(circ, old_chan);
}
/* Change the values only after we have possibly made the circuit inactive
@@ -161,10 +171,26 @@ circuit_set_circid_chan_helper(circuit_t *circ, int direction,
found->circuit = circ;
HT_INSERT(chan_circid_map, &chan_circid_map, found);
}
+
+ /* Attach to the circuitmux if we're changing channels */
+ if (old_chan != chan) {
+ tor_assert(chan->cmux);
+ circuitmux_attach_circuit(chan->cmux, circ, direction);
+ }
+
+ /*
+ * This is a no-op if we have no cells, but if we do it marks us active to
+ * the circuitmux
+ */
if (make_active && old_chan != chan)
- make_circuit_active_on_chan(circ,chan);
+ update_circuit_on_cmux(circ, direction);
- ++chan->n_circuits;
+ /* Adjust circuit counts on new channel */
+ if (direction == CELL_DIRECTION_OUT) {
+ ++chan->num_n_circuits;
+ } else {
+ ++chan->num_p_circuits;
+ }
}
/** Set the p_conn field of a circuit <b>circ</b>, along
@@ -994,7 +1020,7 @@ circuit_unlink_all_from_channel(channel_t *chan, int reason)
{
circuit_t *circ;
- channel_unlink_all_active_circs(chan);
+ channel_unlink_all_circuits(chan);
for (circ = global_circuitlist; circ; circ = circ->next) {
int mark = 0;
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index bf69711..f143e9b 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -336,7 +336,7 @@ connection_or_get_num_circuits(or_connection_t *conn)
tor_assert(conn);
if (conn->chan) {
- return TLS_CHAN_TO_BASE(conn->chan)->n_circuits;
+ return channel_num_circuits(TLS_CHAN_TO_BASE(conn->chan));
} else return 0;
}
diff --git a/src/or/or.h b/src/or/or.h
index 87ee7bb..a9b0361 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2634,8 +2634,6 @@ typedef struct circuit_t {
uint32_t magic; /**< For memory and type debugging: must equal
* ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
- /** Queue of cells waiting to be transmitted on n_conn. */
- cell_queue_t n_chan_cells;
/** The channel that is next in this circuit. */
channel_t *n_chan;
@@ -2643,13 +2641,36 @@ typedef struct circuit_t {
* The circuit_id used in the next (forward) hop of this circuit;
* this is unique to n_chan, but this ordered pair is globally
* unique:
+<<<<<<< HEAD
*
+=======
+ *
+>>>>>>> f1e8169... Use circuitmux_t in channels and when relaying cells
* (n_chan->global_identifier, n_circ_id)
*/
circid_t n_circ_id;
- /** The hop to which we want to extend this circuit. Should be NULL if
- * the circuit has attached to a connection. */
+ /**
+ * Circuit mux associated with n_chan to which this circuit is attached;
+ * NULL if we have no n_chan.
+ */
+ circuitmux_t *mux;
+
+ /** Queue of cells waiting to be transmitted on n_chan */
+ cell_queue_t n_chan_cells;
+
+ /**
+ * The hop to which we want to extend this circuit. Should be NULL if
+ * the circuit has attached to a connection.
+ *
+ * TODO:
+ * - If this is NULL, we have extended. Is it true that if this is
+ * NULL then n_chan is not NULL?
+ * - If n_chan is NULL, then what is n_circ_id?
+ * - It doesn't matter, because we'll only ever attach to a circuitmux_t
+ * when n_chan is not NULL, and that's what needs to use a unique ID
+ * for circuits.
+ */
extend_info_t *n_hop;
/** True iff we are waiting for n_chan_cells to become less full before
@@ -2701,6 +2722,15 @@ typedef struct circuit_t {
const char *marked_for_close_file; /**< For debugging: in which file was this
* circuit marked for close? */
+ /** Unique ID for measuring tunneled network status requests. */
+ uint64_t dirreq_id;
+
+ /** TODO is this *all* circuits or all circuits on n_chan? */
+ struct circuit_t *next; /**< Next circuit in linked list of all circuits. */
+
+ /** TODO all this from here on down should go away in favor of
+ * circuitmux_t.
+ */
/** Next circuit in the doubly-linked ring of circuits waiting to add
* cells to n_conn. NULL if we have no cells pending, or if we're not
* linked to an OR connection. */
@@ -2709,10 +2739,6 @@ typedef struct circuit_t {
* cells to n_conn. NULL if we have no cells pending, or if we're not
* linked to an OR connection. */
struct circuit_t *prev_active_on_n_chan;
- struct circuit_t *next; /**< Next circuit in linked list of all circuits. */
-
- /** Unique ID for measuring tunneled network status requests. */
- uint64_t dirreq_id;
/** The EWMA count for the number of cells flushed from the
* n_chan_cells queue. Used to determine which circuit to flush from next.
diff --git a/src/or/relay.c b/src/or/relay.c
index 60f696c..f079243 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1779,10 +1779,10 @@ circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint)
}
#ifdef ACTIVE_CIRCUITS_PARANOIA
-#define assert_active_circuits_ok_paranoid(conn) \
- assert_active_circuits_ok(conn)
+#define assert_cmux_ok_paranoid(chan) \
+ assert_cmux_okay(chan)
#else
-#define assert_active_circuits_ok_paranoid(conn)
+#define assert_cmux_ok_paranoid(chan)
#endif
/** The total number of cells we have allocated from the memory pool. */
@@ -2004,6 +2004,7 @@ prev_circ_on_chan_p(circuit_t *circ, channel_t *chan)
}
}
+#if 0
/** Helper for sorting cell_ewma_t values in their priority queue. */
static int
compare_cell_ewma_counts(const void *p1, const void *p2)
@@ -2240,122 +2241,61 @@ pop_first_cell_ewma_from_chan(channel_t *chan)
compare_cell_ewma_counts,
STRUCT_OFFSET(cell_ewma_t, heap_index));
}
+#endif
-/** Add <b>circ</b> to the list of circuits with pending cells on
- * <b>chan</b>. No effect if <b>circ</b> is already linked. */
+/**
+ * Update the number of cells available on the circuit's n_chan or p_chan's
+ * circuit mux.
+ */
void
-make_circuit_active_on_chan(circuit_t *circ, channel_t *chan)
+update_circuit_on_cmux(circuit_t *circ, cell_direction_t direction)
{
- circuit_t **nextp = NULL, **prevp = NULL;
+ channel_t *chan = NULL;
+ or_circuit_t *or_circ = NULL;
+ circuitmux_t *cmux = NULL;
- tor_assert(chan);
tor_assert(circ);
- nextp = next_circ_on_chan_p(circ, chan);
- prevp = prev_circ_on_chan_p(circ, chan);
-
- if (*nextp && *prevp) {
- /* Already active. */
- return;
- }
-
- assert_active_circuits_ok_paranoid(chan);
-
- if (!(chan->active_circuits)) {
- chan->active_circuits = circ;
- *prevp = *nextp = circ;
- } else {
- 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;
- *prev_circ_on_chan_p(head, chan) = circ;
- *prevp = old_tail;
- }
-
- if (circ->n_chan == chan) {
- add_cell_ewma_to_chan(chan, &circ->n_cell_ewma);
+ /* Okay, get the channel */
+ if (direction == CELL_DIRECTION_OUT) {
+ chan = circ->n_chan;
} else {
- or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
- tor_assert(chan == orcirc->p_chan);
- add_cell_ewma_to_chan(chan, &orcirc->p_cell_ewma);
+ or_circ = TO_OR_CIRCUIT(circ);
+ chan = or_circ->p_chan;
}
- assert_active_circuits_ok_paranoid(chan);
-}
-
-/** Remove <b>circ</b> from the list of circuits with pending cells on
- * <b>chan</b>. No effect if <b>circ</b> is already unlinked. */
-void
-make_circuit_inactive_on_chan(circuit_t *circ, channel_t *chan)
-{
- circuit_t **nextp = NULL, **prevp = NULL;
- circuit_t *next = NULL, *prev = NULL;
-
tor_assert(chan);
- tor_assert(circ);
+ tor_assert(chan->cmux);
- nextp = next_circ_on_chan_p(circ, chan);
- prevp = prev_circ_on_chan_p(circ, chan);
- next = *nextp;
- prev = *prevp;
+ /* Now get the cmux */
+ cmux = chan->cmux;
- if (!next && !prev) {
- /* Already inactive. */
- return;
- }
-
- assert_active_circuits_ok_paranoid(chan);
-
- tor_assert(next && prev);
- tor_assert(*prev_circ_on_chan_p(next, chan) == circ);
- tor_assert(*next_circ_on_chan_p(prev, chan) == circ);
+ /* Cmux sanity check */
+ tor_assert(circuitmux_is_circuit_attached(cmux, circ));
+ tor_assert(circuitmux_attached_circuit_direction(cmux, circ) == direction);
- if (next == circ) {
- chan->active_circuits = NULL;
- } else {
- *prev_circ_on_chan_p(next, chan) = prev;
- *next_circ_on_chan_p(prev, chan) = next;
- if (chan->active_circuits == circ)
- chan->active_circuits = next;
- }
- *prevp = *nextp = NULL;
+ assert_cmux_ok_paranoid(chan);
- if (circ->n_chan == chan) {
- remove_cell_ewma_from_chan(chan, &circ->n_cell_ewma);
+ /* Update the number of cells we have for the circuit mux */
+ if (direction == CELL_DIRECTION_OUT) {
+ circuitmux_set_num_cells(cmux, circ, circ->n_chan_cells.n);
} else {
- or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
- tor_assert(chan == orcirc->p_chan);
- remove_cell_ewma_from_chan(chan, &orcirc->p_cell_ewma);
+ circuitmux_set_num_cells(cmux, circ, or_circ->p_chan_cells.n);
}
- assert_active_circuits_ok_paranoid(chan);
+ assert_cmux_ok_paranoid(chan);
}
-/** Remove all circuits from the list of circuits with pending cells on
- * <b>chan</b>. */
+/** Remove all circuits from the cmux on <b>chan</b>. */
void
-channel_unlink_all_active_circs(channel_t *chan)
+channel_unlink_all_circuits(channel_t *chan)
{
- circuit_t *head = NULL, *cur = NULL;
-
tor_assert(chan);
+ tor_assert(chan->cmux);
- cur = head = chan->active_circuits;
- if (! head)
- return;
- do {
- circuit_t *next = *next_circ_on_chan_p(cur, chan);
- *prev_circ_on_chan_p(cur, chan) = NULL;
- *next_circ_on_chan_p(cur, chan) = NULL;
- cur = next;
- } while (cur != head);
- chan->active_circuits = NULL;
-
- SMARTLIST_FOREACH(chan->active_circuit_pqueue,
- cell_ewma_t *, e,
- e->heap_index = -1);
- smartlist_clear(chan->active_circuit_pqueue);
+ circuitmux_detach_all_circuits(chan->cmux);
+ chan->num_n_circuits = 0;
+ chan->num_p_circuits = 0;
}
/** Block (if <b>block</b> is true) or unblock (if <b>block</b> is false)
@@ -2419,53 +2359,71 @@ set_streams_blocked_on_circ(circuit_t *circ, channel_t *chan,
int
channel_flush_from_first_active_circuit(channel_t *chan, int max)
{
- int n_flushed;
+ circuitmux_t *cmux = NULL;
+ int n_flushed = 0;
cell_queue_t *queue;
circuit_t *circ;
+ or_circuit_t *or_circ;
int streams_blocked;
+ packed_cell_t *cell;
+#if 0
/* The current (hi-res) time */
struct timeval now_hires;
/* The EWMA cell counter for the circuit we're flushing. */
cell_ewma_t *cell_ewma = NULL;
double ewma_increment = -1;
+#endif
+ /* Get the cmux */
tor_assert(chan);
+ tor_assert(chan->cmux);
+ cmux = chan->cmux;
+
+ /* Main loop: pick a circuit, send a cell, update the cmux */
+ while (n_flushed < max) {
+ circ = circuitmux_get_first_active_circuit(cmux);
+ /* If it returns NULL, no cells left to send */
+ if (!circ) break;
+ assert_cmux_ok_paranoid(chan);
+
+#if 0
+ /* This will go in circuitmux_get_first_active_circuit() */
+ /* See if we're doing the ewma circuit selection algorithm. */
+ if (ewma_enabled) {
+ unsigned tick;
+ double fractional_tick;
+ tor_gettimeofday_cached(&now_hires);
+ tick = cell_ewma_tick_from_timeval(&now_hires, &fractional_tick);
+
+ if (tick != chan->active_circuit_pqueue_last_recalibrated) {
+ scale_active_circuits(chan, tick);
+ }
- circ = chan->active_circuits;
- if (!circ) return 0;
- assert_active_circuits_ok_paranoid(chan);
-
- /* See if we're doing the ewma circuit selection algorithm. */
- if (ewma_enabled) {
- unsigned tick;
- double fractional_tick;
- tor_gettimeofday_cached(&now_hires);
- tick = cell_ewma_tick_from_timeval(&now_hires, &fractional_tick);
+ ewma_increment = pow(ewma_scale_factor, -fractional_tick);
- if (tick != chan->active_circuit_pqueue_last_recalibrated) {
- scale_active_circuits(chan, tick);
+ cell_ewma = smartlist_get(chan->active_circuit_pqueue, 0);
+ circ = cell_ewma_to_circuit(cell_ewma);
}
+#endif
- ewma_increment = pow(ewma_scale_factor, -fractional_tick);
-
- cell_ewma = smartlist_get(chan->active_circuit_pqueue, 0);
- circ = cell_ewma_to_circuit(cell_ewma);
- }
-
- if (circ->n_chan == chan) {
- queue = &circ->n_chan_cells;
- streams_blocked = circ->streams_blocked_on_n_chan;
- } else {
- queue = &TO_OR_CIRCUIT(circ)->p_chan_cells;
- streams_blocked = circ->streams_blocked_on_p_chan;
- }
- tor_assert(*next_circ_on_chan_p(circ, chan));
+ if (circ->n_chan == chan) {
+ queue = &circ->n_chan_cells;
+ streams_blocked = circ->streams_blocked_on_n_chan;
+ } else {
+ or_circ = TO_OR_CIRCUIT(circ);
+ tor_assert(or_circ->p_chan == chan);
+ queue = &TO_OR_CIRCUIT(circ)->p_chan_cells;
+ streams_blocked = circ->streams_blocked_on_p_chan;
+ }
- for (n_flushed = 0; n_flushed < max && queue->head; ) {
- packed_cell_t *cell = cell_queue_pop(queue);
- tor_assert(*next_circ_on_chan_p(circ, chan));
+ /*
+ * Get just one cell here; once we've sent it, that can change the circuit
+ * selection, so we have to loop around for another even if this circuit
+ * has more than one.
+ */
+ cell = cell_queue_pop(queue);
/* Calculate the exact time that this cell has spent in the queue. */
if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
@@ -2481,8 +2439,8 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
"Looks like the CellStatistics option was "
"recently enabled.");
} else {
- or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
insertion_time_elem_t *elem = it_queue->first;
+ or_circ = TO_OR_CIRCUIT(circ);
cell_waiting_time =
(uint32_t)((flushed * 10L + SECONDS_IN_A_DAY * 1000L -
elem->insertion_time * 10L) %
@@ -2495,8 +2453,8 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
it_queue->last = NULL;
mp_pool_release(elem);
}
- orcirc->total_cell_waiting_time += cell_waiting_time;
- orcirc->processed_cells++;
+ or_circ->total_cell_waiting_time += cell_waiting_time;
+ or_circ->processed_cells++;
}
}
@@ -2507,14 +2465,34 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
DIRREQ_TUNNELED,
DIRREQ_CIRC_QUEUE_FLUSHED);
+ /* Now send the cell */
channel_write_packed_cell(chan, cell);
+ cell = NULL;
+
/*
* Don't packed_cell_free_unchecked(cell) here because the channel will
* do so when it gets out of the channel queue (probably already did, in
* which case that was an immediate double-free bug).
*/
+ /* Update the counter */
++n_flushed;
+
+ /*
+ * Now update the cmux; tell it we've just sent a cell, and how many
+ * we have left.
+ */
+ circuitmux_notify_xmit_cells(cmux, circ, 1);
+ circuitmux_set_num_cells(cmux, circ, queue->n);
+ if (queue->n == 0)
+ log_debug(LD_GENERAL, "Made a circuit inactive.");
+
+ /* Is the cell queue low enough to unblock all the streams that are waiting
+ * to write to this circuit? */
+ if (streams_blocked && queue->n <= CELL_QUEUE_LOWWATER_SIZE)
+ set_streams_blocked_on_circ(circ, chan, 0, 0); /* unblock streams */
+
+#if 0
if (cell_ewma) {
cell_ewma_t *tmp;
cell_ewma->cell_count += ewma_increment;
@@ -2534,22 +2512,13 @@ channel_flush_from_first_active_circuit(channel_t *chan, int max)
assert_active_circuits_ok_paranoid(chan);
goto done;
}
- }
- tor_assert(*next_circ_on_chan_p(circ, chan));
- assert_active_circuits_ok_paranoid(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? */
- if (streams_blocked && queue->n <= CELL_QUEUE_LOWWATER_SIZE)
- set_streams_blocked_on_circ(circ, chan, 0, 0); /* unblock streams */
+#endif
- /* Did we just run out of cells on this circuit's queue? */
- if (queue->n == 0) {
- log_debug(LD_GENERAL, "Made a circuit inactive.");
- make_circuit_inactive_on_chan(circ, chan);
+ /* If n_flushed < max still, loop around and pick another circuit */
}
- done:
+
+ /* Okay, we're done sending now */
+ assert_cmux_ok_paranoid(chan);
return n_flushed;
}
@@ -2587,11 +2556,11 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
set_streams_blocked_on_circ(circ, chan, 1, fromstream);
}
+ update_circuit_on_cmux(circ, direction);
if (queue->n == 1) {
- /* This was the first cell added to the queue. We need to make this
+ /* This was the first cell added to the queue. We just made this
* circuit active. */
log_debug(LD_GENERAL, "Made a circuit active.");
- make_circuit_active_on_chan(circ, chan);
}
if (!channel_has_queued_writes(chan)) {
@@ -2669,20 +2638,37 @@ void
circuit_clear_cell_queue(circuit_t *circ, channel_t *chan)
{
cell_queue_t *queue;
+ cell_direction_t direction;
+
if (circ->n_chan == chan) {
queue = &circ->n_chan_cells;
+ direction = CELL_DIRECTION_OUT;
} else {
or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
tor_assert(orcirc->p_chan == chan);
queue = &orcirc->p_chan_cells;
+ direction = CELL_DIRECTION_IN;
}
- if (queue->n)
- make_circuit_inactive_on_chan(circ, chan);
-
+ /* Clear the queue */
cell_queue_clear(queue);
+
+ /* Update the cell counter in the cmux */
+ update_circuit_on_cmux(circ, direction);
+}
+
+/** Fail with an assert if the circuit mux on chan is corrupt
+ */
+void
+assert_circuit_mux_okay(channel_t *chan)
+{
+ tor_assert(chan);
+ tor_assert(chan->cmux);
+
+ circuitmux_assert_okay(chan->cmux);
}
+#if 0
/** Fail with an assert if the active circuits ring on <b>orconn</b> is
* corrupt. */
void
@@ -2721,6 +2707,7 @@ assert_active_circuits_ok(channel_t *chan)
tor_assert(n == smartlist_len(chan->active_circuit_pqueue));
}
+#endif
/** Return 1 if we shouldn't restart reading on this circuit, even if
* we get a SENDME. Else return 0.
diff --git a/src/or/relay.h b/src/or/relay.h
index 7f96d59..ef5074b 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -51,11 +51,10 @@ void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell);
void append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
cell_t *cell, cell_direction_t direction,
streamid_t fromstream);
-void channel_unlink_all_active_circs(channel_t *chan);
+void channel_unlink_all_circuits(channel_t *chan);
int channel_flush_from_first_active_circuit(channel_t *chan, int max);
-void assert_active_circuits_ok(channel_t *chan);
-void make_circuit_inactive_on_chan(circuit_t *circ, channel_t *chan);
-void make_circuit_active_on_chan(circuit_t *circ, channel_t *chan);
+void assert_circuit_mux_okay(channel_t *chan);
+void update_circuit_on_cmux(circuit_t *circ, cell_direction_t direction);
int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr);
const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
1
0

[tor/master] Use cell_queue_entry_new/free() functions in channel.c
by andrea@torproject.org 11 Oct '12
by andrea@torproject.org 11 Oct '12
11 Oct '12
commit 1c3362dcdcf39f4b9da8c71567412349d111d08f
Author: Andrea Shepard <andrea(a)torproject.org>
Date: Tue Oct 9 11:35:08 2012 -0700
Use cell_queue_entry_new/free() functions in channel.c
---
src/or/channel.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 135 insertions(+), 22 deletions(-)
diff --git a/src/or/channel.c b/src/or/channel.c
index 278daa6..e87f4de 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -18,6 +18,7 @@
#include "channeltls.h"
#include "circuitbuild.h"
#include "circuitlist.h"
+#include "connection_or.h" /* For var_cell_free() */
#include "geoip.h"
#include "nodelist.h"
#include "relay.h"
@@ -80,7 +81,13 @@ static uint64_t n_channels_allocated = 0;
*/
static digestmap_t *channel_identity_map = NULL;
+static cell_queue_entry_t * cell_queue_entry_dup(cell_queue_entry_t *q);
+static void cell_queue_entry_free(cell_queue_entry_t *q, int handed_off);
static int cell_queue_entry_is_padding(cell_queue_entry_t *q);
+static cell_queue_entry_t *
+cell_queue_entry_new_fixed(cell_t *cell);
+static cell_queue_entry_t *
+cell_queue_entry_new_var(var_cell_t *var_cell);
/* Functions to maintain the digest map */
static void channel_add_to_digest_map(channel_t *chan);
@@ -865,7 +872,7 @@ channel_force_free(channel_t *chan)
if (chan->incoming_queue) {
SMARTLIST_FOREACH_BEGIN(chan->incoming_queue,
cell_queue_entry_t *, q) {
- tor_free(q);
+ cell_queue_entry_free(q, 0);
} SMARTLIST_FOREACH_END(q);
smartlist_free(chan->incoming_queue);
@@ -876,12 +883,7 @@ channel_force_free(channel_t *chan)
if (chan->outgoing_queue) {
SMARTLIST_FOREACH_BEGIN(chan->outgoing_queue,
cell_queue_entry_t *, q) {
- if (q->type == CELL_QUEUE_PACKED) {
- if (q->u.packed.packed_cell) {
- packed_cell_free(q->u.packed.packed_cell);
- }
- }
- tor_free(q);
+ cell_queue_entry_free(q, 0);
} SMARTLIST_FOREACH_END(q);
smartlist_free(chan->outgoing_queue);
@@ -1502,6 +1504,79 @@ channel_set_remote_end(channel_t *chan,
}
/**
+ * Duplicate a cell queue entry; this is a shallow copy intended for use
+ * in channel_write_cell_queue_entry().
+ */
+
+static cell_queue_entry_t *
+cell_queue_entry_dup(cell_queue_entry_t *q)
+{
+ cell_queue_entry_t *rv = NULL;
+
+ tor_assert(q);
+
+ rv = tor_malloc(sizeof(*rv));
+ memcpy(rv, q, sizeof(*rv));
+
+ return rv;
+}
+
+/**
+ * Free a cell_queue_entry_t; the handed_off parameter indicates whether
+ * the contents were passed to the lower layer (it is responsible for
+ * them) or not (we should free).
+ */
+
+static void
+cell_queue_entry_free(cell_queue_entry_t *q, int handed_off) {
+ if (!q) return;
+
+ if (!handed_off) {
+ /*
+ * If we handed it off, the recipient becomes responsible (or
+ * with packed cells the channel_t subclass calls packed_cell
+ * free after writing out its contents; see, e.g.,
+ * channel_tls_write_packed_cell_method(). Otherwise, we have
+ * to take care of it here if possible.
+ */
+ switch (q->type) {
+ case CELL_QUEUE_FIXED:
+ if (q->u.fixed.cell) {
+ /*
+ * There doesn't seem to be a cell_free() function anywhere in the
+ * pre-channel code; just use tor_free()
+ */
+ tor_free(q->u.fixed.cell);
+ }
+ break;
+ case CELL_QUEUE_PACKED:
+ if (q->u.packed.packed_cell) {
+ packed_cell_free(q->u.packed.packed_cell);
+ }
+ break;
+ case CELL_QUEUE_VAR:
+ if (q->u.var.var_cell) {
+ /*
+ * This one's in connection_or.c; it'd be nice to figure out the
+ * whole flow of cells from one end to the other and factor the
+ * cell memory management functions like this out of the specific
+ * TLS lower layer.
+ */
+ var_cell_free(q->u.var.var_cell);
+ }
+ break;
+ default:
+ /*
+ * Nothing we can do if we don't know the type; this will
+ * have been warned about elsewhere.
+ */
+ break;
+ }
+ }
+ tor_free(q);
+}
+
+/**
* Check whether a cell queue entry is padding; this is a helper function
* for channel_write_cell_queue_entry()
*/
@@ -1531,6 +1606,42 @@ cell_queue_entry_is_padding(cell_queue_entry_t *q)
}
/**
+ * Allocate a new cell queue entry for a fixed-size cell
+ */
+
+static cell_queue_entry_t *
+cell_queue_entry_new_fixed(cell_t *cell)
+{
+ cell_queue_entry_t *q = NULL;
+
+ tor_assert(cell);
+
+ q = tor_malloc(sizeof(*q));
+ q->type = CELL_QUEUE_FIXED;
+ q->u.fixed.cell = cell;
+
+ return q;
+}
+
+/**
+ * Allocate a new cell queue entry for a variable-size cell
+ */
+
+static cell_queue_entry_t *
+cell_queue_entry_new_var(var_cell_t *var_cell)
+{
+ cell_queue_entry_t *q = NULL;
+
+ tor_assert(var_cell);
+
+ q = tor_malloc(sizeof(*q));
+ q->type = CELL_QUEUE_VAR;
+ q->u.var.var_cell = var_cell;
+
+ return q;
+}
+
+/**
* Write to a channel based on a cell_queue_entry_t
*
* Given a cell_queue_entry_t filled out by the caller, try to send the cell
@@ -1601,8 +1712,7 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q)
* We have to copy the queue entry passed in, since the caller probably
* used the stack.
*/
- tmp = tor_malloc(sizeof(*tmp));
- memcpy(tmp, q, sizeof(*tmp));
+ tmp = cell_queue_entry_dup(q);
smartlist_add(chan->outgoing_queue, tmp);
/* Try to process the queue? */
if (chan->state == CHANNEL_STATE_OPEN) channel_flush_cells(chan);
@@ -1980,10 +2090,11 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
if (q->u.fixed.cell) {
if (chan->write_cell(chan,
q->u.fixed.cell)) {
- tor_free(q);
++flushed;
channel_timestamp_xmit(chan);
++(chan->n_cells_xmitted);
+ cell_queue_entry_free(q, 1);
+ q = NULL;
}
/* Else couldn't write it; leave it on the queue */
} else {
@@ -1994,17 +2105,19 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
"(global ID " U64_FORMAT ").",
chan, U64_PRINTF_ARG(chan->global_identifier));
/* Throw it away */
- tor_free(q);
+ cell_queue_entry_free(q, 0);
+ q = NULL;
}
break;
case CELL_QUEUE_PACKED:
if (q->u.packed.packed_cell) {
if (chan->write_packed_cell(chan,
q->u.packed.packed_cell)) {
- tor_free(q);
++flushed;
channel_timestamp_xmit(chan);
++(chan->n_cells_xmitted);
+ cell_queue_entry_free(q, 1);
+ q = NULL;
}
/* Else couldn't write it; leave it on the queue */
} else {
@@ -2015,17 +2128,19 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
"(global ID " U64_FORMAT ").",
chan, U64_PRINTF_ARG(chan->global_identifier));
/* Throw it away */
- tor_free(q);
+ cell_queue_entry_free(q, 0);
+ q = NULL;
}
break;
case CELL_QUEUE_VAR:
if (q->u.var.var_cell) {
if (chan->write_var_cell(chan,
q->u.var.var_cell)) {
- tor_free(q);
++flushed;
channel_timestamp_xmit(chan);
++(chan->n_cells_xmitted);
+ cell_queue_entry_free(q, 1);
+ q = NULL;
}
/* Else couldn't write it; leave it on the queue */
} else {
@@ -2036,7 +2151,8 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
"(global ID " U64_FORMAT ").",
chan, U64_PRINTF_ARG(chan->global_identifier));
/* Throw it away */
- tor_free(q);
+ cell_queue_entry_free(q, 0);
+ q = NULL;
}
break;
default:
@@ -2046,7 +2162,8 @@ channel_flush_some_cells_from_outgoing_queue(channel_t *chan,
"(global ID " U64_FORMAT "; ignoring it."
" Someone should fix this.",
q->type, chan, U64_PRINTF_ARG(chan->global_identifier));
- tor_free(q); /* tor_free() NULLs it out */
+ cell_queue_entry_free(q, 0);
+ q = NULL;
}
} else {
/* This shouldn't happen; log and throw it away */
@@ -2403,9 +2520,7 @@ channel_queue_cell(channel_t *chan, cell_t *cell)
} else {
/* Otherwise queue it and then process the queue if possible. */
tor_assert(chan->incoming_queue);
- q = tor_malloc(sizeof(*q));
- q->type = CELL_QUEUE_FIXED;
- q->u.fixed.cell = cell;
+ q = cell_queue_entry_new_fixed(cell);
log_debug(LD_CHANNEL,
"Queueing incoming cell_t %p for channel %p "
"(global ID " U64_FORMAT ")",
@@ -2465,9 +2580,7 @@ channel_queue_var_cell(channel_t *chan, var_cell_t *var_cell)
} else {
/* Otherwise queue it and then process the queue if possible. */
tor_assert(chan->incoming_queue);
- q = tor_malloc(sizeof(*q));
- q->type = CELL_QUEUE_VAR;
- q->u.var.var_cell = var_cell;
+ q = cell_queue_entry_new_var(var_cell);
log_debug(LD_CHANNEL,
"Queueing incoming var_cell_t %p for channel %p "
"(global ID " U64_FORMAT ")",
1
0
commit f00b44ef8c82eb52fad19fd2218f485f1c5aceca
Author: Andrea Shepard <andrea(a)torproject.org>
Date: Tue Oct 9 11:38:15 2012 -0700
Improve comments on channel_write_*()
---
src/or/channel.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/or/channel.c b/src/or/channel.c
index e87f4de..334f843 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -1723,7 +1723,9 @@ channel_write_cell_queue_entry(channel_t *chan, cell_queue_entry_t *q)
* Write a cell to a channel
*
* Write a fixed-length cell to a channel using the write_cell() method.
- * This is equivalent to the pre-channels connection_or_write_cell_to_buf().
+ * This is equivalent to the pre-channels connection_or_write_cell_to_buf();
+ * it is called by the transport-independent code to deliver a cell to a
+ * channel for transmission.
*/
void
@@ -1747,7 +1749,9 @@ channel_write_cell(channel_t *chan, cell_t *cell)
/**
* Write a packed cell to a channel
*
- * Write a packed cell to a channel using the write_cell() method.
+ * Write a packed cell to a channel using the write_cell() method. This is
+ * called by the transport-independent code to deliver a packed cell to a
+ * channel for transmission.
*/
void
@@ -1774,7 +1778,8 @@ channel_write_packed_cell(channel_t *chan, packed_cell_t *packed_cell)
*
* Write a variable-length cell to a channel using the write_cell() method.
* This is equivalent to the pre-channels
- * connection_or_write_var_cell_to_buf().
+ * connection_or_write_var_cell_to_buf(); it's called by the transport-
+ * independent code to deliver a var_cell to a channel for transmission.
*/
void
1
0
commit c684076fc7f685d6e0cd97f426d1474749f1da8b
Author: Andrea Shepard <andrea(a)torproject.org>
Date: Fri Sep 21 14:45:32 2012 -0700
Add circuitmux.c, circuitmux.h
---
src/or/Makefile.nmake | 12 ++++----
src/or/circuitmux.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++
src/or/circuitmux.h | 50 ++++++++++++++++++++++++++++++++++++
src/or/include.am | 2 +
src/or/or.h | 13 +++++++++-
5 files changed, 137 insertions(+), 7 deletions(-)
diff --git a/src/or/Makefile.nmake b/src/or/Makefile.nmake
index b145fdc..9f948d6 100644
--- a/src/or/Makefile.nmake
+++ b/src/or/Makefile.nmake
@@ -9,12 +9,12 @@ LIBS = ..\..\..\build-alpha\lib\libevent.a \
ws2_32.lib advapi32.lib shell32.lib
LIBTOR_OBJECTS = buffers.obj channel.obj channeltls.obj circuitbuild.obj \
- circuitlist.obj circuituse.obj command.obj config.obj connection.obj
- connection_edge.obj connection_or.obj control.obj cpuworker.obj \
- directory.obj dirserv.obj dirvote.obj dns.obj dnsserv.obj geoip.obj \
- hibernate.obj main.obj microdesc.obj networkstatus.obj \
- nodelist.obj onion.obj policies.obj reasons.obj relay.obj \
- rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \
+ circuitlist.obj circuitmux.obj circuituse.obj command.obj config.obj \
+ connection.obj connection_edge.obj connection_or.obj control.obj \
+ cpuworker.obj directory.obj dirserv.obj dirvote.obj dns.obj \
+ dnsserv.obj geoip.obj hibernate.obj main.obj microdesc.obj \
+ networkstatus.obj nodelist.obj onion.obj policies.obj reasons.obj \
+ relay.obj rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \
rephist.obj router.obj routerlist.obj routerparse.obj status.obj \
config_codedigest.obj ntmain.obj
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c
new file mode 100644
index 0000000..45b72f2
--- /dev/null
+++ b/src/or/circuitmux.c
@@ -0,0 +1,67 @@
+/* * Copyright (c) 2012, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file circuitmux.c
+ * \brief Circuit mux/cell selection abstraction
+ **/
+
+#include "or.h"
+#include "circuitmux.h"
+
+/*
+ * A circuitmux is a collection of circuits; it tracks which subset
+ * of the attached circuits are 'active' (i.e., have cells available
+ * to transmit) and how many cells on each. It expoes three distinct
+ * interfaces to other components:
+ *
+ * To channels, which each have a circuitmux_t, the supported operations
+ * are:
+ *
+ * circuitmux_flush_cells():
+ *
+ * Retrieve a cell from one of the active circuits, chosen according to
+ * the circuitmux_t's cell selection policy.
+ *
+ * circuitmux_unlink_all():
+ *
+ * The channel is closing down, all circuits must be detached.
+ *
+ * To circuits, the exposed operations are:
+ *
+ * TODO
+ *
+ * To circuit selection policies, the exposed operations are:
+ *
+ * TODO
+ *
+ * General status inquiries?
+ *
+ */
+
+struct circuitmux_s {
+ /*
+ * 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;
+};
+
diff --git a/src/or/circuitmux.h b/src/or/circuitmux.h
new file mode 100644
index 0000000..c5f9526
--- /dev/null
+++ b/src/or/circuitmux.h
@@ -0,0 +1,50 @@
+/* * Copyright (c) 2012, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file circuitmux.h
+ * \brief Header file for circuitmux.c
+ **/
+
+#ifndef _TOR_CIRCUITMUX_H
+#define _TOR_CIRCUITMUX_H
+
+#include "or.h"
+
+/* Consistency check */
+void circuitmux_assert_okay(circuitmux_t *cmux);
+
+/* Create/destroy */
+circuitmux_t * circuitmux_alloc(void);
+void circuitmux_detach_all_circuits(circuitmux_t *cmux);
+void circuitmux_free(circuitmux_t *cmux);
+
+/* Status inquiries */
+cell_direction_t circuitmux_attached_circuit_direction(
+ circuitmux_t *cmux,
+ circuit_t *circ);
+int circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ);
+int circuitmux_is_circuit_active(circuitmux_t *cmux, circuit_t *circ);
+unsigned int circuitmux_num_cells_for_circuit(circuitmux_t *cmux,
+ circuit_t *circ);
+unsigned int circuitmux_num_cells(circuitmux_t *cmux);
+unsigned int circuitmux_num_circuits(circuitmux_t *cmux);
+unsigned int circuitmux_num_active_circuits(circuitmux_t *cmux);
+
+/* Channel interface */
+circuit_t * circuitmux_get_first_active_circuit(circuitmux_t *cmux);
+void circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
+ unsigned int n_cells);
+
+/* Circuit interface */
+void circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ,
+ cell_direction_t direction);
+void circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ);
+void circuitmux_clear_num_cells(circuitmux_t *cmux, circuit_t *circ);
+void circuitmux_add_to_num_cells(circuitmux_t *cmux, circuit_t *circ,
+ unsigned int n_cells);
+void circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
+ unsigned int n_cells);
+
+#endif /* _TOR_CIRCUITMUX_H */
+
diff --git a/src/or/include.am b/src/or/include.am
index c323575..3ec94e5 100644
--- a/src/or/include.am
+++ b/src/or/include.am
@@ -21,6 +21,7 @@ src_or_libtor_a_SOURCES = \
src/or/channeltls.c \
src/or/circuitbuild.c \
src/or/circuitlist.c \
+ src/or/circuitmux.c \
src/or/circuituse.c \
src/or/command.c \
src/or/config.c \
@@ -92,6 +93,7 @@ ORHEADERS = \
src/or/channeltls.h \
src/or/circuitbuild.h \
src/or/circuitlist.h \
+ src/or/circuitmux.h \
src/or/circuituse.h \
src/or/command.h \
src/or/config.h \
diff --git a/src/or/or.h b/src/or/or.h
index 5987eef..87ee7bb 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1016,6 +1016,10 @@ typedef enum {
typedef struct channel_tls_s channel_tls_t;
+/* circuitmux_t typedef; struct circuitmux_s is in circuitmux.h */
+
+typedef struct circuitmux_s circuitmux_t;
+
/** Parsed onion routing cell. All communication between nodes
* is via cells. */
typedef struct cell_t {
@@ -2634,7 +2638,14 @@ typedef struct circuit_t {
cell_queue_t n_chan_cells;
/** The channel that is next in this circuit. */
channel_t *n_chan;
- /** The circuit_id used in the next (forward) hop of this circuit. */
+
+ /**
+ * The circuit_id used in the next (forward) hop of this circuit;
+ * this is unique to n_chan, but this ordered pair is globally
+ * unique:
+ *
+ * (n_chan->global_identifier, n_circ_id)
+ */
circid_t n_circ_id;
/** The hop to which we want to extend this circuit. Should be NULL if
1
0

[tor/master] Implement circuitmux_alloc()/circuitmux_free() and chanid/circid->muxinfo hash table
by andrea@torproject.org 11 Oct '12
by andrea@torproject.org 11 Oct '12
11 Oct '12
commit e4a11b890e7c5fe45dc1f5f271fbd8130ccc9c55
Author: Andrea Shepard <andrea(a)torproject.org>
Date: Mon Sep 24 08:52:05 2012 -0700
Implement circuitmux_alloc()/circuitmux_free() and chanid/circid->muxinfo hash table
---
src/or/circuitmux.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 143 insertions(+), 1 deletions(-)
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c
index 45b72f2..d4866ca 100644
--- a/src/or/circuitmux.c
+++ b/src/or/circuitmux.c
@@ -10,6 +10,33 @@
#include "circuitmux.h"
/*
+ * Private typedefs for circuitmux.c
+ */
+
+/*
+ * Map of muxinfos for circuitmux_t to use; struct is defined below (name
+ * of struct must match HT_HEAD line).
+ */
+typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t;
+
+/*
+ * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to
+ * break the hash table code).
+ */
+typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t;
+
+/*
+ * Anything the mux wants to store per-circuit in the map; right now just
+ * a count of queued cells.
+ */
+
+typedef struct circuit_muxinfo_s circuit_muxinfo_t;
+
+/*
+ * Structures for circuitmux.c
+ */
+
+/*
* A circuitmux is a collection of circuits; it tracks which subset
* of the attached circuits are 'active' (i.e., have cells available
* to transmit) and how many cells on each. It expoes three distinct
@@ -40,6 +67,14 @@
*/
struct circuitmux_s {
+ /* Keep count of attached, active circuits */
+ unsigned int n_circuits, n_active_circuits;
+
+ /*
+ * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
+ */
+ chanid_circid_muxinfo_map_t *chanid_circid_map;
+
/*
* 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
@@ -62,6 +97,113 @@ struct circuitmux_s {
* The tick on which the cell_ewma_ts in active_circuit_pqueue last had
* their ewma values rescaled.
*/
- unsigned active_circuit_pqueue_last_recalibrated;
+ unsigned int active_circuit_pqueue_last_recalibrated;
+};
+
+/*
+ * This struct holds whatever we want to store per attached circuit on a
+ * circuitmux_t; right now, just the count of queued cells.
+ */
+
+struct circuit_muxinfo_s {
+ unsigned int cell_count;
+};
+
+/*
+ * A map from channel ID and circuit ID to a circuit_muxinfo_t for that
+ * circuit.
+ */
+
+struct chanid_circid_muxinfo_t {
+ HT_ENTRY(chanid_circid_muxinfo_t) node;
+ uint64_t chan_id;
+ circid_t circ_id;
+ circuit_muxinfo_t muxinfo;
};
+/*
+ * Static function declarations
+ */
+
+static INLINE int
+chanid_circid_entries_eq(chanid_circid_muxinfo_t *a,
+ chanid_circid_muxinfo_t *b);
+static INLINE unsigned int
+chanid_circid_entry_hash(chanid_circid_muxinfo_t *a);
+
+/* Function definitions */
+
+/**
+ * Helper for chanid_circid_cell_count_map_t hash table: compare the channel
+ * ID and circuit ID for a and b, and return less than, equal to, or greater
+ * than zero appropriately.
+ */
+
+static INLINE int
+chanid_circid_entries_eq(chanid_circid_muxinfo_t *a,
+ chanid_circid_muxinfo_t *b)
+{
+ return a->chan_id == b->chan_id && a->circ_id == b->circ_id;
+}
+
+/**
+ * Helper: return a hash based on circuit ID and channel ID in a.
+ */
+
+static INLINE unsigned int
+chanid_circid_entry_hash(chanid_circid_muxinfo_t *a)
+{
+ return (((unsigned int)(a->circ_id) << 8) ^
+ ((unsigned int)((a->chan_id >> 32) & 0xffffffff)) ^
+ ((unsigned int)(a->chan_id & 0xffffffff)));
+}
+
+/* Declare the struct chanid_circid_muxinfo_map type */
+HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t);
+
+/* Emit a bunch of hash table stuff */
+HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
+ chanid_circid_entry_hash, chanid_circid_entries_eq);
+HT_GENERATE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
+ chanid_circid_entry_hash, chanid_circid_entries_eq, 0.6,
+ malloc, realloc, free);
+
+/**
+ * Allocate a new circuitmux_t
+ */
+
+circuitmux_t *
+circuitmux_alloc(void)
+{
+ circuitmux_t *rv = NULL;
+
+ rv = tor_malloc_zero(sizeof(*rv));
+ rv->chanid_circid_map = tor_malloc_zero(sizeof(*( rv->chanid_circid_map)));
+ HT_INIT(chanid_circid_muxinfo_map, rv->chanid_circid_map);
+
+ return rv;
+}
+
+/**
+ * Free a circuitmux_t; the circuits must be detached first with
+ * circuitmux_detach_all_circuits().
+ */
+
+void
+circuitmux_free(circuitmux_t *cmux)
+{
+ if (!cmux) return;
+
+ tor_assert(cmux->n_circuits == 0);
+ tor_assert(cmux->n_active_circuits == 0);
+
+ smartlist_free(cmux->active_circuit_pqueue);
+
+ if (cmux->chanid_circid_map) {
+ HT_CLEAR(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
+ tor_free(cmux->chanid_circid_map);
+ }
+
+ tor_free(cmux);
+}
+
1
0

[tor/master] Implement circuitmux_detach_circuit() in circuitmux.c
by andrea@torproject.org 11 Oct '12
by andrea@torproject.org 11 Oct '12
11 Oct '12
commit c3ebd0340cca67dc4dd44bd18849100ebba39051
Author: Andrea Shepard <andrea(a)torproject.org>
Date: Wed Sep 26 11:40:33 2012 -0700
Implement circuitmux_detach_circuit() in circuitmux.c
---
src/or/circuitmux.c | 98 +++++++++++++++-----------------------------------
1 files changed, 30 insertions(+), 68 deletions(-)
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c
index 629fbcf..2a7d075 100644
--- a/src/or/circuitmux.c
+++ b/src/or/circuitmux.c
@@ -443,98 +443,60 @@ circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ,
}
}
-/*
- * Circuitmux/circuit attachment status inquiry functions
- */
-
/**
- * Query the direction of an attached circuit
+ * Detach a circuit from a circuitmux and update all counters as needed;
+ * no-op if not attached.
*/
-cell_direction_t
-circuitmux_attached_circuit_direction(circuitmux_t *cmux, circuit_t *circ)
+void
+circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ)
{
- chanid_circid_muxinfo_t *hashent = NULL;
-
- /* Try to find a map entry */
- hashent = circuitmux_find_map_entry(cmux, circ);
-
+ chanid_circid_muxinfo_t search, *hashent = NULL;
/*
- * This function should only be called on attached circuits; assert that
- * we had a map entry.
+ * Use this to keep track of whether we found it for n_chan or
+ * p_chan for consistency checking.
*/
- tor_assert(hashent);
-
- /* Return the direction from the map entry */
- return hashent->muxinfo.direction;
-}
-
-/**
- * Find an entry in the cmux's map for this circuit or return NULL if there
- * is none.
- */
+ cell_direction_t last_searched_direction;
-static chanid_circid_muxinfo_t *
-circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ)
-{
- chanid_circid_muxinfo_t search, *hashent = NULL;
-
- /* Sanity-check parameters */
tor_assert(cmux);
tor_assert(cmux->chanid_circid_map);
tor_assert(circ);
tor_assert(circ->n_chan);
- /* Okay, let's see if it's attached for n_chan/n_circ_id */
+ /* See if we have it for n_chan/n_circ_id */
search.chan_id = circ->n_chan->global_identifier;
search.circ_id = circ->n_circ_id;
+ hashent = HT_REMOVE(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
+ &search);
+ last_searched_direction = CELL_DIRECTION_OUT;
- /* Query */
- hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
- &search);
-
- /* Found something? */
- if (hashent) {
- /*
- * Assert that the direction makes sense for a hashent we found by
- * n_chan/n_circ_id before we return it.
- */
- tor_assert(hashent->muxinfo.direction == CELL_DIRECTION_OUT);
- } else {
- /* Not there, have we got a p_chan/p_circ_id to try? */
+ /* Got one? If not, see if it's an or_circuit_t and try p_chan/p_circ_id */
+ if (!hashent) {
if (circ->magic == OR_CIRCUIT_MAGIC) {
search.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
- /* Check for p_chan */
if (TO_OR_CIRCUIT(circ)->p_chan) {
search.chan_id = TO_OR_CIRCUIT(circ)->p_chan->global_identifier;
- /* Okay, search for that */
- hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
- &search);
- /* Find anything? */
- if (hashent) {
- /* Assert that the direction makes sense before we return it */
- tor_assert(hashent->muxinfo.direction == CELL_DIRECTION_IN);
- }
+ hashent = HT_REMOVE(chanid_circid_muxinfo_map,
+ cmux->chanid_circid_map,
+ &search);
+ last_searched_direction = CELL_DIRECTION_IN;
}
}
}
- /* Okay, hashent is it if it was there */
- return hashent;
-}
-
-/**
- * Query whether a circuit is attached to a circuitmux
- */
-
-int
-circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ)
-{
- chanid_circid_muxinfo_t *hashent = NULL;
+ /* If hashent isn't NULL, we just removed it from the map */
+ if (hashent) {
+ /* Update counters */
+ --(cmux->n_circuits);
+ if (hashent->muxinfo.cell_count > 0) --(cmux->n_active_circuits);
+ cmux->n_cells -= hashent->muxinfo.cell_count;
+ /* TODO update active_circuits / active_circuit_pqueue */
- /* Look if it's in the circuit map */
- hashent = circuitmux_find_map_entry(cmux, circ);
+ /* Consistency check: the direction must match the direction searched */
+ tor_assert(last_searched_direction == hashent->muxinfo.direction);
- return (hashent != NULL);
+ /* Free the hash entry */
+ tor_free(hashent);
+ }
}
1
0