aboutsummaryrefslogtreecommitdiff
path: root/src/or/circuitmux.c
diff options
context:
space:
mode:
authorAndrea Shepard <andrea@torproject.org>2012-09-27 15:04:46 -0700
committerAndrea Shepard <andrea@torproject.org>2012-10-10 00:44:46 -0700
commitaff77eb1a9dcbdf723d3f8e74e6502e5047bbe63 (patch)
tree60506f01fd3b20f9c9dca7ad9cfa256956941442 /src/or/circuitmux.c
parentdebef8f0cd8fbe72fb40bd811c636bb66c7a9001 (diff)
downloadtor-aff77eb1a9dcbdf723d3f8e74e6502e5047bbe63.tar
tor-aff77eb1a9dcbdf723d3f8e74e6502e5047bbe63.tar.gz
Implement circuitmux_notify_xmit_cells() and circuitmux_move_active_circ_to_tail() helper in circuitmux.c
Diffstat (limited to 'src/or/circuitmux.c')
-rw-r--r--src/or/circuitmux.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c
index b5dda9e11..deb5bf12a 100644
--- a/src/or/circuitmux.c
+++ b/src/or/circuitmux.c
@@ -141,6 +141,9 @@ circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ,
static void
circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ,
cell_direction_t direction);
+static INLINE void
+circuitmux_move_active_circ_to_tail(circuitmux_t *cmux, circuit_t *circ,
+ cell_direction_t direction);
static INLINE circuit_t **
circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
static INLINE circuit_t **
@@ -152,6 +155,72 @@ circuitmux_prev_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
* Linked list helpers
*/
+static INLINE void
+circuitmux_move_active_circ_to_tail(circuitmux_t *cmux, circuit_t *circ,
+ cell_direction_t direction)
+{
+ circuit_t **next_p = NULL, **prev_p = NULL;
+ circuit_t **next_prev = NULL, **prev_next = NULL;
+ or_circuit_t *or_circ = NULL;
+
+ tor_assert(cmux);
+ tor_assert(circ);
+
+ /* Figure out our next_p and prev_p for this cmux/direction */
+ if (direction) {
+ if (direction == CELL_DIRECTION_OUT) {
+ tor_assert(circ->n_mux == cmux);
+ next_p = &(circ->next_active_on_n_chan);
+ prev_p = &(circ->prev_active_on_n_chan);
+ } else {
+ or_circ = TO_OR_CIRCUIT(circ);
+ tor_assert(or_circ->p_mux == cmux);
+ next_p = &(or_circ->next_active_on_p_chan);
+ prev_p = &(or_circ->prev_active_on_p_chan);
+ }
+ } else {
+ if (circ->n_mux == cmux) {
+ next_p = &(circ->next_active_on_n_chan);
+ prev_p = &(circ->prev_active_on_n_chan);
+ direction = CELL_DIRECTION_OUT;
+ } else {
+ or_circ = TO_OR_CIRCUIT(circ);
+ tor_assert(or_circ->p_mux == cmux);
+ next_p = &(or_circ->next_active_on_p_chan);
+ prev_p = &(or_circ->prev_active_on_p_chan);
+ direction = CELL_DIRECTION_IN;
+ }
+ }
+ tor_assert(next_p);
+ tor_assert(prev_p);
+
+ /* Check if this really is an active circuit */
+ if ((*next_p == NULL && *prev_p == NULL) &&
+ !(circ == cmux->active_circuits_head ||
+ circ == cmux->active_circuits_tail)) {
+ /* Not active, no-op */
+ return;
+ }
+
+ /* Check if this is already the tail */
+ if (circ == cmux->active_circuits_tail) return;
+
+ /* Okay, we have to move it; figure out next_prev and prev_next */
+ if (*next_p) next_prev = circuitmux_prev_active_circ_p(cmux, *next_p);
+ if (*prev_p) prev_next = circuitmux_next_active_circ_p(cmux, *prev_p);
+ /* Adjust the previous node's next pointer, if any */
+ if (prev_next) *prev_next = *next_p;
+ /* Otherwise, we were the head */
+ else cmux->active_circuits_head = *next_p;
+ /* Adjust the next node's previous pointer, if any */
+ if (next_prev) *next_prev = *prev_p;
+ /* Adjust our next and prev pointers */
+ *next_p = NULL;
+ *prev_p = cmux->active_circuits_tail;
+ /* Set the tail to this circuit */
+ cmux->active_circuits_tail = circ;
+}
+
static INLINE circuit_t **
circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ)
{
@@ -1175,3 +1244,67 @@ circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
hashent->muxinfo.cell_count = n_cells;
}
+/*
+ * Functions for channel code to call to get a circuit to transmit from or
+ * notify that cells have been transmitted.
+ */
+
+void
+circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
+ unsigned int n_cells)
+{
+ chanid_circid_muxinfo_t *hashent = NULL;
+ int becomes_inactive = 0;
+
+ tor_assert(cmux);
+ tor_assert(circ);
+
+ if (n_cells == 0) return;
+
+ /*
+ * To handle this, we have to:
+ *
+ * 1.) Adjust the circuit's cell counter in the cmux hash table
+ * 2.) Move the circuit to the tail of the active_circuits linked list
+ * for this cmux, or make the circuit inactive if the cell count
+ * went to zero.
+ * 3.) Call cmux->policy->notify_xmit_cells(), if any
+ */
+
+ /* Find the hash entry */
+ hashent = circuitmux_find_map_entry(cmux, circ);
+ /* Assert that we found one */
+ tor_assert(hashent);
+
+ /* Adjust the cell counter and assert that we had that many cells to send */
+ tor_assert(n_cells <= hashent->muxinfo.cell_count);
+ hashent->muxinfo.cell_count -= n_cells;
+ /* Do we need to make the circuit inactive? */
+ if (hashent->muxinfo.cell_count == 0) becomes_inactive = 1;
+
+ /* If we aren't making it inactive later, move it to the tail of the list */
+ if (!becomes_inactive) {
+ circuitmux_move_active_circ_to_tail(cmux, circ,
+ hashent->muxinfo.direction);
+ }
+
+ /*
+ * We call notify_xmit_cells() before making the circuit inactive if needed,
+ * so the policy can always count on this coming in on an active circuit.
+ */
+ if (cmux->policy && cmux->policy->notify_xmit_cells) {
+ cmux->policy->notify_xmit_cells(cmux, cmux->policy_data, circ,
+ hashent->muxinfo.policy_data,
+ n_cells);
+ }
+
+ /*
+ * Now make the circuit inactive if needed; this will call the policy's
+ * notify_circ_inactive() if present.
+ */
+ if (becomes_inactive) {
+ --(cmux->n_active_circuits);
+ circuitmux_make_circuit_inactive(cmux, circ, hashent->muxinfo.direction);
+ }
+}
+