[tor-commits] [tor/master] Implement circuitmux_clear_policy(), circuitmux_get_policy() and circuitmux_set_policy() in circuitmux.c

andrea at torproject.org andrea at torproject.org
Thu Oct 11 02:05:23 UTC 2012


commit 86d9d85dfc177b7a24051f64a5c35997de5c9ac9
Author: Andrea Shepard <andrea at torproject.org>
Date:   Thu Sep 27 13:42:47 2012 -0700

    Implement circuitmux_clear_policy(), circuitmux_get_policy() and circuitmux_set_policy() in circuitmux.c
---
 src/or/circuitmux.c |  159 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 158 insertions(+), 1 deletions(-)

diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c
index 53d3a1b..4e33569 100644
--- a/src/or/circuitmux.c
+++ b/src/or/circuitmux.c
@@ -343,7 +343,13 @@ circuitmux_free(circuitmux_t *cmux)
   tor_assert(cmux->n_circuits == 0);
   tor_assert(cmux->n_active_circuits == 0);
 
-  /* Free policy-specific data if we have any */
+  /*
+   * Free policy-specific data if we have any; we don't
+   * need to do circuitmux_set_policy(cmux, NULL) to cover
+   * the circuits because they would have been handled in
+   * circuitmux_detach_all_circuits() before this was
+   * called.
+   */
   if (cmux->policy && cmux->policy->free_cmux_data) {
     if (cmux->policy_data) {
       cmux->policy->free_cmux_data(cmux, cmux->policy_data);
@@ -360,6 +366,157 @@ circuitmux_free(circuitmux_t *cmux)
 }
 
 /*
+ * Circuitmux policy control functions
+ */
+
+/**
+ * Remove any policy installed on cmux; all policy data will be freed and
+ * cmux behavior will revert to the built-in round-robin active_circuits
+ * mechanism.
+ */
+
+void
+circuitmux_clear_policy(circuitmux_t *cmux)
+{
+  tor_assert(cmux);
+
+  /* Internally, this is just setting policy to NULL */
+  if (cmux->policy) {
+    circuitmux_set_policy(cmux, NULL);
+  }
+}
+
+/**
+ * Return the policy currently installed on a circuitmux_t
+ */
+
+const circuitmux_policy_t *
+circuitmux_get_policy(circuitmux_t *cmux)
+{
+  tor_assert(cmux);
+
+  return cmux->policy;
+}
+
+/**
+ * Set policy; allocate for new policy, detach all circuits from old policy
+ * if any, attach them to new policy, and free old policy data.
+ */
+
+void
+circuitmux_set_policy(circuitmux_t *cmux,
+                      const circuitmux_policy_t *pol)
+{
+  const circuitmux_policy_t *old_pol = NULL, *new_pol = NULL;
+  circuitmux_policy_data_t *old_pol_data = NULL, *new_pol_data = NULL;
+  chanid_circid_muxinfo_t **i = NULL;
+  channel_t *chan = NULL;
+  uint64_t last_chan_id_searched = 0;
+  circuit_t *circ = NULL;
+
+  tor_assert(cmux);
+
+  /* Set up variables */
+  old_pol = cmux->policy;
+  old_pol_data = cmux->policy_data;
+  new_pol = pol;
+
+  /* Check if this is the trivial case */
+  if (old_pol == new_pol) return;
+
+  /* Allocate data for new policy, if any */
+  if (new_pol && new_pol->alloc_cmux_data) {
+    /*
+     * If alloc_cmux_data is not null, then we expect to get some policy
+     * data.  Assert that we also have free_cmux_data so we can free it
+     * when the time comes, and allocate it.
+     */
+    tor_assert(new_pol->free_cmux_data);
+    new_pol_data = new_pol->alloc_cmux_data(cmux);
+    tor_assert(new_pol_data);
+  }
+
+  /* Install new policy and new policy data on cmux */
+  cmux->policy = new_pol;
+  cmux->policy_data = new_pol_data;
+
+  /* Iterate over all circuits, attaching/detaching each one */
+  i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
+  while (i) {
+    /* Assert that this entry isn't NULL */
+    tor_assert(*i);
+
+    /*
+     * Get the channel; since normal case is all circuits on the mux share a
+     * channel, we cache last_chan_id_searched
+     */
+    if (!chan || last_chan_id_searched != (*i)->chan_id) {
+      chan = channel_find_by_global_id((*i)->chan_id);
+      last_chan_id_searched = (*i)->chan_id;
+    }
+    tor_assert(chan);
+
+    /* Get the circuit */
+    circ = circuit_get_by_circid_channel((*i)->circ_id, chan);
+    tor_assert(circ);
+
+    /* Need to tell old policy it becomes inactive (i.e., it is active) ? */
+    if (old_pol && old_pol->notify_circ_inactive &&
+        (*i)->muxinfo.cell_count > 0) {
+      old_pol->notify_circ_inactive(cmux, old_pol_data, circ,
+                                    (*i)->muxinfo.policy_data);
+    }
+
+    /* Need to free old policy data? */
+    if ((*i)->muxinfo.policy_data) {
+      /* Assert that we have the means to free it if we have policy data */
+      tor_assert(old_pol);
+      tor_assert(old_pol->free_circ_data);
+      /* Free it */
+      old_pol->free_circ_data(cmux, old_pol_data, circ,
+                             (*i)->muxinfo.policy_data);
+      (*i)->muxinfo.policy_data = NULL;
+    }
+
+    /* Need to allocate new policy data? */
+    if (new_pol && new_pol->alloc_circ_data) {
+      /*
+       * If alloc_circ_data is not null, we expect to get some per-circuit
+       * policy data.  Assert that we also have free_circ_data so we can
+       * free it when the time comes, and allocate it.
+       */
+      tor_assert(new_pol->free_circ_data);
+      (*i)->muxinfo.policy_data =
+        new_pol->alloc_circ_data(cmux, new_pol_data, circ,
+                                 (*i)->muxinfo.direction,
+                                 (*i)->muxinfo.cell_count);
+    }
+
+    /* Need to make active on new policy? */
+    if (new_pol && new_pol->notify_circ_active &&
+        (*i)->muxinfo.cell_count > 0) {
+      new_pol->notify_circ_active(cmux, new_pol_data, circ,
+                                  (*i)->muxinfo.policy_data);
+    }
+
+    /* Advance to next circuit map entry */
+    i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
+  }
+
+  /* Free data for old policy, if any */
+  if (old_pol_data) {
+    /*
+     * If we had old policy data, we should have an old policy and a free
+     * function for it.
+     */
+    tor_assert(old_pol);
+    tor_assert(old_pol->free_cmux_data);
+    old_pol->free_cmux_data(cmux, old_pol_data);
+    old_pol_data = NULL;
+  }
+}
+
+/*
  * Circuitmux/circuit attachment status inquiry functions
  */
 





More information about the tor-commits mailing list