diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index 5806b997d7..9f530c50da 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -508,7 +508,7 @@ static int start_spying(struct ast_autochan *autochan, const char *spychan_name, if (!res) { ast_channel_lock(autochan->chan); if (ast_channel_is_bridged(autochan->chan)) { - ast_softhangup_nolock(autochan->chan, AST_SOFTHANGUP_UNBRIDGE); + ast_channel_set_unbridged_nolock(autochan->chan, 1); } ast_channel_unlock(autochan->chan); } diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c index 52128942ab..cf7b935185 100644 --- a/apps/app_mixmonitor.c +++ b/apps/app_mixmonitor.c @@ -461,7 +461,7 @@ static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook) if (!res) { ast_channel_lock(chan); if (ast_channel_is_bridged(chan)) { - ast_softhangup_nolock(chan, AST_SOFTHANGUP_UNBRIDGE); + ast_channel_set_unbridged_nolock(chan, 1); } ast_channel_unlock(chan); } diff --git a/apps/app_stack.c b/apps/app_stack.c index b05afb0e5c..c9d37cd344 100644 --- a/apps/app_stack.c +++ b/apps/app_stack.c @@ -976,10 +976,9 @@ static int gosub_run(struct ast_channel *chan, const char *sub_args, int ignore_ /* Save non-hangup softhangup flags. */ saved_hangup_flags = ast_channel_softhangup_internal_flag(chan) - & (AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE); + & AST_SOFTHANGUP_ASYNCGOTO; if (saved_hangup_flags) { - ast_channel_clear_softhangup(chan, - AST_SOFTHANGUP_ASYNCGOTO | AST_SOFTHANGUP_UNBRIDGE); + ast_channel_clear_softhangup(chan, AST_SOFTHANGUP_ASYNCGOTO); } /* Save autoloop flag */ @@ -1028,10 +1027,6 @@ static int gosub_run(struct ast_channel *chan, const char *sub_args, int ignore_ */ do { /* Check for hangup. */ - if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_UNBRIDGE) { - saved_hangup_flags |= AST_SOFTHANGUP_UNBRIDGE; - ast_channel_clear_softhangup(chan, AST_SOFTHANGUP_UNBRIDGE); - } if (ast_check_hangup(chan)) { if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) { ast_log(LOG_ERROR, "%s An async goto just messed up our execution location.\n", diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 08f4effe60..cee07f2cb7 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -1048,11 +1048,6 @@ enum { * needed. */ AST_SOFTHANGUP_EXPLICIT = (1 << 5), - /*! - * Used to request that the bridge core re-evaluate the current - * bridging technology in use by the bridge this channel is in. - */ - AST_SOFTHANGUP_UNBRIDGE = (1 << 6), /*! * Used to indicate that the channel is currently executing hangup * logic in the dialplan. The channel has been hungup when this is @@ -1574,6 +1569,40 @@ int ast_check_hangup(struct ast_channel *chan); int ast_check_hangup_locked(struct ast_channel *chan); +/*! \brief This function will check if the bridge needs to be re-evaluated due to + * external changes. + * + * \param chan Channel on which to check the unbridge_eval flag + * + * \return Returns 0 if the flag is down or 1 if the flag is up. + */ +int ast_channel_unbridged(struct ast_channel *chan); + +/*! \brief ast_channel_unbridged variant. Use this if the channel + * is already locked prior to calling. + * + * \param chan Channel on which to check the unbridge flag + * + * \return Returns 0 if the flag is down or 1 if the flag is up. + */ +int ast_channel_unbridged_nolock(struct ast_channel *chan); + +/*! \brief Sets the unbridged flag and queues a NULL frame on the channel to trigger + * a check by bridge_channel_wait + * + * \param chan Which channel is having its unbridged value set + * \param value What the unbridge value is being set to + */ +void ast_channel_set_unbridged(struct ast_channel *chan, int value); + +/*! \brief Variant of ast_channel_set_unbridged. Use this if the channel + * is already locked prior to calling. + * + * \param chan Which channel is having its unbridged value set + * \param value What the unbridge value is being set to + */ +void ast_channel_set_unbridged_nolock(struct ast_channel *chan, int value); + /*! * \brief Lock the given channel, then request softhangup on the channel with the given causecode * \param chan channel on which to hang up diff --git a/main/bridge_after.c b/main/bridge_after.c index fbe4e605a5..a21cbf58ea 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 5c2e56241d..f6b4665455 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 50b9e87261..5681ec1a52 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 8a9e18eb00..e32a52791a 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 0d42b49906..ec4e1695f9 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 785175fc4b..d814c5ac61 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;