Skip to content
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

Replace transport protocol only if protocol was specified in flags #432

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

arkadiam
Copy link

Setup: Polycom phone with SDES (optional) -- Kamailio + Rtpengine -- Asterisk PBX

On initial INVITE Polycom sends SDP with:
m=audio 2278 RTP/SAVP
m=audio 2278 RTP/AVP
m=video 2280 RTP/SAVP
m=video 2280 RTP/AVP

Kmailio calls rtpengine_manage() with flags:
"direction=pub direction=priv replace-origin replace-session-connection ICE=remove SDES-off"

INVITE passed to Asterisk with the same media options (different port numbers). Asterisk is configured only to accept audio RTP. Call is answered and media goes like:
Polycom -- SRTP -- rtpengine -- RTP -- Asterisk.

Now Polycom puts call on HOLD. That produce INVITE with SDP like:
m=audio 2278 RTP/SAVP
m=audio 2278 RTP/AVP
m=video 0 RTP/SAVP
m=video 0 RTP/AVP

At this point, by some reason, Rtpengine replaces transport protocol with RTP/AVP and Asterisk presented with such media options:
m=audio xxx RTP/AVP
m=audio xxx RTP/AVP
m=video 0 RTP/AVP
m=video 0 RTP/AVP
Multiple RTP/AVP for audio confuses the Asterisk and it rejects the INVITE with 488.

Patch in this pull request prevents protocol replacement if it wasn't set in "flags".
It allows RE-INVITE to pass and present Asterisk valid media options:
m=audio xxx RTP/SAVP
m=audio xxx RTP/AVP
m=video 0 RTP/SAVP
m=video 0 RTP/AVP

This may potentially fix issues #275 and #393

@rfuchs
Copy link
Member

rfuchs commented Dec 18, 2017

Can you post a concrete example of a call going wrong? Debug log containing the SDP bodies would be great.

I don't believe this is a the correct patch to fix this. Rtpengine is supposed to remember the protocols used by clients that it talked to before, and is supposed to insert the correct transport protocol without being instructed to (or even when not instructed to do anything).

@arkadiam
Copy link
Author

Thanks for looking at it.
Please find the logs of a test call attached.
It follows calls scenario I've originally described: Polycom phone places a call, call is answered, then Polycom phone puts call on Hold, then it Resumes the call.

The issue corresponds to the log line 53 where Rtpengine translates one of "m=audio" to RTP/AVP.

rtpengine-20171218.log.txt

@rfuchs
Copy link
Member

rfuchs commented Dec 21, 2017

I believe the problem stems from the way Asterisk responds to the multi-stream SDP.

Polycom offers 4 media streams: audio SRTP, audio RTP, video SRTP, video RTP.
Asterisk then answers with only 2 media streams: audio RTP, video RTP (disabled)

My understanding of RFC 3264 (section 6) is that media descriptions in the SDP (m= lines) in the answer must match up with media descriptions given in the offer. So if the offer contains 4 media streams, the answer must also contain 4 media streams. Asterisk doesn't do this.

The result is that rtpengine matches up the first media stream from Polycom with the first media stream from Asterisk, thus it thinks that Polycom wants to speak SRTP there while Asterisk wants to speak RTP. It remembers this and in the subsequent re-offer substitutes the appropriate transport protocol.

A correct response from Asterisk (IMO and from my understanding of the RFC) would be to generate an SDP answer with 4 media streams, with the same types and protocols as the original offer, and all of them except the second one (audio RTP) disabled (zero port).

@arkadiam
Copy link
Author

Asterisk version we have to work with, doesn't support SRTP. Unsupported media are being ignored without producing zero-port m-line records. I agree with your RFC3264 interpretation.

I can try to modify Asterisk code to return 4 media streams like:
m=audio 0 RTP/SAVP
m=audio 2278 RTP/AVP
m=video 0 RTP/SAVP
m=video 0 RTP/AVP

BUT I'm not sure if in this case the media path will be:
Polycom -- SRTP -- rtpengine -- RTP -- Asterisk.
I think it might be turned into:
Polycom -- RTP -- rtpengine -- RTP -- Asterisk.
which is not our intention. We would like to keep the first call leg secure.

I don't see how rtpengine_manage() can be called with any other flags to achieve SRTP-RTP conversion. Specifying transport protocol: "RTP/AVP" will turn initial SDP into:
m=audio 2278 RTP/AVP
m=audio 2278 RTP/AVP
m=video 0 RTP/AVP
m=video 0 RTP/AVP
which will be rejected by Asterisk due to duplicate values.

@rfuchs
Copy link
Member

rfuchs commented Dec 22, 2017

Ah no, actually you're right. It would be RTP both ways. I suppose in the offer, you have to specify RTP/AVP. (This sort of alternative protocol selection isn't supported by rtpengine. I'm not sure if there's an RFC for it, but I guess it could be implemented anyway.)

@rfuchs
Copy link
Member

rfuchs commented Dec 22, 2017

A possible workaround for the Asterisk side of this is to make rtpengine recognize this situation (m= lines missing) and attempt to match up the lines as Asterisk thinks they should match up (possibly by internally filling up the missing media streams with dummy entries). See __get_media and its invocation in monologue_offer_answer

@rfuchs
Copy link
Member

rfuchs commented Jan 2, 2018

#435 is related

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants