aboutsummaryrefslogtreecommitdiff
path: root/src/or/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/channel.c')
-rw-r--r--src/or/channel.c84
1 files changed, 74 insertions, 10 deletions
diff --git a/src/or/channel.c b/src/or/channel.c
index 7f3c6f5868..cd5972f1ec 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -11,15 +11,17 @@
* should touch.
*/
-#define _TOR_CHANNEL_INTERNAL
+#define TOR_CHANNEL_INTERNAL_
#include "or.h"
#include "channel.h"
#include "channeltls.h"
#include "circuitbuild.h"
#include "circuitlist.h"
+#include "circuitstats.h"
#include "connection_or.h" /* For var_cell_free() */
#include "circuitmux.h"
+#include "entrynodes.h"
#include "geoip.h"
#include "nodelist.h"
#include "relay.h"
@@ -111,7 +113,7 @@ channel_idmap_eq(const channel_idmap_entry_t *a,
HT_PROTOTYPE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash,
channel_idmap_eq);
HT_GENERATE(channel_idmap, channel_idmap_entry_s, node, channel_idmap_hash,
- channel_idmap_eq, 0.5, tor_malloc, tor_realloc, _tor_free);
+ channel_idmap_eq, 0.5, tor_malloc, tor_realloc, tor_free_);
static cell_queue_entry_t * cell_queue_entry_dup(cell_queue_entry_t *q);
static void cell_queue_entry_free(cell_queue_entry_t *q, int handed_off);
@@ -779,11 +781,24 @@ channel_free(channel_t *chan)
/* It must be deregistered */
tor_assert(!(chan->registered));
+ log_debug(LD_CHANNEL,
+ "Freeing channel " U64_FORMAT " at %p",
+ U64_PRINTF_ARG(chan->global_identifier), chan);
+
+ /*
+ * Get rid of cmux policy before we do anything, so cmux policies don't
+ * see channels in weird half-freed states.
+ */
+ if (chan->cmux) {
+ circuitmux_set_policy(chan->cmux, NULL);
+ }
+
/* Call a free method if there is one */
if (chan->free) chan->free(chan);
channel_clear_remote_end(chan);
+ /* Get rid of cmux */
if (chan->cmux) {
circuitmux_detach_all_circuits(chan->cmux);
circuitmux_free(chan->cmux);
@@ -806,6 +821,11 @@ channel_listener_free(channel_listener_t *chan_l)
{
if (!chan_l) return;
+ log_debug(LD_CHANNEL,
+ "Freeing channel_listener_t " U64_FORMAT " at %p",
+ U64_PRINTF_ARG(chan_l->global_identifier),
+ chan_l);
+
/* It must be closed or errored */
tor_assert(chan_l->state == CHANNEL_LISTENER_STATE_CLOSED ||
chan_l->state == CHANNEL_LISTENER_STATE_ERROR);
@@ -835,11 +855,29 @@ channel_force_free(channel_t *chan)
cell_queue_entry_t *cell, *cell_tmp;
tor_assert(chan);
+ log_debug(LD_CHANNEL,
+ "Force-freeing channel " U64_FORMAT " at %p",
+ U64_PRINTF_ARG(chan->global_identifier), chan);
+
+ /*
+ * Get rid of cmux policy before we do anything, so cmux policies don't
+ * see channels in weird half-freed states.
+ */
+ if (chan->cmux) {
+ circuitmux_set_policy(chan->cmux, NULL);
+ }
+
/* Call a free method if there is one */
if (chan->free) chan->free(chan);
channel_clear_remote_end(chan);
+ /* Get rid of cmux */
+ if (chan->cmux) {
+ circuitmux_free(chan->cmux);
+ chan->cmux = NULL;
+ }
+
/* We might still have a cell queue; kill it */
SIMPLEQ_FOREACH_SAFE(cell, &chan->incoming_queue, next, cell_tmp) {
cell_queue_entry_free(cell, 0);
@@ -866,6 +904,11 @@ channel_listener_force_free(channel_listener_t *chan_l)
{
tor_assert(chan_l);
+ log_debug(LD_CHANNEL,
+ "Force-freeing channel_listener_t " U64_FORMAT " at %p",
+ U64_PRINTF_ARG(chan_l->global_identifier),
+ chan_l);
+
/* Call a free method if there is one */
if (chan_l->free) chan_l->free(chan_l);
@@ -3122,6 +3165,7 @@ channel_dump_statistics(channel_t *chan, int severity)
/* Handle remote address and descriptions */
have_remote_addr = channel_get_addr_if_possible(chan, &remote_addr);
if (have_remote_addr) {
+ char *actual = tor_strdup(channel_get_actual_remote_descr(chan));
remote_addr_str = tor_dup_addr(&remote_addr);
log(severity, LD_GENERAL,
" * Channel " U64_FORMAT " says its remote address"
@@ -3130,16 +3174,19 @@ channel_dump_statistics(channel_t *chan, int severity)
U64_PRINTF_ARG(chan->global_identifier),
remote_addr_str,
channel_get_canonical_remote_descr(chan),
- channel_get_actual_remote_descr(chan));
+ actual);
tor_free(remote_addr_str);
+ tor_free(actual);
} else {
+ char *actual = tor_strdup(channel_get_actual_remote_descr(chan));
log(severity, LD_GENERAL,
" * Channel " U64_FORMAT " does not know its remote "
"address, but gives a canonical description of \"%s\" and an "
"actual description of \"%s\"",
U64_PRINTF_ARG(chan->global_identifier),
channel_get_canonical_remote_descr(chan),
- channel_get_actual_remote_descr(chan));
+ actual);
+ tor_free(actual);
}
/* Handle marks */
@@ -3352,8 +3399,10 @@ channel_listener_dump_transport_statistics(channel_listener_t *chan_l,
* This function return a test provided by the lower layer of the remote
* endpoint for this channel; it should specify the actual address connected
* to/from.
+ *
+ * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr}
+ * may invalidate the return value from this function.
*/
-
const char *
channel_get_actual_remote_descr(channel_t *chan)
{
@@ -3361,7 +3410,20 @@ channel_get_actual_remote_descr(channel_t *chan)
tor_assert(chan->get_remote_descr);
/* Param 1 indicates the actual description */
- return chan->get_remote_descr(chan, 1);
+ return chan->get_remote_descr(chan, GRD_FLAG_ORIGINAL);
+}
+
+/**
+ * Return the text address of the remote endpoint.
+ *
+ * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr}
+ * may invalidate the return value from this function.
+ */
+const char *
+channel_get_actual_remote_address(channel_t *chan)
+{
+ /* Param 1 indicates the actual description */
+ return chan->get_remote_descr(chan, GRD_FLAG_ORIGINAL|GRD_FLAG_ADDR_ONLY);
}
/**
@@ -3370,8 +3432,10 @@ channel_get_actual_remote_descr(channel_t *chan)
* This function return a test provided by the lower layer of the remote
* endpoint for this channel; it should use the known canonical address for
* this OR's identity digest if possible.
+ *
+ * Subsequent calls to channel_get_{actual,canonical}_remote_{address,descr}
+ * may invalidate the return value from this function.
*/
-
const char *
channel_get_canonical_remote_descr(channel_t *chan)
{
@@ -3383,12 +3447,12 @@ channel_get_canonical_remote_descr(channel_t *chan)
}
/**
- * Get remote address if possible
+ * Get remote address if possible.
*
* Write the remote address out to a tor_addr_t if the underlying transport
- * supports this operation.
+ * supports this operation, and return 1. Return 0 if the underlying transport
+ * doesn't let us do this.
*/
-
int
channel_get_addr_if_possible(channel_t *chan, tor_addr_t *addr_out)
{