summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/asterisk/stasis_app.h9
-rw-r--r--res/ari/resource_bridges.c9
-rw-r--r--res/res_stasis.c16
3 files changed, 33 insertions, 1 deletions
diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h
index 90ef82ebf..8ceeffba3 100644
--- a/include/asterisk/stasis_app.h
+++ b/include/asterisk/stasis_app.h
@@ -746,6 +746,15 @@ int stasis_app_bridge_playback_channel_add(struct ast_bridge *bridge,
struct stasis_app_control *control);
/*!
+ * \brief remove channel from list of ARI playback channels for bridges.
+ *
+ * \param bridge_id The unique ID of the bridge the playback channel is in.
+ * \param control The app control structure for the playback channel
+ */
+void stasis_app_bridge_playback_channel_remove(char *bridge_id,
+ struct stasis_app_control *control);
+
+/*!
* \brief Result codes used when adding/removing channels to/from bridges.
*/
enum stasis_app_control_channel_result {
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index a86f3129c..39709d022 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -278,6 +278,7 @@ struct bridge_channel_control_thread_data {
struct ast_channel *bridge_channel;
struct stasis_app_control *control;
struct stasis_forward *forward;
+ char bridge_id[0];
};
static void *bridge_channel_control_thread(void *data)
@@ -286,6 +287,7 @@ static void *bridge_channel_control_thread(void *data)
struct ast_channel *bridge_channel = thread_data->bridge_channel;
struct stasis_app_control *control = thread_data->control;
struct stasis_forward *forward = thread_data->forward;
+ char *bridge_id = ast_strdupa(thread_data->bridge_id);
RAII_VAR(struct ast_callid *, callid, ast_channel_callid(bridge_channel), ast_callid_cleanup);
@@ -299,6 +301,7 @@ static void *bridge_channel_control_thread(void *data)
stasis_app_control_execute_until_exhausted(bridge_channel, control);
stasis_app_control_flush_queue(control);
+ stasis_app_bridge_playback_channel_remove(bridge_id, control);
stasis_forward_cancel(forward);
ao2_cleanup(control);
ast_hangup(bridge_channel);
@@ -464,8 +467,9 @@ static void ari_bridges_play_new(const char *args_media,
}
/* Give play_channel and control reference to the thread data */
- thread_data = ast_calloc(1, sizeof(*thread_data));
+ thread_data = ast_malloc(sizeof(*thread_data) + strlen(bridge->uniqueid) + 1);
if (!thread_data) {
+ stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
ast_ari_response_alloc_failed(response);
return;
}
@@ -473,8 +477,11 @@ static void ari_bridges_play_new(const char *args_media,
thread_data->bridge_channel = play_channel;
thread_data->control = control;
thread_data->forward = channel_forward;
+ /* Safe */
+ strcpy(thread_data->bridge_id, bridge->uniqueid);
if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
+ stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
ast_ari_response_alloc_failed(response);
ast_free(thread_data);
return;
diff --git a/res/res_stasis.c b/res/res_stasis.c
index fae9aa220..11aeb438e 100644
--- a/res/res_stasis.c
+++ b/res/res_stasis.c
@@ -713,6 +713,22 @@ int stasis_app_bridge_playback_channel_add(struct ast_bridge *bridge,
return 0;
}
+void stasis_app_bridge_playback_channel_remove(char *bridge_id,
+ struct stasis_app_control *control)
+{
+ struct stasis_app_bridge_channel_wrapper *wrapper;
+
+ wrapper = ao2_find(app_bridges_playback, bridge_id, OBJ_SEARCH_KEY | OBJ_UNLINK);
+ if (wrapper) {
+ /* If wrapper is not found, then that means the after bridge callback has been
+ * called or is in progress. No need to unlink the control here since that has
+ * been done or is about to be done in the after bridge callback
+ */
+ ao2_unlink(app_controls, control);
+ ao2_ref(wrapper, -1);
+ }
+}
+
struct ast_channel *stasis_app_bridge_playback_channel_find(struct ast_bridge *bridge)
{
struct stasis_app_bridge_channel_wrapper *playback_wrapper;