mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-03 11:11:05 +00:00
Bridging: Fix orphaned bridge if neither of the joining channels can join.
The original issue noted that the bridge is orphaned when res_parking.so is not loaded and a call uses the dial kK flags. A similar issue happens when only one of the park flags is used. In this case you have the bridge with one or the other channel left in it. The channel and bridge will stay around until the channel hangs up. * Fixed the initial bridge channel push failure to act as if the channel were kicked out of the bridge. The bridge then decides if it needs to be dissolved. (closes issue ASTERISK-22629) Reported by: Kevin Harwell Review: https://reviewboard.asterisk.org/r/2928/ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/12@401424 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -107,6 +107,9 @@ void bridge_channel_settle_owed_events(struct ast_bridge *orig_bridge, struct as
|
|||||||
*
|
*
|
||||||
* \retval 0 on success.
|
* \retval 0 on success.
|
||||||
* \retval -1 on failure. The channel did not get pushed.
|
* \retval -1 on failure. The channel did not get pushed.
|
||||||
|
*
|
||||||
|
* \note On failure the caller must call
|
||||||
|
* ast_bridge_features_remove(bridge_channel->features, AST_BRIDGE_HOOK_REMOVE_ON_PULL);
|
||||||
*/
|
*/
|
||||||
int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel);
|
int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel);
|
||||||
|
|
||||||
|
@@ -1791,6 +1791,8 @@ void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridg
|
|||||||
bridge_channel_change_bridge(bridge_channel, dst_bridge);
|
bridge_channel_change_bridge(bridge_channel, dst_bridge);
|
||||||
|
|
||||||
if (bridge_channel_internal_push(bridge_channel)) {
|
if (bridge_channel_internal_push(bridge_channel)) {
|
||||||
|
ast_bridge_features_remove(bridge_channel->features,
|
||||||
|
AST_BRIDGE_HOOK_REMOVE_ON_PULL);
|
||||||
ast_bridge_channel_leave_bridge(bridge_channel,
|
ast_bridge_channel_leave_bridge(bridge_channel,
|
||||||
BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
|
BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
|
||||||
}
|
}
|
||||||
@@ -2036,11 +2038,15 @@ int bridge_do_move(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bri
|
|||||||
|
|
||||||
if (bridge_channel_internal_push(bridge_channel)) {
|
if (bridge_channel_internal_push(bridge_channel)) {
|
||||||
/* Try to put the channel back into the original bridge. */
|
/* Try to put the channel back into the original bridge. */
|
||||||
|
ast_bridge_features_remove(bridge_channel->features,
|
||||||
|
AST_BRIDGE_HOOK_REMOVE_ON_PULL);
|
||||||
if (attempt_recovery && was_in_bridge) {
|
if (attempt_recovery && was_in_bridge) {
|
||||||
/* Point back to original bridge. */
|
/* Point back to original bridge. */
|
||||||
bridge_channel_change_bridge(bridge_channel, orig_bridge);
|
bridge_channel_change_bridge(bridge_channel, orig_bridge);
|
||||||
|
|
||||||
if (bridge_channel_internal_push(bridge_channel)) {
|
if (bridge_channel_internal_push(bridge_channel)) {
|
||||||
|
ast_bridge_features_remove(bridge_channel->features,
|
||||||
|
AST_BRIDGE_HOOK_REMOVE_ON_PULL);
|
||||||
ast_bridge_channel_leave_bridge(bridge_channel,
|
ast_bridge_channel_leave_bridge(bridge_channel,
|
||||||
BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
|
BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
|
||||||
bridge_channel_settle_owed_events(orig_bridge, bridge_channel);
|
bridge_channel_settle_owed_events(orig_bridge, bridge_channel);
|
||||||
|
@@ -1566,7 +1566,6 @@ int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel)
|
|||||||
|| ast_bridge_channel_establish_roles(bridge_channel)) {
|
|| ast_bridge_channel_establish_roles(bridge_channel)) {
|
||||||
ast_debug(1, "Bridge %s: pushing %p(%s) into bridge failed\n",
|
ast_debug(1, "Bridge %s: pushing %p(%s) into bridge failed\n",
|
||||||
bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
|
bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
|
||||||
ast_bridge_features_remove(bridge_channel->features, AST_BRIDGE_HOOK_REMOVE_ON_PULL);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bridge_channel->in_bridge = 1;
|
bridge_channel->in_bridge = 1;
|
||||||
@@ -1969,8 +1968,7 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel)
|
|||||||
*/
|
*/
|
||||||
ast_bridge_lock(bridge_channel->bridge);
|
ast_bridge_lock(bridge_channel->bridge);
|
||||||
|
|
||||||
/* Make sure we're still good to be put into a bridge
|
/* Make sure we're still good to be put into a bridge */
|
||||||
*/
|
|
||||||
ast_channel_lock(bridge_channel->chan);
|
ast_channel_lock(bridge_channel->chan);
|
||||||
if (ast_channel_internal_bridge(bridge_channel->chan)
|
if (ast_channel_internal_bridge(bridge_channel->chan)
|
||||||
|| ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_ZOMBIE)) {
|
|| ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_ZOMBIE)) {
|
||||||
@@ -1993,8 +1991,14 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bridge_channel_internal_push(bridge_channel)) {
|
if (bridge_channel_internal_push(bridge_channel)) {
|
||||||
ast_bridge_channel_leave_bridge(bridge_channel,
|
int cause = bridge_channel->bridge->cause;
|
||||||
BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause);
|
|
||||||
|
ast_bridge_unlock(bridge_channel->bridge);
|
||||||
|
ast_bridge_channel_kick(bridge_channel, cause);
|
||||||
|
ast_bridge_channel_lock_bridge(bridge_channel);
|
||||||
|
ast_bridge_features_remove(bridge_channel->features,
|
||||||
|
AST_BRIDGE_HOOK_REMOVE_ON_PULL);
|
||||||
|
bridge_channel_dissolve_check(bridge_channel);
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
bridge_reconfigured(bridge_channel->bridge, !bridge_channel->inhibit_colp);
|
bridge_reconfigured(bridge_channel->bridge, !bridge_channel->inhibit_colp);
|
||||||
|
Reference in New Issue
Block a user