Fix CLI "bridge kick <bridge> <channel>" to check if the bridge needs dissolving.

SIP/foo -- Local;1==Local;2 -- .... -- Local;1==Local;2 -- SIP/bar
Kick a ;1 channel and the chain toward SIP/foo goes away.
Kick a ;2 channel and the chain toward SIP/bar goes away.

This can leave a local channel chain between the kicked ;1 and ;2 channels
that are orphaned until you manually request one of those channels to
hangup or request the bridge to dissolve.

* Added ast_bridge_kick() as a companion to ast_bridge_remove().  The
functional difference is that ast_bridge_kick() may dissolve the bridge as
a result of the channel leaving the bridge.

* Made CLI "bridge kick <bridge> <channel>" use ast_bridge_kick() instead
of ast_bridge_remove() so the bridge can dissolve if needed.

* Renamed bridge_channel_handle_hangup() to ast_bridge_channel_kick() and
made it accessible to other files.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396877 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Richard Mudgett
2013-08-16 20:48:13 +00:00
parent 6399836f9b
commit 35b9c6a660
4 changed files with 78 additions and 34 deletions

View File

@@ -1681,6 +1681,31 @@ int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan)
return 0;
}
static void kick_it(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
{
ast_bridge_channel_kick(bridge_channel);
}
int ast_bridge_kick(struct ast_bridge *bridge, struct ast_channel *chan)
{
struct ast_bridge_channel *bridge_channel;
int res;
ast_bridge_lock(bridge);
/* Try to find the channel that we want to kick. */
if (!(bridge_channel = bridge_find_channel(bridge, chan))) {
ast_bridge_unlock(bridge);
return -1;
}
res = ast_bridge_channel_queue_callback(bridge_channel, kick_it, NULL, 0);
ast_bridge_unlock(bridge);
return res;
}
/*!
* \internal
* \brief Point the bridge_channel to a new bridge.
@@ -4651,25 +4676,9 @@ static char *handle_bridge_kick_channel(struct ast_cli_entry *e, int cmd, struct
return CLI_SUCCESS;
}
/*
* BUGBUG the CLI kick needs to get the bridge to decide if it should dissolve.
*
* Likely the best way to do this is to add a kick method. The
* basic bridge class can then decide to dissolve the bridge if
* one of two channels is kicked.
*
* SIP/foo -- Local;1==Local;2 -- .... -- Local;1==Local;2 -- SIP/bar
* Kick a ;1 channel and the chain toward SIP/foo goes away.
* Kick a ;2 channel and the chain toward SIP/bar goes away.
*
* This can leave a local channel chain between the kicked ;1
* and ;2 channels that are orphaned until you manually request
* one of those channels to hangup or request the bridge to
* dissolve.
*/
ast_cli(a->fd, "Kicking channel '%s' from bridge '%s'\n",
ast_channel_name(chan), a->argv[2]);
ast_bridge_remove(bridge, chan);
ast_bridge_kick(bridge, chan);
return CLI_SUCCESS;
}