From d17a780333fc007fdfcd75282a9c4ee032894f2c Mon Sep 17 00:00:00 2001 From: Joshua Colp Date: Fri, 1 Nov 2013 12:13:09 +0000 Subject: res_stasis: Ensure the channel is always departed from the bridge when it leaves. This change adds a command to the command queue to explicitly depart the channel from the bridge when it is told it has left. If the channel has already been departed or has entered a different bridge this command will become a no-op. (closes issue ASTERISK-22703) Reported by: John Bigelow (closes issue ASTERISK-22634) Reported by: Kevin Harwell Review: https://reviewboard.asterisk.org/r/2965/ ........ Merged revisions 402336 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@402337 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- res/stasis/control.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'res/stasis/control.c') diff --git a/res/stasis/control.c b/res/stasis/control.c index 26406bb07..8a77deae4 100644 --- a/res/stasis/control.c +++ b/res/stasis/control.c @@ -489,11 +489,34 @@ struct ast_bridge *stasis_app_get_bridge(struct stasis_app_control *control) } } +static void *bridge_channel_depart(struct stasis_app_control *control, + struct ast_channel *chan, void *data) +{ + RAII_VAR(struct ast_bridge_channel *, bridge_channel, data, ao2_cleanup); + + { + SCOPED_CHANNELLOCK(lock, chan); + + if (bridge_channel != ast_channel_internal_bridge_channel(chan)) { + ast_debug(3, "%s: Channel is no longer in departable state\n", + ast_channel_uniqueid(chan)); + return NULL; + } + } + + ast_debug(3, "%s: Channel departing bridge\n", + ast_channel_uniqueid(chan)); + + ast_bridge_depart(chan); + + return NULL; +} static void bridge_after_cb(struct ast_channel *chan, void *data) { struct stasis_app_control *control = data; SCOPED_AO2LOCK(lock, control); + struct ast_bridge_channel *bridge_channel; ast_debug(3, "%s, %s: Channel leaving bridge\n", ast_channel_uniqueid(chan), control->bridge->uniqueid); @@ -507,8 +530,15 @@ static void bridge_after_cb(struct ast_channel *chan, void *data) /* No longer in the bridge */ control->bridge = NULL; - /* Wakeup the command_queue loop */ - exec_command(control, NULL, NULL); + /* Get the bridge channel so we don't depart from the wrong bridge */ + ast_channel_lock(chan); + bridge_channel = ast_channel_get_bridge_channel(chan); + ast_channel_unlock(chan); + + /* Depart this channel from the bridge using the command queue if possible */ + if (stasis_app_send_command_async(control, bridge_channel_depart, bridge_channel)) { + ao2_cleanup(bridge_channel); + } } static void bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason, -- cgit v1.2.3