mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-30 02:26:23 +00:00
216 lines
8.1 KiB
Diff
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
|
||
|
|