diff options
Diffstat (limited to 'src/or/circuitmux.c')
-rw-r--r-- | src/or/circuitmux.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c index 860ba64e5d..5a5739fcd9 100644 --- a/src/or/circuitmux.c +++ b/src/or/circuitmux.c @@ -260,7 +260,10 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux) if (to_remove->muxinfo.direction == CELL_DIRECTION_OUT) { /* Clear n_mux */ circ->n_mux = NULL; - /* Update active_circuits et al. */ + /* + * Update active_circuits et al.; this does policy notifies, so + * comes before freeing policy data + */ circuitmux_make_circuit_inactive(cmux, circ, CELL_DIRECTION_OUT); } else if (circ->magic == OR_CIRCUIT_MAGIC) { /* @@ -268,7 +271,10 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux) * so clear p_mux. */ TO_OR_CIRCUIT(circ)->p_mux = NULL; - /* Update active_circuits et al. */ + /* + * Update active_circuits et al.; this does policy notifies, so + * comes before freeing policy data + */ circuitmux_make_circuit_inactive(cmux, circ, CELL_DIRECTION_IN); } else { /* Complain and move on */ @@ -278,6 +284,24 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux) to_remove->circ_id, U64_PRINTF_ARG(to_remove->chan_id)); } + + + /* Free policy-specific data if we have it */ + if (to_remove->muxinfo.policy_data) { + /* + * If we have policy data, assert that we have the means to + * free it + */ + tor_assert(cmux->policy); + tor_assert(cmux->policy_data); + tor_assert(cmux->policy->free_circ_data); + /* Call free_circ_data() */ + cmux->policy->free_circ_data(cmux, + cmux->policy_data, + circ, + to_remove->muxinfo.policy_data); + to_remove->muxinfo.policy_data = NULL; + } } else { /* Complain and move on */ log_warn(LD_CIRC, @@ -293,6 +317,9 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux) to_remove->circ_id); } + /* Assert that we don't have un-freed policy data for this circuit */ + tor_assert(to_remove->muxinfo.policy_data == NULL); + /* Free it */ tor_free(to_remove); } @@ -620,6 +647,18 @@ circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ, hashent->circ_id = circ_id; hashent->muxinfo.cell_count = cell_count; hashent->muxinfo.direction = direction; + /* Allocate policy specific circuit data if we need it */ + if (cmux->policy && cmux->policy_data && + cmux->policy->alloc_circ_data) { + hashent->muxinfo.policy_data = + cmux->policy->alloc_circ_data(cmux, + cmux->policy_data, + circ, + direction, + cell_count); + /* If we wanted policy data, it's an error not to get any */ + tor_assert(hashent->muxinfo.policy_data); + } HT_INSERT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, hashent); @@ -693,10 +732,25 @@ circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ) --(cmux->n_circuits); if (hashent->muxinfo.cell_count > 0) { --(cmux->n_active_circuits); + /* This does policy notifies, so comes before freeing policy data */ circuitmux_make_circuit_inactive(cmux, circ, last_searched_direction); } cmux->n_cells -= hashent->muxinfo.cell_count; + /* Free policy-specific data if we have it */ + if (hashent->muxinfo.policy_data) { + /* If we have policy data, assert that we have the means to free it */ + tor_assert(cmux->policy); + tor_assert(cmux->policy_data); + tor_assert(cmux->policy->free_circ_data); + /* Call free_circ_data() */ + cmux->policy->free_circ_data(cmux, + cmux->policy_data, + circ, + hashent->muxinfo.policy_data); + hashent->muxinfo.policy_data = NULL; + } + /* Consistency check: the direction must match the direction searched */ tor_assert(last_searched_direction == hashent->muxinfo.direction); /* Clear the circuit's mux for this direction */ |