mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-24 06:53:41 +00:00
bridge_channel: Support the lonely flag and make ARI use it.
The lonely flag is an optional flag for bridge channels that will make them leave a bridge when a channel leaves if only lonely channels are in the bridge at that point. This is useful for things like ending recording and playback channels when they cease to be interacting with other channels in the bridge. (closes issue ASTERISK-22117) Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/2721/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@396497 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -295,6 +295,8 @@ struct ast_bridge {
|
|||||||
unsigned int num_channels;
|
unsigned int num_channels;
|
||||||
/*! Number of active channels in the bridge. */
|
/*! Number of active channels in the bridge. */
|
||||||
unsigned int num_active;
|
unsigned int num_active;
|
||||||
|
/*! Number of channels with AST_BRIDGE_CHANNEL_FLAG_LONELY in the bridge. */
|
||||||
|
unsigned int num_lonely;
|
||||||
/*!
|
/*!
|
||||||
* \brief Count of the active temporary requests to inhibit bridge merges.
|
* \brief Count of the active temporary requests to inhibit bridge merges.
|
||||||
* Zero if merges are allowed.
|
* Zero if merges are allowed.
|
||||||
|
@@ -215,13 +215,14 @@ void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
|
|||||||
*
|
*
|
||||||
* \param ast A member of the unreal channel being pushed
|
* \param ast A member of the unreal channel being pushed
|
||||||
* \param bridge Which bridge we want to push the channel to
|
* \param bridge Which bridge we want to push the channel to
|
||||||
|
* \param flags Feature flags to be set on the bridge channel.
|
||||||
*
|
*
|
||||||
* \retval 0 if the channel is successfully imparted onto the bridge
|
* \retval 0 if the channel is successfully imparted onto the bridge
|
||||||
* \retval -1 on failure
|
* \retval -1 on failure
|
||||||
*
|
*
|
||||||
* \note This is equivalent to ast_call() on unreal based channel drivers that are designed to use it instead.
|
* \note This is equivalent to ast_call() on unreal based channel drivers that are designed to use it instead.
|
||||||
*/
|
*/
|
||||||
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge);
|
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
@@ -1324,7 +1324,12 @@ static void bridge_channel_dissolve_check(struct ast_bridge_channel *bridge_chan
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* BUGBUG need to implement AST_BRIDGE_CHANNEL_FLAG_LONELY support here */
|
|
||||||
|
if (bridge->num_lonely && bridge->num_lonely == bridge->num_channels) {
|
||||||
|
/* This will start a chain reaction where each channel leaving enters this function and causes
|
||||||
|
* the next to leave as long as there aren't non-lonely channels in the bridge. */
|
||||||
|
ast_bridge_channel_leave_bridge(AST_LIST_FIRST(&bridge->channels), BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bridge_channel_internal_pull(struct ast_bridge_channel *bridge_channel)
|
void bridge_channel_internal_pull(struct ast_bridge_channel *bridge_channel)
|
||||||
@@ -1361,6 +1366,9 @@ void bridge_channel_internal_pull(struct ast_bridge_channel *bridge_channel)
|
|||||||
if (!bridge_channel->suspended) {
|
if (!bridge_channel->suspended) {
|
||||||
--bridge->num_active;
|
--bridge->num_active;
|
||||||
}
|
}
|
||||||
|
if (ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
|
||||||
|
--bridge->num_lonely;
|
||||||
|
}
|
||||||
--bridge->num_channels;
|
--bridge->num_channels;
|
||||||
AST_LIST_REMOVE(&bridge->channels, bridge_channel, entry);
|
AST_LIST_REMOVE(&bridge->channels, bridge_channel, entry);
|
||||||
bridge->v_table->pull(bridge, bridge_channel);
|
bridge->v_table->pull(bridge, bridge_channel);
|
||||||
@@ -1416,6 +1424,9 @@ int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel)
|
|||||||
bridge_channel->just_joined = 1;
|
bridge_channel->just_joined = 1;
|
||||||
AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, entry);
|
AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, entry);
|
||||||
++bridge->num_channels;
|
++bridge->num_channels;
|
||||||
|
if (ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
|
||||||
|
++bridge->num_lonely;
|
||||||
|
}
|
||||||
if (!bridge_channel->suspended) {
|
if (!bridge_channel->suspended) {
|
||||||
++bridge->num_active;
|
++bridge->num_active;
|
||||||
}
|
}
|
||||||
|
@@ -668,7 +668,7 @@ void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
|
|||||||
ast_channel_datastore_inherit(semi1, semi2);
|
ast_channel_datastore_inherit(semi1, semi2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge)
|
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct ast_bridge_features *features;
|
struct ast_bridge_features *features;
|
||||||
struct ast_channel *chan;
|
struct ast_channel *chan;
|
||||||
@@ -741,7 +741,8 @@ int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge
|
|||||||
ast_channel_unref(chan);
|
ast_channel_unref(chan);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
|
|
||||||
|
ast_set_flag(&features->feature_flags, flags);
|
||||||
|
|
||||||
/* Impart the semi2 channel into the bridge */
|
/* Impart the semi2 channel into the bridge */
|
||||||
if (ast_bridge_impart(bridge, chan, NULL, features, 1)) {
|
if (ast_bridge_impart(bridge, chan, NULL, features, 1)) {
|
||||||
|
@@ -300,7 +300,8 @@ void ast_ari_play_on_bridge(struct ast_variable *headers, struct ast_play_on_bri
|
|||||||
}
|
}
|
||||||
ast_debug(1, "Created announcer channel '%s'\n", ast_channel_name(play_channel));
|
ast_debug(1, "Created announcer channel '%s'\n", ast_channel_name(play_channel));
|
||||||
|
|
||||||
if (ast_unreal_channel_push_to_bridge(play_channel, bridge)) {
|
if (ast_unreal_channel_push_to_bridge(play_channel, bridge,
|
||||||
|
AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE | AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
|
||||||
ast_ari_response_error(
|
ast_ari_response_error(
|
||||||
response, 500, "Internal Error", "Failed to put playback channel into the bridge");
|
response, 500, "Internal Error", "Failed to put playback channel into the bridge");
|
||||||
return;
|
return;
|
||||||
@@ -394,7 +395,8 @@ void ast_ari_record_bridge(struct ast_variable *headers, struct ast_record_bridg
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ast_unreal_channel_push_to_bridge(record_channel, bridge)) {
|
if (ast_unreal_channel_push_to_bridge(record_channel, bridge,
|
||||||
|
AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE | AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
|
||||||
ast_ari_response_error(
|
ast_ari_response_error(
|
||||||
response, 500, "Internal Error", "Failed to put recording channel into the bridge");
|
response, 500, "Internal Error", "Failed to put recording channel into the bridge");
|
||||||
return;
|
return;
|
||||||
|
Reference in New Issue
Block a user