struct ast_channel *bridge_channel;
struct stasis_app_control *control;
struct stasis_forward *forward;
- char bridge_id[0];
+ char *bridge_id;
};
static void *bridge_channel_control_thread(void *data)
struct stasis_app_control *control = thread_data->control;
struct stasis_forward *forward = thread_data->forward;
ast_callid callid = ast_channel_callid(bridge_channel);
- char *bridge_id = ast_strdupa(thread_data->bridge_id);
+ char *bridge_id = thread_data->bridge_id;
if (callid) {
ast_callid_threadassoc_add(callid);
stasis_app_control_execute_until_exhausted(bridge_channel, control);
stasis_app_control_flush_queue(control);
- stasis_app_bridge_playback_channel_remove(bridge_id, control);
+ if (bridge_id) {
+ stasis_app_bridge_playback_channel_control_remove(bridge_id, control);
+ ast_free(bridge_id);
+ }
stasis_forward_cancel(forward);
ao2_cleanup(control);
ast_hangup(bridge_channel);
ast_bridge_queue_everyone_else(bridge, NULL, &prog);
/* Give play_channel and control reference to the thread data */
- thread_data = ast_malloc(sizeof(*thread_data) + strlen(bridge->uniqueid) + 1);
+ thread_data = ast_calloc(1, sizeof(*thread_data));
if (!thread_data) {
stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
ast_ari_response_alloc_failed(response);
thread_data->bridge_channel = play_channel;
thread_data->control = control;
thread_data->forward = channel_forward;
- /* Safe */
- strcpy(thread_data->bridge_id, bridge->uniqueid);
+ thread_data->bridge_id = ast_strdup(bridge->uniqueid);
+ if (!thread_data->bridge_id) {
+ stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
+ ast_ari_response_alloc_failed(response);
+ ast_free(thread_data);
+ return;
+ }
if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control);
+ ast_free(thread_data->bridge_id);
ast_ari_response_alloc_failed(response);
ast_free(thread_data);
return;
* in which case we'll revert to ari_bridges_play_new.
*/
if (ari_bridges_play_found(args_media, args_media_count, args_lang,
- args_offset_ms, args_skipms, args_playback_id, response,bridge,
+ args_offset_ms, args_skipms, args_playback_id, response, bridge,
play_channel) == PLAY_FOUND_CHANNEL_UNAVAILABLE) {
continue;
}
ast_free(bridge_id);
}
+void stasis_app_bridge_playback_channel_control_remove(const char *bridge_id,
+ struct stasis_app_control *control)
+{
+ ast_assert(!ast_strlen_zero(bridge_id));
+ ao2_unlink(app_controls, control);
+}
+
static void playback_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
{
char *bridge_id = data;
* 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);
+ stasis_app_bridge_playback_channel_control_remove(bridge_id, control);
ao2_ref(wrapper, -1);
}
}