summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/asterisk/bridge.h2
-rw-r--r--include/asterisk/core_unreal.h3
-rw-r--r--main/bridge_channel.c13
-rw-r--r--main/core_unreal.c5
-rw-r--r--res/ari/resource_bridges.c6
5 files changed, 23 insertions, 6 deletions
diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h
index 5f22d37ef..3bcb1131a 100644
--- a/include/asterisk/bridge.h
+++ b/include/asterisk/bridge.h
@@ -295,6 +295,8 @@ struct ast_bridge {
unsigned int num_channels;
/*! Number of active channels in the bridge. */
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.
* Zero if merges are allowed.
diff --git a/include/asterisk/core_unreal.h b/include/asterisk/core_unreal.h
index c7a82ef92..9a8d2e1f5 100644
--- a/include/asterisk/core_unreal.h
+++ b/include/asterisk/core_unreal.h
@@ -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 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 -1 on failure
*
* \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);
/* ------------------------------------------------------------------- */
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index c782ec67d..830abb750 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -1324,7 +1324,12 @@ static void bridge_channel_dissolve_check(struct ast_bridge_channel *bridge_chan
default:
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)
@@ -1361,6 +1366,9 @@ void bridge_channel_internal_pull(struct ast_bridge_channel *bridge_channel)
if (!bridge_channel->suspended) {
--bridge->num_active;
}
+ if (ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
+ --bridge->num_lonely;
+ }
--bridge->num_channels;
AST_LIST_REMOVE(&bridge->channels, bridge_channel, entry);
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;
AST_LIST_INSERT_TAIL(&bridge->channels, bridge_channel, entry);
++bridge->num_channels;
+ if (ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
+ ++bridge->num_lonely;
+ }
if (!bridge_channel->suspended) {
++bridge->num_active;
}
diff --git a/main/core_unreal.c b/main/core_unreal.c
index 7b7595b87..99ddc5163 100644
--- a/main/core_unreal.c
+++ b/main/core_unreal.c
@@ -668,7 +668,7 @@ void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *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_channel *chan;
@@ -741,7 +741,8 @@ int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge
ast_channel_unref(chan);
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 */
if (ast_bridge_impart(bridge, chan, NULL, features, 1)) {
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index 65fe8d79f..cc92017fc 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -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));
- 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(
response, 500, "Internal Error", "Failed to put playback channel into the bridge");
return;
@@ -394,7 +395,8 @@ void ast_ari_record_bridge(struct ast_variable *headers, struct ast_record_bridg
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(
response, 500, "Internal Error", "Failed to put recording channel into the bridge");
return;