summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMatt Jordan <mjordan@digium.com>2015-05-05 13:13:10 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2015-05-05 13:13:10 -0500
commit2d9081b5ec8872102d7dd8169842725933eed7cf (patch)
tree1b1239e208068e37b60b203902ed1094bcf0135a /main
parent8ca25dfd7e9d3270ddaa02db9fce3ccbdcf1c3d5 (diff)
parent181ae3b8d929bd798a98b584868d1eac85b2eee9 (diff)
Merge "stasis: Fix dial masquerade datastore lifetime" into 13
Diffstat (limited to 'main')
-rw-r--r--main/stasis_channels.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/main/stasis_channels.c b/main/stasis_channels.c
index 9ed38c3ae..ae76c1e84 100644
--- a/main/stasis_channels.c
+++ b/main/stasis_channels.c
@@ -364,6 +364,7 @@ static void ast_channel_publish_dial_internal(struct ast_channel *caller,
}
static void remove_dial_masquerade(struct ast_channel *peer);
+static void remove_dial_masquerade_caller(struct ast_channel *caller);
static int set_dial_masquerade(struct ast_channel *caller,
struct ast_channel *peer, const char *dialstring);
@@ -373,6 +374,11 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_cha
{
ast_assert(peer != NULL);
+ /* XXX With an early bridge the below dial masquerade datastore code could, theoretically,
+ * go away as the act of changing the channel during dialing would be done using the bridge
+ * API itself and not a masquerade.
+ */
+
if (caller) {
/*
* Lock two or three channels.
@@ -407,6 +413,7 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_cha
ast_channel_unlock(forwarded);
}
ast_channel_unlock(peer);
+ remove_dial_masquerade_caller(caller);
ast_channel_unlock(caller);
}
}
@@ -1349,7 +1356,6 @@ static void dial_masquerade_datastore_cleanup(struct dial_masquerade_datastore *
while ((cur = AST_LIST_REMOVE_HEAD(&masq_data->dialed_peers, list))) {
dial_target_free(cur);
}
- masq_data->caller = ast_channel_cleanup(masq_data->caller);
}
static void dial_masquerade_datastore_remove_chan(struct dial_masquerade_datastore *masq_data, struct ast_channel *chan)
@@ -1399,6 +1405,16 @@ static void dial_masquerade_datastore_destroy(void *data)
ao2_ref(data, -1);
}
+/*!
+ * \internal
+ * \brief Datastore destructor for dial_masquerade_datastore
+ */
+static void dial_masquerade_caller_datastore_destroy(void *data)
+{
+ dial_masquerade_datastore_cleanup(data);
+ ao2_ref(data, -1);
+}
+
static struct ast_datastore *dial_masquerade_datastore_find(struct ast_channel *chan);
static void dial_masquerade_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
@@ -1517,6 +1533,13 @@ static const struct ast_datastore_info dial_masquerade_info = {
.chan_breakdown = dial_masquerade_breakdown,
};
+static const struct ast_datastore_info dial_masquerade_caller_info = {
+ .type = "stasis-chan-dial-masq",
+ .destroy = dial_masquerade_caller_datastore_destroy,
+ .chan_fixup = dial_masquerade_fixup,
+ .chan_breakdown = dial_masquerade_breakdown,
+};
+
/*!
* \internal
* \brief Find the dial masquerade datastore on the given channel.
@@ -1527,7 +1550,14 @@ static const struct ast_datastore_info dial_masquerade_info = {
*/
static struct ast_datastore *dial_masquerade_datastore_find(struct ast_channel *chan)
{
- return ast_channel_datastore_find(chan, &dial_masquerade_info, NULL);
+ struct ast_datastore *datastore;
+
+ datastore = ast_channel_datastore_find(chan, &dial_masquerade_info, NULL);
+ if (!datastore) {
+ datastore = ast_channel_datastore_find(chan, &dial_masquerade_caller_info, NULL);
+ }
+
+ return datastore;
}
/*!
@@ -1546,7 +1576,7 @@ static struct dial_masquerade_datastore *dial_masquerade_datastore_add(
{
struct ast_datastore *datastore;
- datastore = ast_datastore_alloc(&dial_masquerade_info, NULL);
+ datastore = ast_datastore_alloc(!masq_data ? &dial_masquerade_caller_info : &dial_masquerade_info, NULL);
if (!datastore) {
return NULL;
}
@@ -1557,7 +1587,7 @@ static struct dial_masquerade_datastore *dial_masquerade_datastore_add(
ast_datastore_free(datastore);
return NULL;
}
- masq_data->caller = ast_channel_ref(chan);
+ masq_data->caller = chan;
}
datastore->data = masq_data;
@@ -1663,3 +1693,24 @@ static void remove_dial_masquerade(struct ast_channel *peer)
ast_channel_datastore_remove(peer, datastore);
ast_datastore_free(datastore);
}
+
+static void remove_dial_masquerade_caller(struct ast_channel *caller)
+{
+ struct ast_datastore *datastore;
+ struct dial_masquerade_datastore *masq_data;
+
+ datastore = dial_masquerade_datastore_find(caller);
+ if (!datastore) {
+ return;
+ }
+
+ masq_data = datastore->data;
+ if (!masq_data || !AST_LIST_EMPTY(&masq_data->dialed_peers)) {
+ return;
+ }
+
+ dial_masquerade_datastore_remove_chan(masq_data, caller);
+
+ ast_channel_datastore_remove(caller, datastore);
+ ast_datastore_free(datastore);
+} \ No newline at end of file