|
@@ -8,6 +8,7 @@
|
|
|
|
|
|
#include "or.h"
|
|
|
#include "channel.h"
|
|
|
+#include "circuitlist.h"
|
|
|
#include "circuitmux.h"
|
|
|
|
|
|
/*
|
|
@@ -197,6 +198,74 @@ circuitmux_alloc(void)
|
|
|
return rv;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Detach all circuits from a circuitmux (use before circuitmux_free())
|
|
|
+ */
|
|
|
+
|
|
|
+void
|
|
|
+circuitmux_detach_all_circuits(circuitmux_t *cmux)
|
|
|
+{
|
|
|
+ chanid_circid_muxinfo_t **i = NULL, *to_remove;
|
|
|
+ channel_t *chan = NULL;
|
|
|
+ circuit_t *circ = NULL;
|
|
|
+
|
|
|
+ tor_assert(cmux);
|
|
|
+
|
|
|
+ i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
|
|
|
+ while (i) {
|
|
|
+ to_remove = *i;
|
|
|
+ i = HT_NEXT_RMV(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
|
|
|
+ if (to_remove) {
|
|
|
+ /* Find a channel and circuit */
|
|
|
+ chan = channel_find_by_global_id(to_remove->chan_id);
|
|
|
+ if (chan) {
|
|
|
+ circ = circuit_get_by_circid_channel(to_remove->circ_id, chan);
|
|
|
+ if (circ) {
|
|
|
+ /* Clear the circuit's mux for this direction */
|
|
|
+ if (to_remove->muxinfo.direction == CELL_DIRECTION_OUT) {
|
|
|
+ /* Clear n_mux */
|
|
|
+ circ->n_mux = NULL;
|
|
|
+ } else if (circ->magic == OR_CIRCUIT_MAGIC) {
|
|
|
+ /*
|
|
|
+ * It has a sensible p_chan and direction == CELL_DIRECTION_IN,
|
|
|
+ * so clear p_mux.
|
|
|
+ */
|
|
|
+ TO_OR_CIRCUIT(circ)->p_mux = NULL;
|
|
|
+ } else {
|
|
|
+ /* Complain and move on */
|
|
|
+ log_warn(LD_CIRC,
|
|
|
+ "Circuit %d/channel " U64_FORMAT " had direction == "
|
|
|
+ "CELL_DIRECTION_IN, but isn't an or_circuit_t",
|
|
|
+ to_remove->circ_id,
|
|
|
+ U64_PRINTF_ARG(to_remove->chan_id));
|
|
|
+ }
|
|
|
+
|
|
|
+ /* TODO update active_circuits / active_circuit_pqueue */
|
|
|
+ } else {
|
|
|
+ /* Complain and move on */
|
|
|
+ log_warn(LD_CIRC,
|
|
|
+ "Couldn't find circuit %d (for channel " U64_FORMAT ")",
|
|
|
+ to_remove->circ_id,
|
|
|
+ U64_PRINTF_ARG(to_remove->chan_id));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /* Complain and move on */
|
|
|
+ log_warn(LD_CIRC,
|
|
|
+ "Couldn't find channel " U64_FORMAT " (for circuit id %d)",
|
|
|
+ U64_PRINTF_ARG(to_remove->chan_id),
|
|
|
+ to_remove->circ_id);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Free it */
|
|
|
+ tor_free(to_remove);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cmux->n_circuits = 0;
|
|
|
+ cmux->n_active_circuits = 0;
|
|
|
+ cmux->n_cells = 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Free a circuitmux_t; the circuits must be detached first with
|
|
|
* circuitmux_detach_all_circuits().
|