summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2014-11-09 00:03:52 +0000
committerMatthew Jordan <mjordan@digium.com>2014-11-09 00:03:52 +0000
commit266c022a45e6a8325a5928e0303926f60928ba5d (patch)
tree37a810e0b614c1379bdd9569551d4775e0414bfe /bridges
parenta6bfa0d20a5d93bd14db48f0d82f7e570cdf834d (diff)
bridge_native_rtp: Fix T.38 issues with remote bridges
After r425242 the fax/sip/directmedia_reinvite_t38 test started failing due to the surviving channel not being re-INVITEd back from T.38 to audio. This patch fixes that bug - a deeper explanation of what happened follows. When two RTP channels are in a native bridge, the bridging layer will investigate each via the get_rtp_info glue callback. This callback returns the native bridge preference of the channel *at that moment in time* (that part is key). At different points during the bridging, the native bridging layer will inform the RTP capable channels of the status of the bridge via the update_peer glue callback. In a T.38 scenario with audio direct media, the sequence of events will often look like the following: * SIP/A and SIP/B both have audio and enter a native bridge. * Asterisk re-INVITEs audio between SIP/A and SIP/B directly (via an update_peer callback). * SIP/A sends a re-INVITE to T.38, which causes Asterisk to send a re-INVITE to T.38 to SIP/B. Assuming everyone 200 OKs the process, the UDPTL stack receives UDPTL packets in Asterisk from both endpoints. From the perspective of the channels, we are now in a local bridge for T.38, even though we are technically still in a remote bridge in bridge_native_rtp. (YAY!) * When one side hangs up, bridge_native_rtp is told to stop bridging. It then re-evaluates the channels and asks them how they are bridged - and since T.38 is enabled, they reply with a Local bridge (which is correct), but is wrong because the audio portion is still technically in a remote bridge. * Asterisk releases the surviving channel, whose audio is *not* re-INVITED back to Asterisk as bridge_native_rtp incorrectly assumes that it was in a local bridge. Ironically, prior to r425242, this used to work mostly due to a fluke in the bridging layer. The purpose of the get_rtp_info callback shouldn't be modified: it should tell the bridging layer what kind of bridge the channel prefers at that moment in time. If you have T.38 enabled, that *must* be a local bridge, as the UDPTPL stack must be in the media path. As such, this patch does not modify that part of the code. However, we have to tell the channels to re-evaluate themselves when they come out of a native bridge, since we can no longer trust the get_rtp_info callbacks when the native bridge is being stopped. Something else may have changed in the channels, and they may now be lying to us. As such, this patch makes it so that we unilaterally tell the channels that they are no longer bridged via the update_peer callback. This is actually what the channels expect anyway: code in both chan_sip and chan_pjsip's callbacks look at the T.38 state and - if they were in T.38 - send a re-INVITE to get the audio back to Asterisk. Review: https://reviewboard.asterisk.org/r/4157/ ........ Merged revisions 427582 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@427583 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'bridges')
-rw-r--r--bridges/bridge_native_rtp.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/bridges/bridge_native_rtp.c b/bridges/bridge_native_rtp.c
index adb85ffd4..f6b0e68fa 100644
--- a/bridges/bridge_native_rtp.c
+++ b/bridges/bridge_native_rtp.c
@@ -229,10 +229,7 @@ static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel
}
break;
case AST_RTP_GLUE_RESULT_REMOTE:
- if (!target) {
- glue0->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
- glue1->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
- } else {
+ if (target) {
/*
* If a target was provided, it is being put on hold and should expect to
* receive media from Asterisk instead of what it was previously connected to.
@@ -248,6 +245,11 @@ static void native_rtp_bridge_stop(struct ast_bridge *bridge, struct ast_channel
break;
}
+ if (!target && native_type != AST_RTP_GLUE_RESULT_FORBID) {
+ glue0->update_peer(bc0->chan, NULL, NULL, NULL, NULL, 0);
+ glue1->update_peer(bc1->chan, NULL, NULL, NULL, NULL, 0);
+ }
+
ast_debug(2, "Discontinued RTP bridging of '%s' and '%s' - media will flow through Asterisk core\n",
ast_channel_name(bc0->chan), ast_channel_name(bc1->chan));