From bfc93cc95428532e89ac8ffd72084dc1c811229b Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 27 Dec 2019 08:04:42 -0500 Subject: [PATCH] chan_pjsip: Ignore RTP that we haven't negotiated If chan_pjsip receives an RTP packet whose payload differs from the channel's native format, and asymmetric_rtp_codec is disabled (the default), Asterisk will switch the channel's native format to match that of the incoming packet without regard to the negotiated payloads. We now keep track of the formats that have been negotiated and check before switching payloads which results in these packets being dropped instead of causing the session to terminate. ASTERISK-28139 #close Reported by: Paul Brooks Change-Id: Icc3b85cee1772026cee5dc1b68459bf9431c14a3 --- channels/chan_pjsip.c | 3 ++- include/asterisk/res_pjsip_session.h | 2 ++ res/res_pjsip_sdp_rtp.c | 3 +++ res/res_pjsip_session.c | 5 +++++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 33abe03209..c4281c32da 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -771,7 +771,8 @@ static struct ast_frame *chan_pjsip_read(struct ast_channel *ast) * raw read format BEFORE the native format check */ if (!session->endpoint->asymmetric_rtp_codec && - ast_format_cmp(ast_channel_rawwriteformat(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) { + ast_format_cmp(ast_channel_rawwriteformat(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL && + ast_format_cap_iscompatible_format(session->joint_caps, f->subclass.format) == AST_FORMAT_CMP_EQUAL) { struct ast_format_cap *caps; /* For maximum compatibility we ensure that the formats match that of the received media */ diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h index 9ae1883d04..38df3fd165 100644 --- a/include/asterisk/res_pjsip_session.h +++ b/include/asterisk/res_pjsip_session.h @@ -167,6 +167,8 @@ struct ast_sip_session { enum ast_sip_dtmf_mode dtmf; /*! Initial incoming INVITE Request-URI. NULL otherwise. */ pjsip_uri *request_uri; + /*! Joint capabilities */ + struct ast_format_cap *joint_caps; }; typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata); diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c index 98e981965f..36b60444d3 100644 --- a/res/res_pjsip_sdp_rtp.c +++ b/res/res_pjsip_sdp_rtp.c @@ -408,6 +408,9 @@ static int set_caps(struct ast_sip_session *session, struct ast_sip_session_medi if (session->channel) { ast_channel_lock(session->channel); + ast_format_cap_remove_by_type(session->joint_caps, media_type); + ast_format_cap_append_from_cap(session->joint_caps, joint, media_type); + ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_UNKNOWN); ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(session->channel), AST_MEDIA_TYPE_UNKNOWN); diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index bbdb8d148a..b61b0fd917 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -1351,6 +1351,7 @@ static void session_destructor(void *obj) ao2_cleanup(session->aor); ao2_cleanup(session->contact); ao2_cleanup(session->req_caps); + ao2_cleanup(session->joint_caps); ao2_cleanup(session->direct_media_cap); ast_dsp_free(session->dsp); @@ -1433,6 +1434,10 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint, if (!session->req_caps) { return NULL; } + session->joint_caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + if (!session->joint_caps) { + return NULL; + } session->datastores = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, DATASTORE_BUCKETS, datastore_hash, NULL, datastore_cmp); if (!session->datastores) {