-
Notifications
You must be signed in to change notification settings - Fork 359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RTP Engine doesn't send audio on NAT scenario with Re-INVITE #817
Comments
I suspect this is a case of the peer address learning feature interfering with the endpoint switching. Check your logs for lines If you don't require the peer address learning feature (e.g. none of your clients are behind NAT and the addresses in the SDP are always correct), you can use the |
Hi rfuchs, and thanks for the quick reply! I also had exactly the same thinking as you described, but what I see is that the IPs in the lines with
What seems even stranger to me is: if the problem happens because of the address learning feature, doesn't RTPEngine should be able to understand that it is sending audio to itself before the re-negotiation is requested, and then, after asterisk requests the re-negotiation, it needs to "forget" that "old"/learned IP address (which is actually its own) and start sending audio to the new address that is requested on the re-negotiation (which is the correct asterisk's address)? I also failed to mention but I really need the address learning feature because I can't assure that my clients will never be behind NAT. |
Unfortunately there's no way to support both NAT detection AND dynamic endpoint switching at the same time. Rtpengine sending audio to itself is actually a valid use case. And rtpengine does "forget" the old learned address after receiving a signalling event, but I suspect that in your case, it then still receives some audio packets from the old endpoint, and possibly also audio packets from the new endpoint, and has no of distinguishing the two, and so will learn the address if whichever packet is received last just before the learning timeout kicks in. The only thing you can try is to increase the length of time that rtpengine waits after a signalling event before committing to a learned address. This is not configurable but you can change it in the code at https://github.com/sipwise/rtpengine/blob/master/daemon/media_socket.c#L1579 |
@JRequeijo could you solve this? |
Could you please take a look #1139 and see if it is the same as yours? Thanks, |
@ecarruda @magixyu sorry for the late reply. I couldn't solve this issue and so I stopped using rtpengine and integrated with a commercial SBC provider that handles all the media flows. It has been a long time since I opened this issue so I don't really recall the details to ensure if it is the same as #1139 or not. When I get some free time, I'll try to recall the details of the problem I had back then and then try to compare it with #1139. Thanks |
Hi @rfuchs ! I faced the similar issue like this one.
audio port is 34150
RTP port has been changed from 34150 to 30840, but after offer second INVITE operator sent one RTP packet from old UDP port. Operator is waiting media from us on new port and didn't send RTP to us. But RTPengine learned to send media to old port and we have no audio issue. I added fix of this issue (add skipping first 5 packets after answer/offer) and it works for me, but I'm interesting to deliver this change to community as well (if it's correct)
Thanks in advance |
This should already be handled by the |
exactly, you are right, but RTP packet from old port came after answer and rtpengine learned to this old port.
in my case operator did't send any RTP packets from the new port, it is waiting RTP from us, but rtpengine didn't send RTP to new port, because it learned to old one. |
Ah I see, you want to suppress the learning of a new address completely for a short while, and not just the confirmation of a learned address. I feel that using a hard-coded number of packets to wait out for this is a bit of a hack and that there should be a better solution. One approach that comes to mind: Use a timer similar to |
This fixes a race condition: Peer sends updated SDP with new address, but an older RTP packet from the old address is received afterwards. Thsi triggers learning of this old address is the "correct" endpoint. Afterwards the peer stops sending RTP until a packet to the new endpoint is received there, which never happens because the new endpoint has been discarded in favour of the "learned" old one. closes #817 Change-Id: I508f465a669f03e35ddcc6e770d5e7859e57569f
So that would look something like 2ad51fa Untested |
Hi @rfuchs! Thank you! |
Not a typo - the bool type is valid and already in use elsewhere. |
Ah, sorry, I use older version, without bool type |
As for me the issue has been solved, probably make sense to close this issue... Thank you @rfuchs, as usual :) |
This fixes a race condition: Peer sends updated SDP with new address, but an older RTP packet from the old address is received afterwards. Thsi triggers learning of this old address is the "correct" endpoint. Afterwards the peer stops sending RTP until a packet to the new endpoint is received there, which never happens because the new endpoint has been discarded in favour of the "learned" old one. closes #817 Change-Id: I508f465a669f03e35ddcc6e770d5e7859e57569f (cherry picked from commit 45bd10d)
This fixes a race condition: Peer sends updated SDP with new address, but an older RTP packet from the old address is received afterwards. Thsi triggers learning of this old address is the "correct" endpoint. Afterwards the peer stops sending RTP until a packet to the new endpoint is received there, which never happens because the new endpoint has been discarded in favour of the "learned" old one. closes #817 Change-Id: I508f465a669f03e35ddcc6e770d5e7859e57569f (cherry picked from commit 45bd10d)
This fixes a race condition: Peer sends updated SDP with new address, but an older RTP packet from the old address is received afterwards. Thsi triggers learning of this old address is the "correct" endpoint. Afterwards the peer stops sending RTP until a packet to the new endpoint is received there, which never happens because the new endpoint has been discarded in favour of the "learned" old one. closes #817 Change-Id: I508f465a669f03e35ddcc6e770d5e7859e57569f (cherry picked from commit 45bd10d)
This fixes a race condition: Peer sends updated SDP with new address, but an older RTP packet from the old address is received afterwards. Thsi triggers learning of this old address is the "correct" endpoint. Afterwards the peer stops sending RTP until a packet to the new endpoint is received there, which never happens because the new endpoint has been discarded in favour of the "learned" old one. closes #817 Change-Id: I508f465a669f03e35ddcc6e770d5e7859e57569f (cherry picked from commit 45bd10d)
Hello,
I have a NAT environment with RTPEngine + Kamailio + Asterisk.
The system components IP addresses are:
NOTE: Understand the XXX in the addresses as "masks" of my public IPs for confidentiality purposes.
So Asterisk is only accessible internally through its private IP by Kamailio and RTPEngine.
All the calls enter the system via Kamailio and are forwarded to Asterisk.
All the audio enters and leaves the system via RTPEngine.
When a call is made between 2 peers, the audio between them INITIALLY flows through both RTPEngine and Asterisk, i.e.:
So the complete audio flow is:
NOTE: all the audio between the peers and RTPEngine flows through the RTPEngine's public address. All the audio between Asterisk and RTPEngine leaves Asterisk through its private address (10.51.0.15) and enters RTPEngine through its public address 13.74.XXX.XXX.
After the call is established between the 2 peers, Asterisk will "delegate" the audio flow only to RTPEngine, sending Re-INVITES to the peers, re-negotiating the audio endpoints.
The audio flow is therefore changed to:
Up to this point everything works fine EVERY time.
PROBLEM:
From this point on, when Asterisk needs to play some file or to record the call legs, it re-negotiates the audio endpoints again with re-INVITES, so the final flow becomes equal to the initial one, i.e.:
In this step the problem occurs, because sometimes (ONLY SOMETIMES), RTPEngine mixes up the IP addresses in the 2nd re-negotiation and, in the end, it reaches a state where it doesn't send any audio to Asterisk at all.
What I can see on RTPEngine's log files is:
CASE 1 WHERE EVERYTHING WORKS FINE:
CASE 2 WHERE EVERYTHING WORKS FINE:
CASE 3 WHERE PROBLEM OCCURS:
So I see that, in case 3 (when the problem happens), RTPEngine tries to send audio to it public IP (13.74.XXX.XXX) after the re-negotiation, i.e.:
instead of sending it to the private IP of Asterisk, as request by Asterisk in the re-negotiation.
What is also stranger is:
The IP (13.79.XXX.XXX) actually belongs to another application/component of my system that is not even related to SIP or telephony, but somehow RTPEngine is picking it up from the network.
Can anyone help to explain what may be happening on RTPEngine so that (ONLY SOMETIMES) it sends audio to its public IP after the re-negotiation, instead of sending it to Asterisk?
The RTPEngine's configuration file is:
The flags that Kamailio passes to RTPEngine through rtpengine_manage() are:
The text was updated successfully, but these errors were encountered: