[Home]

Summary:ASTERISK-26729: res_pjsip_sdp_rtp: Keepalive does not work on video
Reporter:Luke Escude (lukeescude)Labels:
Date Opened:2017-01-18 12:13:33.000-0600Date Closed:2020-05-13 07:52:08
Priority:MajorRegression?
Status:Closed/CompleteComponents:Resources/res_pjsip_sdp_rtp
Versions:13.13.1 Frequency of
Occurrence
Related
Issues:
is duplicated byASTERISK-28890 res_pjsip_sdp_rtp: Keepalive not supported for video streams
Environment:x64 CentOSAttachments:( 0) call1.pcap
( 1) Call1.txt
( 2) echo1.pcap
( 3) Echo1.txt
( 4) video_keepalive.patch.txt
( 5) video.pcap
( 6) Video.txt
( 7) Video2.txt
Description:We are running Asterisk 14.3 with PJSIP.

The setup is as follows:

The Asterisk boxes are all virtualized behind NAT - let's say their address space is 172.x.x.x. The router that controls that nat is IP address 10.0.4.1. Kamailio/RTPProxy is running on 10.0.1.1.

Kamailio essentially looks like a "public" IP to the asterisk boxes - we have them REGISTERING to kamailio to IP address 10.0.1.1 (which is routable of course). That way, Kamailio knows how to get to the Asterisks via their "public IP" (10.0.4.1) and NAT port (probably like 16875 or whatever).

SIP communication happens wonderfully with this setup.

However, when Kamailio sends an SDP containing its address 10.0.1.1 and an RTP address, it seems like Asterisk doesn't want to send audio to that address. In order for a new NAT port to open, Asterisk has to "talk" first.

Regardless of our pjsip configuration, we cannot get Asterisk to behave properly, even by following the wiki and setting the external signaling/media addresses.
Comments:By: Asterisk Team (asteriskteam) 2017-01-18 12:13:35.115-0600

Thanks for creating a report! The issue has entered the triage process. That means the issue will wait in this status until a Bug Marshal has an opportunity to review the issue. Once the issue has been reviewed you will receive comments regarding the next steps towards resolution.

A good first step is for you to review the [Asterisk Issue Guidelines|https://wiki.asterisk.org/wiki/display/AST/Asterisk+Issue+Guidelines] if you haven't already. The guidelines detail what is expected from an Asterisk issue report.

Then, if you are submitting a patch, please review the [Patch Contribution Process|https://wiki.asterisk.org/wiki/display/AST/Patch+Contribution+Process].

By: Luke Escude (lukeescude) 2017-01-18 12:26:14.935-0600

Also, using Playback(Silence/1) or Answer() fixes the problem. Not sure what that means, but I don't think that's a good solution.

By: Joshua C. Colp (jcolp) 2017-01-19 05:28:13.247-0600

Have you tried using the "rtp_keepalive" option? This will send a keep alive RTP packet to ensure that the NAT mapping is opened and stays open even if no media is flowing.

Otherwise we'd need to see the console log with rtp set debug on and SIP traffic to see the precise flow.

By: Luke Escude (lukeescude) 2017-01-21 23:22:16.357-0600

It seems that RTP Keepalive has fixed the issue. I don't see the harm in enabling RTP Keep Alive, so I'd call this a solution.

Thanks!

By: Luke Escude (lukeescude) 2017-01-21 23:22:50.018-0600

Fixed - enabled rtp keepalive

By: Luke Escude (lukeescude) 2017-03-14 11:45:25.063-0500

So my previous solution of Playback(silence) or Answer() works just fine for standard audio calls, but this isn't a good solution in the long term (because video calling doesn't work - Asterisk isn't honoring a mid-stream re-invite).

How can we configure asterisk to "pay attention" to the IP/Port in the SDP given by Kamailio? When using Answer() asterisk sends the audio correctly, it seems. But it should not be necessary to do this at the beginning of every dial plan extension.

By: Asterisk Team (asteriskteam) 2017-03-14 11:45:25.385-0500

This issue has been reopened as a result of your commenting on it as the reporter. It will be triaged once again as applicable.

By: Luke Escude (lukeescude) 2017-03-14 11:46:56.690-0500

Attached two PCAPs and debug log outputs for a couple of example calls that don't have two-way audio.

I believe the INVITE coming from kamailio is receiving a TRYING response from Asterisk, but asterisk isn't actually doing anything.

By: Joshua C. Colp (jcolp) 2017-03-14 11:52:49.922-0500

Echo does not answer the call and until a response with SDP is sent the remote side would not know where to send media. You can place a Progress() in front of the Echo() to have a 183 Session Progress be sent, that may have the remote side send media to echo.

By: Joshua C. Colp (jcolp) 2017-03-14 11:55:01.647-0500

As for the other call we are receiving opus but sending ulaw. That's likely the cause of it, not NAT itself.

By: Luke Escude (lukeescude) 2017-03-14 12:02:45.443-0500

Because kamailio is telling the endpoint where to send audio (and presumably telling Asterisk where to send audio too), then there shouldn't be any confusion about where to send audio.

In the case of Echo() we'll just keep an Answer() function there since I think that's the only way to get it to work.

I suppose at this point, the only bug we're experiencing is an INVITE to use Video (h264) in the middle of a call that previously started with audio.

By: Luke Escude (lukeescude) 2017-03-14 12:06:36.293-0500

I'm going to upload a pcap of the failed video reinvites in just a bit.

We cannot dial other endpoints without an Answer() in front of them, is this normal?

By: Luke Escude (lukeescude) 2017-03-14 12:08:13.277-0500

Attached: Video pcap and log debug

By: Luke Escude (lukeescude) 2017-03-14 12:22:18.936-0500

I think this is the issue:

An audio call functions properly because Kamailio sends it's IP address and RTP Ports in both SDPs (one to asterisk and one to endpoint)... Endpoint will always work, since that's what they're supposed to do... But Asterisk needs Answer() or Playback() to "kick-start" audio being sent to the proper IP and port in that SDP... This is necessary because Asterisk is also behind NAT.

A video invite, which happens after the audio call is already in progress, can't possibly have an Answer() command because there's no dial plan to handle a mid-call INVITE. So the answer() band-aid fix doesn't work here anymore.

The answer is to simply configure asterisk to ALWAYS send RTP packets to whatever it receives in the SDP, regardless if the call is connected or not. rtp_keepalive doesn't seem to work, at least not with video.

By: Joshua C. Colp (jcolp) 2017-03-14 12:31:32.512-0500

How you state it should work is how it already works. If an SDP negotiation occurs (regardless if the call is connected or not) then media will be sent to the IP address and port from the remote SDP. This will occur until we receive a sufficient amount of media and the rtp_symmetric option is enabled. I would suggest enabling SIP logging in the Asterisk log as well and also providing a description of the network layout and scenario.

By: Joshua C. Colp (jcolp) 2017-03-14 12:38:28.244-0500

The output of "rtp set debug on" would also be useful.

By: Luke Escude (lukeescude) 2017-03-14 13:20:38.794-0500

Video2 log.

Pcap looks the same as video1.

By: Joshua C. Colp (jcolp) 2017-03-14 13:32:03.981-0500

And the scenario for the test?

By: Luke Escude (lukeescude) 2017-03-14 13:38:07.545-0500

I will try and create a diagram a little later, but here's the text-based environment:

Phone (GS Wave soft phone app) is behind NAT coming out of 97.77.119.234.
Asterisk is behind NAT coming out of 206.126.62.178
Kamailio has no NAT at all. It's IP address is 206.126.62.175. RTP proxy runs on this same address as well.

By: Joshua C. Colp (jcolp) 2017-03-14 13:42:50.200-0500

Okay and what are you doing in Asterisk? Echo, dialing something else, etc.

By: Luke Escude (lukeescude) 2017-03-14 13:51:14.869-0500

Using echo

In the last step of the video PCAP you can see h264 RTP trying to reach asterisk, but obviously it wasn't going through because Asterisk had not yet reached out (complying with SDP) therefore opening the NAT port. It's not sending any media first at all after the modifying INVITE (re-INVITE)

By: Joshua C. Colp (jcolp) 2017-03-14 13:59:19.534-0500

I'd suggest stopping jumping to conclusions on the reasoning. The RFC doesn't state that Asterisk has to "reach out". It just states that when there is media to be sent it should send it to the address information in the SDP (unless the symmetric RTP option is enabled). As Asterisk does not generate media it wouldn't have sent anything before receiving media. It does appear though that something is going on to prevent it from sending.

By: Luke Escude (lukeescude) 2017-03-14 14:04:09.982-0500

I apologize, however here's the proof (in Video2.txt): Keep in mind this is an Echo() with Answer() in front.... The audio works. It's the video re-INVITE that's failing.

[Mar 14 17:45:19] VERBOSE[1281] res_pjsip_logger.c: <--- Received SIP request (1199 bytes) from UDP:206.126.62.175:5060 --->
INVITE sip:*43@206.126.62.178:5060 SIP/2.0
Via: SIP/2.0/UDP 206.126.62.175;branch=z9hG4bK82f3.bc7727e32286c95afb53687ba5a45ecd.0
Via: SIP/2.0/UDP 192.168.1.12:18108;received=97.77.119.234;branch=z9hG4bK1214768101;rport=18108
Route: <sip:206.126.62.175:5060>
From: "PBX 242" <sip:242@sip.primevox.net>;tag=974045422
To: <sip:*43@sip.primevox.net>;tag=428575d4-4a59-4a93-a522-34ac9b8ee233
Call-ID: 1070804760-18108-19@BJC.BGI.B.BC
CSeq: 183 INVITE
Contact: <sip:424242242@192.168.1.12:18108>
Max-Forwards: 70
Supported: replaces, path, timer, eventlist
User-Agent: Grandstream Wave/Android 1.0.2.5
Allow: INVITE, ACK, OPTIONS, CANCEL, BYE, SUBSCRIBE, NOTIFY, INFO, REFER, UPDATE, MESSAGE
Content-Type: application/sdp
Accept: application/sdp, application/dtmf-relay
Content-Length:   395

v=0
o=424242242 8000 8001 IN IP4 206.126.62.175
s=SIP Call
c=IN IP4 206.126.62.175
t=0 0
m=audio 11590 RTP/AVP 0 8 101
a=sendrecv
a=rtpmap:0 PCMU/8000
a=ptime:20
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
m=video 13452 RTP/AVP 105
b=AS:704
a=sendrecv
a=rtpmap:105 H264/90000
a=fmtp:105 profile-level-id=428016; packetization-mode=1
a=nortpproxy:yes


You can see that the Video RTP port is 13452 - However if you do a search for that port number, it never appears ever again in the debug output. Thus, Asterisk is not sending any data to it.

I realize it's not required by the RFC, but Asterisk should still have the capability to traverse NAT in itself.

By: Luke Escude (lukeescude) 2017-03-14 14:09:11.722-0500

Oh something interesting in that same debug log: ASterisk DOES start sending video, but to port 11256.... This port was never sent to Asterisk by kamailio at all. This port was in Asterisk's 200 OK.

If asterisk was properly handling NAT, it would not attempt to create a new port for video (11256) but should use Kamailio's assigned port (13452)

here's the packet that Asterisk sends back:

[Mar 14 17:45:19] DEBUG[1282] rtp_engine.c: Using engine 'asterisk' for RTP instance '0x7fafac00dd68'
[Mar 14 17:45:19] DEBUG[1282] res_rtp_asterisk.c: Allocated port 11256 for RTP instance '0x7fafac00dd68'
[Mar 14 17:45:19] DEBUG[1282] res_rtp_asterisk.c: Creating ICE session [::]:11256 (11256) for RTP instance '0x7fafac00dd68'

[2:07]  
Then Asterisk Transmits a 200 OK with SDP
m=video 11256 RTP/AVP 105
a=rtpmap:105 H264/90000
a=fmtp:105 profile-level-id=428016
a=sendrecv

By: Joshua C. Colp (jcolp) 2017-03-14 14:15:27.442-0500

Asterisk HAS to allocate a local port in order to have a port to send the media from. That's how SDP negotiation and RTP works. The fact that it is not sending media is the issue and until someone digs in deeper I don't have an answer as to why it isn't.

By: Luke Escude (lukeescude) 2017-03-14 14:19:27.846-0500

That makes sense. It works properly with the beginning of the call (audio only) just not the second invite.

We'll keep playing around with it, but I'm unsure of how to proceed. We don't really need to offer video calling to our customers but it would be a nice-to-have feature.

By: Jared Hull (fortytwo) 2017-03-14 14:37:17.841-0500

Thanks Mr. Colp,
I think we are beginning to make sense of this now.

By "allocated" it means locally for transmission. I am seeing the same sort of behavior in the 1st INVITE which has working RTP, so I guess there is no problem there. Asterisk is not ignoring the ports in the SDP as we first though, but is simply not sending anything to them to open them.
Since this is an echo, there is no other party to receive RTP from until we first send RTP from Asterisk to open the port.
So the only way we can get this to work is if Asterisk sends just one RTP packet to open the port, and that is where the problem lies.

Only an Answer() or Playback() seemed to solve our underlying issue with RTP and NAT. It works okay for opening the RTP port initially; but now we are sending a reINVITE to add an h264 stream to the call; and it doesn't look like there is anything we can do in dialplan to initiate RTP video to open that port.

We have experimented with just about all the NAT and media related options we could find.
https://github.com/asterisk/asterisk/blob/master/configs/samples/pjsip.conf.sample

I think what we need is an option in pjsip.conf which forces Asterisk to send an RTP packet to the port it receives in the SDP of an INVITE. Have I missed anything?

By: Joshua C. Colp (jcolp) 2017-03-14 14:42:29.187-0500

That is what the rtp_keepalive option is supposed to do. The fact it's not seemingly working for video too is a bug.

By: Jared Hull (fortytwo) 2017-03-14 14:56:10.672-0500

Yea I was hoping it would; this is what we have on our endpoints and trunk:
rtp_keepalive=1
rtp_symmetric=yes
force_rport=yes
direct_media=no

This results in working RTP for dialing to an extension, but sending a reINVITE does not punch through NAT for video.
exten => 142,1,Dial(PJSIP/143) ;This didn't used to work until an upgrade to 14.3 (not sure if that was the cause)

This results in ONLY a 100 Trying response (nothing else after, very strange) to the INVITE for an echo.
exten => 142,1,echo()

These result in working RTP for an echo, but sending a reINVITE does not punch through NAT for video.
exten => 142,1,answer()
same => n,echo()
exten => 143,1,Playback(silence/1)
same => n,echo()

By: Jared Hull (fortytwo) 2017-06-14 15:28:00.171-0500

I have attached a simple patch to enable keep alive for AST_MEDIA_TYPE_VIDEO.
I do not know the consequences of what I have done, and have done no serious testing.

By: Joshua C. Colp (jcolp) 2020-05-13 07:52:08.934-0500

Reporter has requested ASTERISK-28890 be used instead.