summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJonathan Rose <jrose@digium.com>2014-08-13 16:24:37 +0000
committerJonathan Rose <jrose@digium.com>2014-08-13 16:24:37 +0000
commitd4695774e7ef3b4699b8283f175d161cd19e3d25 (patch)
tree4f59a5f5dc0094ffbe928dd21b6095defa056832 /main
parent6a6702bb0fff957c0264e872fe0760efe21a1e20 (diff)
Bridges: Fix feature interruption/unintended kick caused by external actions
If a manager or CLI user attached a mixmonitor to a call running a dynamic bridge feature while in a bridge, the feature would be interrupted and the channel would be forcibly kicked out of the bridge (usually ending the call during a simple 1 to 1 call). This would also occur during any similar action that could set the unbridge soft hangup flag, so the fix for this was to remove unbridge from the soft hangup flags and make it a separate thing all together. ASTERISK-24027 #close Reported by: mjordan Review: https://reviewboard.asterisk.org/r/3900/ ........ Merged revisions 420934 from http://svn.asterisk.org/svn/asterisk/branches/12 ........ Merged revisions 420940 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@420947 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/bridge_after.c4
-rw-r--r--main/bridge_channel.c4
-rw-r--r--main/channel.c10
-rw-r--r--main/channel_internal_api.c30
-rw-r--r--main/framehook.c4
-rw-r--r--main/pbx.c5
6 files changed, 40 insertions, 17 deletions
diff --git a/main/bridge_after.c b/main/bridge_after.c
index fbe4e605a..a21cbf58e 100644
--- a/main/bridge_after.c
+++ b/main/bridge_after.c
@@ -452,9 +452,9 @@ int ast_bridge_setup_after_goto(struct ast_channel *chan)
int goto_failed = -1;
/* We are going to be leaving the bridging system now;
- * clear any pending UNBRIDGE flags
+ * clear any pending unbridge flags
*/
- ast_channel_clear_softhangup(chan, AST_SOFTHANGUP_UNBRIDGE);
+ ast_channel_set_unbridged(chan, 0);
/* Determine if we are going to setup a dialplan location and where. */
if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) {
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index 5c2e56241..f6b466545 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -2281,8 +2281,8 @@ static void bridge_channel_wait(struct ast_bridge_channel *bridge_channel)
ms = bridge_channel_next_interval(bridge_channel);
chan = ast_waitfor_nandfds(&bridge_channel->chan, 1,
&bridge_channel->alert_pipe[0], 1, NULL, &outfd, &ms);
- if (ast_channel_softhangup_internal_flag(bridge_channel->chan) & AST_SOFTHANGUP_UNBRIDGE) {
- ast_channel_clear_softhangup(bridge_channel->chan, AST_SOFTHANGUP_UNBRIDGE);
+ if (ast_channel_unbridged(bridge_channel->chan)) {
+ ast_channel_set_unbridged(bridge_channel->chan, 0);
ast_bridge_channel_lock_bridge(bridge_channel);
bridge_channel->bridge->reconfigured = 1;
bridge_reconfigured(bridge_channel->bridge, 0);
diff --git a/main/channel.c b/main/channel.c
index 50b9e8726..5681ec1a5 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -10217,11 +10217,11 @@ int ast_channel_is_bridged(const struct ast_channel *chan)
int ast_channel_is_leaving_bridge(struct ast_channel *chan)
{
int hangup_flags = ast_channel_softhangup_internal_flag(chan);
- int hangup_test = hangup_flags & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE);
+ int hangup_test = hangup_flags & AST_SOFTHANGUP_ASYNCGOTO;
- /* This function should only return true if either ASYNCGOTO
- * or UNBRIDGE is set, or both flags are set. It should return
- * false if any other flag is set.
+ /* This function should only return true if only the ASYNCGOTO
+ * is set. It should false if any other flag is set or if the
+ * ASYNCGOTO flag is not set.
*/
return (hangup_test && (hangup_test == hangup_flags));
}
@@ -10518,7 +10518,7 @@ void ast_channel_end_dtmf(struct ast_channel *chan, char digit, struct timeval s
ast_channel_lock(chan);
dead = ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)
|| (ast_channel_softhangup_internal_flag(chan)
- & ~(AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE));
+ & ~AST_SOFTHANGUP_ASYNCGOTO);
ast_channel_unlock(chan);
if (dead) {
/* Channel is a zombie or a real hangup. */
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c
index 8a9e18eb0..e32a52791 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -173,6 +173,8 @@ struct ast_channel {
* See \arg \ref AstFileDesc */
int softhangup; /*!< Whether or not we have been hung up... Do not set this value
* directly, use ast_softhangup() */
+ int unbridged; /*!< If non-zero, the bridge core needs to re-evaluate the current
+ bridging technology which is in use by this channel's bridge. */
int fdno; /*!< Which fd had an event detected on */
int streamid; /*!< For streaming playback, the schedule ID */
int vstreamid; /*!< For streaming video playback, the schedule ID */
@@ -377,7 +379,6 @@ int ast_channel_data_add_structure(struct ast_data *tree,
ast_data_add_bool(data_softhangup, "timeout", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_TIMEOUT);
ast_data_add_bool(data_softhangup, "appunload", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_APPUNLOAD);
ast_data_add_bool(data_softhangup, "explicit", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_EXPLICIT);
- ast_data_add_bool(data_softhangup, "unbridge", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_UNBRIDGE);
/* channel flags */
data_flags = ast_data_add_node(tree, "flags");
@@ -1141,6 +1142,33 @@ void ast_channel_softhangup_internal_flag_clear(struct ast_channel *chan, int va
chan ->softhangup &= ~value;
}
+int ast_channel_unbridged_nolock(struct ast_channel *chan)
+{
+ return chan->unbridged;
+}
+
+int ast_channel_unbridged(struct ast_channel *chan)
+{
+ int res;
+ ast_channel_lock(chan);
+ res = ast_channel_unbridged_nolock(chan);
+ ast_channel_unlock(chan);
+ return res;
+}
+
+void ast_channel_set_unbridged_nolock(struct ast_channel *chan, int value)
+{
+ chan->unbridged = value;
+ ast_queue_frame(chan, &ast_null_frame);
+}
+
+void ast_channel_set_unbridged(struct ast_channel *chan, int value)
+{
+ ast_channel_lock(chan);
+ ast_channel_set_unbridged_nolock(chan, value);
+ ast_channel_unlock(chan);
+}
+
void ast_channel_callid_cleanup(struct ast_channel *chan)
{
if (chan->callid) {
diff --git a/main/framehook.c b/main/framehook.c
index 0d42b4990..ec4e1695f 100644
--- a/main/framehook.c
+++ b/main/framehook.c
@@ -170,7 +170,7 @@ int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interfac
}
if (ast_channel_is_bridged(chan)) {
- ast_softhangup_nolock(chan, AST_SOFTHANGUP_UNBRIDGE);
+ ast_channel_set_unbridged_nolock(chan, 1);
}
return framehook->id;
@@ -199,7 +199,7 @@ int ast_framehook_detach(struct ast_channel *chan, int id)
AST_LIST_TRAVERSE_SAFE_END;
if (ast_channel_is_bridged(chan)) {
- ast_softhangup_nolock(chan, AST_SOFTHANGUP_UNBRIDGE);
+ ast_channel_set_unbridged_nolock(chan, 1);
}
return res;
diff --git a/main/pbx.c b/main/pbx.c
index 785175fc4..d814c5ac6 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -6363,11 +6363,6 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL),
&found, 1))) {
- /* Defensively clear the UNBRIDGE flag in case it leaked
- * out of the bridging framework. UNBRIDE never implies
- * that a channel is hung up.
- */
- ast_channel_clear_softhangup(c, AST_SOFTHANGUP_UNBRIDGE);
if (!ast_check_hangup(c)) {
ast_channel_priority_set(c, ast_channel_priority(c) + 1);
continue;