summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJonathan Rose <jrose@digium.com>2014-07-18 16:28:10 +0000
committerJonathan Rose <jrose@digium.com>2014-07-18 16:28:10 +0000
commitaf4cd651431b5a2a0dadebf4331be4fe61389e1b (patch)
tree989983f58c5a8ebca0b7588c9592a87f26db23db /main
parent5c988cc4e6c5693f03080f88e3057cb7a5358597 (diff)
Channels: Masquerades to automatically move frame/audio hooks
Whenever possible, audiohooks and framehooks will now be copied over to the channel that the masquerading channel gets cloned into. This should occur for all audiohooks and most framehooks. As a result, in Asterisk 12.5 and up, the AUDIOHOOK_INHERIT function is now deprecated and its behavior is essentially the new default for all audiohooks, plus some additional audiohooks/framehooks. Review: https://reviewboard.asterisk.org/r/3721/ ........ Merged revisions 418914 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@418936 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/audiohook.c49
-rw-r--r--main/bridge_basic.c1
-rw-r--r--main/channel.c14
-rw-r--r--main/framehook.c53
4 files changed, 107 insertions, 10 deletions
diff --git a/main/audiohook.c b/main/audiohook.c
index 4dc7c136b..549ad31eb 100644
--- a/main/audiohook.c
+++ b/main/audiohook.c
@@ -586,15 +586,10 @@ static struct ast_audiohook *find_audiohook_by_source(struct ast_audiohook_list
return NULL;
}
-void ast_audiohook_move_by_source(struct ast_channel *old_chan, struct ast_channel *new_chan, const char *source)
+static void audiohook_move(struct ast_channel *old_chan, struct ast_channel *new_chan, struct ast_audiohook *audiohook)
{
- struct ast_audiohook *audiohook;
enum ast_audiohook_status oldstatus;
- if (!ast_channel_audiohooks(old_chan) || !(audiohook = find_audiohook_by_source(ast_channel_audiohooks(old_chan), source))) {
- return;
- }
-
/* By locking both channels and the audiohook, we can assure that
* another thread will not have a chance to read the audiohook's status
* as done, even though ast_audiohook_remove signals the trigger
@@ -610,6 +605,48 @@ void ast_audiohook_move_by_source(struct ast_channel *old_chan, struct ast_chann
ast_audiohook_unlock(audiohook);
}
+void ast_audiohook_move_by_source(struct ast_channel *old_chan, struct ast_channel *new_chan, const char *source)
+{
+ struct ast_audiohook *audiohook;
+
+ if (!ast_channel_audiohooks(old_chan)) {
+ return;
+ }
+
+ audiohook = find_audiohook_by_source(ast_channel_audiohooks(old_chan), source);
+ if (!audiohook) {
+ return;
+ }
+
+ audiohook_move(old_chan, new_chan, audiohook);
+}
+
+void ast_audiohook_move_all(struct ast_channel *old_chan, struct ast_channel *new_chan)
+{
+ struct ast_audiohook *audiohook;
+ struct ast_audiohook_list *audiohook_list;
+
+ audiohook_list = ast_channel_audiohooks(old_chan);
+ if (!audiohook_list) {
+ return;
+ }
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
+ audiohook_move(old_chan, new_chan, audiohook);
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
+ audiohook_move(old_chan, new_chan, audiohook);
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
+ audiohook_move(old_chan, new_chan, audiohook);
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+}
+
/*! \brief Detach specified source audiohook from channel
* \param chan Channel to detach from
* \param source Name of source to detach
diff --git a/main/bridge_basic.c b/main/bridge_basic.c
index eb44867f1..60ce37a98 100644
--- a/main/bridge_basic.c
+++ b/main/bridge_basic.c
@@ -2858,6 +2858,7 @@ static int attach_framehook(struct attended_transfer_properties *props, struct a
.event_cb = transfer_target_framehook_cb,
.destroy_cb = transfer_target_framehook_destroy_cb,
.consume_cb = transfer_target_framehook_consume,
+ .disable_inheritance = 1,
};
ao2_ref(props, +1);
diff --git a/main/channel.c b/main/channel.c
index 7d9f04837..15f2cbce0 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -6578,6 +6578,12 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
AST_LIST_APPEND_LIST(ast_channel_datastores(original), ast_channel_datastores(clonechan), entry);
}
+ /* Move framehooks over */
+ ast_framehook_list_fixup(clonechan, original);
+
+ /* Move audiohooks over */
+ ast_audiohook_move_all(clonechan, original);
+
ast_autochan_new_channel(clonechan, original);
clone_variables(original, clonechan);
@@ -10295,6 +10301,13 @@ struct suppress_data {
int framehook_id;
};
+static void suppress_framehook_fixup_cb(void *data, int framehook_id, struct ast_channel *old_chan, struct ast_channel *new_chan)
+{
+ struct suppress_data *suppress = data;
+
+ suppress->framehook_id = framehook_id;
+}
+
static struct ast_frame *suppress_framehook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
{
struct suppress_data *suppress = data;
@@ -10346,6 +10359,7 @@ int ast_channel_suppress(struct ast_channel *chan, unsigned int direction, enum
.version = AST_FRAMEHOOK_INTERFACE_VERSION,
.event_cb = suppress_framehook_event_cb,
.destroy_cb = suppress_framehook_destroy_cb,
+ .chan_fixup_cb = suppress_framehook_fixup_cb,
};
int framehook_id;
diff --git a/main/framehook.c b/main/framehook.c
index 84719ef49..0d42b4990 100644
--- a/main/framehook.c
+++ b/main/framehook.c
@@ -56,7 +56,16 @@ struct ast_framehook_list {
AST_LIST_HEAD_NOLOCK(, ast_framehook) list;
};
-static void framehook_detach_and_destroy(struct ast_framehook *framehook)
+enum framehook_detachment_mode
+{
+ /*! Destroy the framehook outright. */
+ FRAMEHOOK_DETACH_DESTROY = 0,
+ /*! Remove the framehook from the channel, but don't destroy the data since
+ * it will be used by a replacement framehook on another channel. */
+ FRAMEHOOK_DETACH_PRESERVE,
+};
+
+static void framehook_detach(struct ast_framehook *framehook, enum framehook_detachment_mode mode)
{
struct ast_frame *frame;
frame = framehook->i.event_cb(framehook->chan, NULL, AST_FRAMEHOOK_EVENT_DETACHED, framehook->i.data);
@@ -67,7 +76,7 @@ static void framehook_detach_and_destroy(struct ast_framehook *framehook)
}
framehook->chan = NULL;
- if (framehook->i.destroy_cb) {
+ if (mode == FRAMEHOOK_DETACH_DESTROY && framehook->i.destroy_cb) {
framehook->i.destroy_cb(framehook->i.data);
}
ast_free(framehook);
@@ -96,7 +105,7 @@ static struct ast_frame *framehook_list_push_event(struct ast_framehook_list *fr
if (framehook->detach_and_destroy_me) {
/* this guy is signaled for destruction */
AST_LIST_REMOVE_CURRENT(list);
- framehook_detach_and_destroy(framehook);
+ framehook_detach(framehook, FRAMEHOOK_DETACH_DESTROY);
continue;
}
@@ -205,7 +214,7 @@ int ast_framehook_list_destroy(struct ast_channel *chan)
}
AST_LIST_TRAVERSE_SAFE_BEGIN(&ast_channel_framehooks(chan)->list, framehook, list) {
AST_LIST_REMOVE_CURRENT(list);
- framehook_detach_and_destroy(framehook);
+ framehook_detach(framehook, FRAMEHOOK_DETACH_DESTROY);
}
AST_LIST_TRAVERSE_SAFE_END;
ast_free(ast_channel_framehooks(chan));
@@ -213,6 +222,42 @@ int ast_framehook_list_destroy(struct ast_channel *chan)
return 0;
}
+void ast_framehook_list_fixup(struct ast_channel *old_chan, struct ast_channel *new_chan)
+{
+ struct ast_framehook *framehook;
+ int moved_framehook_id;
+
+ if (!ast_channel_framehooks(old_chan)) {
+ return;
+ }
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&ast_channel_framehooks(old_chan)->list, framehook, list) {
+ AST_LIST_REMOVE_CURRENT(list);
+
+ /* If inheritance is not allowed for this framehook, just destroy it. */
+ if (framehook->i.disable_inheritance) {
+ framehook_detach(framehook, FRAMEHOOK_DETACH_DESTROY);
+ continue;
+ }
+
+ /* Otherwise move it to the other channel and perform any fixups set by the framehook interface */
+ moved_framehook_id = ast_framehook_attach(new_chan, &framehook->i);
+
+ if (moved_framehook_id < 0) {
+ ast_log(LOG_WARNING, "Failed framehook copy during masquerade. Expect loss of features.\n");
+ framehook_detach(framehook, FRAMEHOOK_DETACH_DESTROY);
+ } else {
+ if (framehook->i.chan_fixup_cb) {
+ framehook->i.chan_fixup_cb(framehook->i.data, moved_framehook_id,
+ old_chan, new_chan);
+ }
+
+ framehook_detach(framehook, FRAMEHOOK_DETACH_PRESERVE);
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+}
+
int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks)
{
if (!framehooks) {