diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c index c6402945c3..61fd30d752 100644 --- a/src/or/circuitmux.c +++ b/src/or/circuitmux.c @@ -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().