From dd7031bfb7848a2a1dd1e6b12883652f134c3c6c Mon Sep 17 00:00:00 2001 From: Matthew Jordan Date: Fri, 17 Oct 2014 13:35:21 +0000 Subject: res_pjsip_session/res_pjsip_sdp_rtp: Be more tolerant of offers When an inbound SDP offer is received, Asterisk currently makes a few incorrection assumptions: (1) If the offer contains more than a single audio/video stream, Asterisk will reject the entire stream with a 488. This is an overly strict response; generally, Asterisk should accept the media streams that it can accept and decline the others. (2) If the offer contains a declined media stream, Asterisk will attempt to process it anyway. This can result in attempting to match format capabilities on a declined media stream, leading to a 488. Asterisk should simply ignore declined media streams. (3) Asterisk will currently attempt to handle offers with AVPF with use_avpf=No/AVP with use_avpf=Yes. This mismatch results in invalid SDP answers being sent in response. If there is a mismatch between the media type being offered and the configuration, Asterisk must reject the offer with a 488. This patch does the following: * Asterisk will accept SDP offers with at least one media stream that it can use. Some WARNING messages have been dropped to NOTICEs as a result. * Asterisk will not accept an offer with a media type that doesn't match its configuration. * Asterisk will ignore declined media streams properly. #SIPit31 Review: https://reviewboard.asterisk.org/r/4063/ ASTERISK-24122 #close Reported by: James Van Vleet ASTERISK-24381 #close Reported by: Matt Jordan ........ Merged revisions 425868 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@425879 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- res/res_pjsip_sdp_rtp.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'res/res_pjsip_sdp_rtp.c') diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c index 2aa8acc38..1f863008f 100644 --- a/res/res_pjsip_sdp_rtp.c +++ b/res/res_pjsip_sdp_rtp.c @@ -247,9 +247,10 @@ static int set_caps(struct ast_sip_session *session, struct ast_sip_session_medi struct ast_str *thembuf = ast_str_alloca(64); ast_rtp_codecs_payloads_destroy(&codecs); - ast_log(LOG_WARNING, "No joint capabilities between our configuration(%s) and incoming SDP(%s)\n", - ast_format_cap_get_names(peer, &usbuf), - ast_format_cap_get_names(caps, &thembuf)); + ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n", + session_media->stream_type, + ast_format_cap_get_names(caps, &usbuf), + ast_format_cap_get_names(peer, &thembuf)); return -1; } @@ -521,12 +522,11 @@ static enum ast_sip_session_media_encryption check_endpoint_media_transport( const struct pjmedia_sdp_media *stream) { enum ast_sip_session_media_encryption incoming_encryption; + char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1]; - if (endpoint->media.rtp.use_avpf) { - char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1]; - if (transport_end != 'F') { - return AST_SIP_MEDIA_TRANSPORT_INVALID; - } + if ((transport_end == 'F' && !endpoint->media.rtp.use_avpf) + || (transport_end != 'F' && endpoint->media.rtp.use_avpf)) { + return AST_SIP_MEDIA_TRANSPORT_INVALID; } incoming_encryption = get_media_encryption_type(stream->desc.transport); @@ -727,8 +727,15 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr); enum ast_media_type media_type = stream_to_media_type(session_media->stream_type); + /* If port is 0, ignore this media stream */ + if (!stream->desc.port) { + ast_debug(3, "Media stream '%s' is already declined\n", session_media->stream_type); + return 0; + } + /* If no type formats have been configured reject this stream */ if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) { + ast_debug(3, "Endpoint has no codecs for media type '%s', declining stream\n", session_media->stream_type); return 0; } @@ -760,7 +767,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct } if (set_caps(session, session_media, stream)) { - return -1; + return 0; } return 1; } @@ -1061,6 +1068,10 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a return 1; } + if (!local_stream->desc.port || !remote_stream->desc.port) { + return 1; + } + /* Ensure incoming transport is compatible with the endpoint's configuration */ if (!session->endpoint->media.rtp.use_received_transport && check_endpoint_media_transport(session->endpoint, remote_stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) { @@ -1088,7 +1099,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a ast_sockaddr_set_port(addrs, remote_stream->desc.port); ast_rtp_instance_set_remote_address(session_media->rtp, addrs); if (set_caps(session, session_media, local_stream)) { - return -1; + return 1; } if ((fdno = media_type_to_fdno(media_type)) < 0) { -- cgit v1.2.3