Files
asterisk/third-party/pjproject/patches/0100-sip_inv-Add-option-to-accept-updated-SDP-on-same-To-.patch
George Joseph 880fbff6b7 res_pjsip_session: Add ability to accept multiple sdp answers
pjproject by default currently will follow media forked during an INVITE
on outbound calls if the To tag is different on a subsequent response as
that on an earlier response.  We handle this correctly.  There have
been reported cases where the To tag is the same but we still need to
follow the media.  The pjproject patch in this commit adds the
capability to sip_inv and also adds the capability to control it at
runtime.  The original "different tag" behavior was always controllable
at runtime but we never did anything with it and left it to default to
TRUE.

So, along with the pjproject patch, this commit adds options to both the
system and endpoint objects to control the two behaviors, and a small
logic change to session_inv_on_media_update in res_pjsip_session to
control the behavior at the endpoint level.

The default behavior for "different tags" remains the same at TRUE and
the default for "same tag" is FALSE.

Change-Id: I64d071942b79adb2f0a4e13137389b19404fe3d6
ASTERISK-27936
Reported-by: Ross Beer
2018-06-26 07:05:34 -06:00

216 lines
8.1 KiB
Diff

From 13e20772cd3c8735a6b78e30391a33f3eba4c023 Mon Sep 17 00:00:00 2001
From: George Joseph <gjoseph@digium.com>
Date: Fri, 22 Jun 2018 09:33:34 -0600
Subject: [PATCH] sip_inv: Add option to accept updated SDP on same To tag
Currently, setting pjsip_cfg()->endpt.follow_early_media_fork allows
sip_inv to process media updates when the To tag is different. There
are some cases where media updates need to be processed when the tags
are the same. Since removing the requirement for different tags would
change default behavior, a new option "accept_multiple_sdp_answers"
has been added along with a new pjsip_inv_session flag
"updated_sdp_answer" to indicate under which condition we're
updating.
The logic was also updated to more closely follow RFC6337 in that
if 100rel is efffect, do not accept updated SDPs.
See
https://tools.ietf.org/html/rfc6337#section-3.1.1
for more information.
---
pjsip/include/pjsip-ua/sip_inv.h | 2 ++
pjsip/include/pjsip/sip_config.h | 25 ++++++++++++++++
pjsip/src/pjsip-ua/sip_inv.c | 62 +++++++++++++++++++++++++---------------
pjsip/src/pjsip/sip_config.c | 3 +-
4 files changed, 68 insertions(+), 24 deletions(-)
diff --git a/pjsip/include/pjsip-ua/sip_inv.h b/pjsip/include/pjsip-ua/sip_inv.h
index 1bb7b8adc..77ef070c3 100644
--- a/pjsip/include/pjsip-ua/sip_inv.h
+++ b/pjsip/include/pjsip-ua/sip_inv.h
@@ -442,6 +442,8 @@ struct pjsip_inv_session
pj_bool_t following_fork; /**< Internal, following
forked media? */
pj_atomic_t *ref_cnt; /**< Reference counter. */
+ pj_bool_t updated_sdp_answer; /**< SDP answer just been
+ updated? */
};
diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h
index b3a9468e2..b7cf6feed 100644
--- a/pjsip/include/pjsip/sip_config.h
+++ b/pjsip/include/pjsip/sip_config.h
@@ -157,6 +157,17 @@ typedef struct pjsip_cfg_t
*/
pj_bool_t disable_secure_dlg_check;
+ /**
+ * Accept multiple SDP answers on non-reliable 18X responses and the 2XX
+ * response when they are all received from the same source (same To tag).
+ *
+ * See also:
+ * https://tools.ietf.org/html/rfc6337#section-3.1.1
+ *
+ * Default is PJSIP_ACCEPT_MULTIPLE_SDP_ANSWERS.
+ */
+ pj_bool_t accept_multiple_sdp_answers;
+
} endpt;
/** Transaction layer settings. */
@@ -402,6 +413,20 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
#endif
+/**
+ * Accept multiple SDP answers on non-reliable 18X responses and the 2XX
+ * response when they are all received from the same source (same To tag).
+ *
+ * This option can also be controlled at run-time by the
+ * \a accept_multiple_sdp_answers setting in pjsip_cfg_t.
+ *
+ * Default is PJ_FALSE.
+ */
+#ifndef PJSIP_ACCEPT_MULTIPLE_SDP_ANSWERS
+# define PJSIP_ACCEPT_MULTIPLE_SDP_ANSWERS PJ_TRUE
+#endif
+
+
/**
* Specify whether "alias" param should be added to the Via header
* in any outgoing request with connection oriented transport.
diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
index c9686a088..c22726bad 100644
--- a/pjsip/src/pjsip-ua/sip_inv.c
+++ b/pjsip/src/pjsip-ua/sip_inv.c
@@ -162,6 +162,7 @@ struct tsx_inv_data
pj_bool_t retrying; /* Resend (e.g. due to 401/407) */
pj_str_t done_tag; /* To tag in RX response with answer */
pj_bool_t done_early;/* Negotiation was done for early med? */
+ pj_bool_t done_early_rel;/* Early med was realiable? */
pj_bool_t has_sdp; /* Message with SDP? */
};
@@ -2000,18 +2001,20 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,
/* Initialize info that we are following forked media */
inv->following_fork = PJ_FALSE;
+ inv->updated_sdp_answer = PJ_FALSE;
/* MUST NOT do multiple SDP offer/answer in a single transaction,
- * EXCEPT if:
- * - this is an initial UAC INVITE transaction (i.e. not re-INVITE), and
- * - the previous negotiation was done on an early media (18x) and
- * this response is a final/2xx response, and
- * - the 2xx response has different To tag than the 18x response
- * (i.e. the request has forked).
+ * EXCEPT previous nego was in 18x (early media) and any of the following
+ * condition is met:
+ * - Non-forking scenario:
+ * - 'accept_multiple_sdp_answers' is set, and
+ * - previous early response was not reliable (rfc6337 section 3.1.1).
+ * - Forking scenario:
+ * - This response has different To tag than the previous response, and
+ * - This response is 18x/2xx (early or final). If this is 18x,
+ * only do multiple SDP nego if 'follow_early_media_fork' is set.
*
- * The exception above is to add a rudimentary support for early media
- * forking (sample case: custom ringback). See this ticket for more
- * info: http://trac.pjsip.org/repos/ticket/657
+ * See also ticket #657, #1644, #1764 for more info.
*/
if (tsx_inv_data->sdp_done) {
pj_str_t res_tag;
@@ -2020,21 +2023,29 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,
res_tag = rdata->msg_info.to->tag;
st_code = rdata->msg_info.msg->line.status.code;
- /* Allow final/early response after SDP has been negotiated in early
- * media, IF this response is a final/early response with different
- * tag.
- * See ticket #1644 and #1764 for forked early media case.
- */
- if (tsx->role == PJSIP_ROLE_UAC &&
- (st_code/100 == 2 ||
- (st_code/10 == 18 /* st_code == 18x */
- && pjsip_cfg()->endpt.follow_early_media_fork)) &&
- tsx_inv_data->done_early &&
- pj_stricmp(&tsx_inv_data->done_tag, &res_tag))
+ if (tsx->role == PJSIP_ROLE_UAC && tsx_inv_data->done_early &&
+ (
+ /* Non-forking scenario */
+ (
+ !tsx_inv_data->done_early_rel &&
+ (st_code/100 == 2 || st_code/10 == 18) &&
+ pjsip_cfg()->endpt.accept_multiple_sdp_answers &&
+ !pj_stricmp(&tsx_inv_data->done_tag, &res_tag)
+ )
+ ||
+ /* Forking scenario */
+ (
+ (st_code/100 == 2 ||
+ (st_code/10 == 18 &&
+ pjsip_cfg()->endpt.follow_early_media_fork)) &&
+ pj_stricmp(&tsx_inv_data->done_tag, &res_tag)
+ )
+ )
+ )
{
const pjmedia_sdp_session *reoffer_sdp = NULL;
- PJ_LOG(4,(inv->obj_name, "Received forked %s response "
+ PJ_LOG(4,(inv->obj_name, "Received %s response "
"after SDP negotiation has been done in early "
"media. Renegotiating SDP..",
(st_code/10==18? "early" : "final" )));
@@ -2054,7 +2065,9 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,
return status;
}
- inv->following_fork = PJ_TRUE;
+ inv->following_fork = !!pj_stricmp(&tsx_inv_data->done_tag,
+ &res_tag);
+ inv->updated_sdp_answer = PJ_TRUE;
} else {
@@ -2135,6 +2148,7 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,
PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER)
{
int status_code;
+ pjsip_msg *msg = rdata->msg_info.msg;
/* This is an answer.
* Process and negotiate remote answer.
@@ -2161,8 +2175,10 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,
*/
tsx_inv_data->sdp_done = 1;
- status_code = rdata->msg_info.msg->line.status.code;
+ status_code = msg->line.status.code;
tsx_inv_data->done_early = (status_code/100==1);
+ tsx_inv_data->done_early_rel = tsx_inv_data->done_early &&
+ pjsip_100rel_is_reliable(rdata);
pj_strdup(tsx->pool, &tsx_inv_data->done_tag,
&rdata->msg_info.to->tag);
diff --git a/pjsip/src/pjsip/sip_config.c b/pjsip/src/pjsip/sip_config.c
index 3576f351e..316824a00 100644
--- a/pjsip/src/pjsip/sip_config.c
+++ b/pjsip/src/pjsip/sip_config.c
@@ -34,7 +34,8 @@ pjsip_cfg_t pjsip_sip_cfg_var =
PJSIP_FOLLOW_EARLY_MEDIA_FORK,
PJSIP_REQ_HAS_VIA_ALIAS,
PJSIP_RESOLVE_HOSTNAME_TO_GET_INTERFACE,
- 0
+ 0,
+ PJSIP_ACCEPT_MULTIPLE_SDP_ANSWERS
},
/* Transaction settings */
--
2.14.4