diff options
-rw-r--r-- | include/asterisk/bridge.h | 2 | ||||
-rw-r--r-- | include/asterisk/core_unreal.h | 3 | ||||
-rw-r--r-- | main/bridge_channel.c | 13 | ||||
-rw-r--r-- | main/core_unreal.c | 5 | ||||
-rw-r--r-- | res/ari/resource_bridges.c | 6 |
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; |