summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
authorKinsey Moore <kmoore@digium.com>2013-10-29 12:30:21 +0000
committerKinsey Moore <kmoore@digium.com>2013-10-29 12:30:21 +0000
commit6c417b0475acea32c508777c94975a6c7abc2ed5 (patch)
tree21ea732a1446d8575eb6f72f0bca0b3e6cf9259e /bridges
parentfd98037fe29a28844b0da8090cdc55180decb0cd (diff)
bridge_native_rtp: Ensure bridge is torn down
When a bridge transitions away from one tech to another, the tech going away is provided a dummy bridge with no channels in it to tear down. Currently this means that the teardown code exits prematurely and does not tear anything down. This change tears down RTP bridging for the channel provided in the leave bridge tech callback. This also reverts the majority of r400403 since it is now redundant. (closes issue ASTERISK-22628) (closes issue ASTERISK-22676) Reported by: John Bigelow Reported by: Kevin Harwell Tested by: John Bigelow Review: https://reviewboard.asterisk.org/r/2905/ Patches: native_rtp_fix.diff uploaded by Kinsey Moore (License 6273) ........ Merged revisions 402148 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@402149 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'bridges')
-rw-r--r--bridges/bridge_native_rtp.c125
1 files changed, 30 insertions, 95 deletions
diff --git a/bridges/bridge_native_rtp.c b/bridges/bridge_native_rtp.c
index 639b8946c..27d8d77ca 100644
--- a/bridges/bridge_native_rtp.c
+++ b/bridges/bridge_native_rtp.c
@@ -183,89 +183,10 @@ static int native_rtp_bridge_start(struct ast_bridge *bridge, struct ast_channel
return 0;
}
-/*!
- * \internal
- * \brief Given a bridge channel, get its RTP instance
- *
- * The returned ast_rtp_instance has its refcount bumped.
- *
- * \param bridge_channel Take a guess
- * \retval NULL No RTP instance on this bridge channel
- * \retval non-NULL The RTP instance on this bridge channel
- */
-static struct ast_rtp_instance *bridge_channel_get_rtp_instance(struct ast_bridge_channel *bridge_channel)
-{
- struct ast_rtp_glue *glue;
- struct ast_rtp_instance *instance;
-
- glue = ast_rtp_instance_get_glue(ast_channel_tech(bridge_channel->chan)->type);
- if (!glue) {
- return NULL;
- }
-
- glue->get_rtp_info(bridge_channel->chan, &instance);
- return instance;
-}
-
-/*!
- * \internal
- * \brief Determine which two channels are bridged together
- *
- * Because of the nature of swapping, when the time comes for a channel to
- * leave a native RTP bridge, it may be that there are more than two channels
- * in the list of bridge channels. Therefore, it is important to correctly
- * determine which two channels were bridged together.
- *
- * \param bridge The involved bridge
- * \param leaving The bridge channel that is leaving the native RTP bridge
- * \param[out] c0 The first bridged channel
- * \param[out] c1 The second bridged channel
- */
-static void find_bridged_channels(struct ast_bridge *bridge, struct ast_bridge_channel *leaving,
- struct ast_bridge_channel **c0, struct ast_bridge_channel **c1)
-{
- RAII_VAR(struct ast_rtp_instance *, leaving_instance, bridge_channel_get_rtp_instance(leaving), ao2_cleanup);
- struct ast_bridge_channel *iter;
-
- if (!leaving_instance) {
- return;
- }
-
- AST_LIST_TRAVERSE(&bridge->channels, iter, entry) {
- RAII_VAR(struct ast_rtp_instance *, instance, NULL, ao2_cleanup);
-
- if (iter == leaving) {
- continue;
- }
-
- instance = bridge_channel_get_rtp_instance(iter);
- if (!instance) {
- continue;
- }
-
- if (instance == ast_rtp_instance_get_bridged(leaving_instance)) {
- break;
- }
- }
- *c0 = leaving;
- *c1 = iter;
- return;
-}
-
-/*!
- * \internal
- * \brief Stop native RTP bridging of two channels
- *
- * \param bridge The bridge that had native RTP bridging happening on it
- * \param target If remote RTP bridging, the channel that is placed on hold.
- * \param leaving If this is called because a channel is leaving, this is the
- * bridge channel that is leaving the bridge
- */
-static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel *target,
- struct ast_bridge_channel *leaving)
+static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel *target)
{
- struct ast_bridge_channel *c0 = NULL;
- struct ast_bridge_channel *c1 = NULL;
+ struct ast_bridge_channel *c0 = AST_LIST_FIRST(&bridge->channels);
+ struct ast_bridge_channel *c1 = AST_LIST_LAST(&bridge->channels);
enum ast_rtp_glue_result native_type;
struct ast_rtp_glue *glue0, *glue1 = NULL;
RAII_VAR(struct ast_rtp_instance *, instance0, NULL, ao2_cleanup);
@@ -273,17 +194,7 @@ static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel
RAII_VAR(struct ast_rtp_instance *, vinstance0, NULL, ao2_cleanup);
RAII_VAR(struct ast_rtp_instance *, vinstance1, NULL, ao2_cleanup);
- if (bridge->num_channels == 2) {
- c0 = AST_LIST_FIRST(&bridge->channels);
- c1 = AST_LIST_LAST(&bridge->channels);
- } else if (bridge->num_channels > 2) {
- /* When a channel leaves a native RTP bridge, it is possible for
- * more channels to exist in the bridge than when the RTP bridge
- * was started. Thus we need to determine which two channels were
- * bridged based on the leaving channel
- */
- find_bridged_channels(bridge, leaving, &c0, &c1);
- } else {
+ if (c0 == c1) {
return;
}
@@ -347,7 +258,7 @@ static struct ast_frame *native_rtp_framehook(struct ast_channel *chan, struct a
if (bridge) {
if (f->subclass.integer == AST_CONTROL_HOLD) {
- native_rtp_bridge_stop(bridge, chan, NULL);
+ native_rtp_bridge_stop(bridge, chan);
} else if ((f->subclass.integer == AST_CONTROL_UNHOLD) || (f->subclass.integer == AST_CONTROL_UPDATE_RTP_PEER)) {
native_rtp_bridge_start(bridge, chan);
}
@@ -511,9 +422,33 @@ static void native_rtp_bridge_unsuspend(struct ast_bridge *bridge, struct ast_br
static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
{
+ struct ast_rtp_glue *glue;
+ RAII_VAR(struct ast_rtp_instance *, instance, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_rtp_instance *, vinstance, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_rtp_instance *, tinstance, NULL, ao2_cleanup);
+
native_rtp_bridge_framehook_detach(bridge_channel);
- native_rtp_bridge_stop(bridge, NULL, bridge_channel);
+ glue = ast_rtp_instance_get_glue(ast_channel_tech(bridge_channel->chan)->type);
+ glue->get_rtp_info(bridge_channel->chan, &instance);
+ glue->get_vrtp_info ? glue->get_vrtp_info(bridge_channel->chan, &vinstance) : AST_RTP_GLUE_RESULT_FORBID;
+ glue->get_trtp_info ? glue->get_trtp_info(bridge_channel->chan, &tinstance) : AST_RTP_GLUE_RESULT_FORBID;
+
+ /* Tear down P2P bridges */
+ if (instance) {
+ ast_rtp_instance_set_bridged(instance, NULL);
+ }
+ if (vinstance) {
+ ast_rtp_instance_set_bridged(vinstance, NULL);
+ }
+ if (tinstance) {
+ ast_rtp_instance_set_bridged(tinstance, NULL);
+ }
+
+ /* Direct RTP may have occurred, tear it down */
+ glue->update_peer(bridge_channel->chan, NULL, NULL, NULL, NULL, 0);
+
+ native_rtp_bridge_stop(bridge, NULL);
}
static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)