Merge "res_pjsip_session: Add ability to accept multiple sdp answers" into 13

13.23
Jenkins2 7 years ago committed by Gerrit Code Review
commit 6b6fa461d6

@ -34,6 +34,30 @@ app_confbridge
detection as the ConfbridgeTalking event, so bridges must be configured
with "talk_detection_events=yes" for this flag to have meaning.
res_pjsip
------------------
* Two new options have been added to the system and endpoint objects to
control whether, on outbound calls, Asterisk will accept updated SDP answers
during the initial INVITE transaction when 100rel is not in effect.
This usually happens when the INVITE is forked to multiple UASs and more
than one sends an SDP answer or when a single UAS needs to change a media
port to switch from custom ringback to the actual media destination.
The 'follow_early_media_forked' option sets whether Asterisk will accept
the updated SDP when the To tag on the subsequent response is different than
that on the the previous response. This usually occurs in the forked INVITE
scenario. The default value is "yes" which is the current behavior.
The 'accept_multiple_sdp_answers' flag sets whether Asterisk will accept the
updated SDP when the To tag on the subsequent response is the same as that
on the previous response. This can occur when a UAS needs to switch media
ports from custom ringback to the final media path. The default value is
"no" which is the current behavior.
These options have to be enabled system-wide in the system config section
of pjsip.conf as well as on individual endpoints that require the
functionality.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 13.20.0 to Asterisk 13.21.0 ----------
------------------------------------------------------------------------------

@ -789,6 +789,27 @@
; this mailbox will be used when notifying other modules
; of MWI status changes. If not set, incoming MWI
; NOTIFYs are ignored.
;follow_early_media_fork = ; On outgoing calls, if the UAS responds with
; different SDP attributes on subsequent 18X or 2XX
; responses (such as a port update) AND the To tag
; on the subsequent response is different than that
; on the previous one, follow it. This usually
; happens when the INVITE is forked to multiple UASs
; and more than 1 sends an SDP answer.
; This option must also be enabled in the system
; section.
; (default: yes)
;accept_multiple_sdp_answers =
; On outgoing calls, if the UAS responds with
; different SDP attributes on non-100rel 18X or 2XX
; responses (such as a port update) AND the To tag on
; the subsequent response is the same as that on the
; previous one, process it. This can happen when the
; UAS needs to change ports for some reason such as
; using a separate port for custom ringback.
; This option must also be enabled in the system
; section.
; (default: no)
;==========================AUTH SECTION OPTIONS=========================
;[auth]
@ -935,6 +956,27 @@
; Disabling this option has been known to cause interoperability
; issues, so disable at your own risk.
; (default: "yes")
;follow_early_media_fork = ; On outgoing calls, if the UAS responds with
; different SDP attributes on subsequent 18X or 2XX
; responses (such as a port update) AND the To tag
; on the subsequent response is different than that
; on the previous one, follow it. This usually
; happens when the INVITE is forked to multiple UASs
; and more than 1 sends an SDP answer.
; This option must also be enabled on endpoints that
; require this functionality.
; (default: yes)
;accept_multiple_sdp_answers =
; On outgoing calls, if the UAS responds with
; different SDP attributes on non-100rel 18X or 2XX
; responses (such as a port update) AND the To tag on
; the subsequent response is the same as that on the
; previous one, process it. This can happen when the
; UAS needs to change ports for some reason such as
; using a separate port for custom ringback.
; This option must also be enabled on endpoints that
; require this functionality.
; (default: no)
;type= ; Must be of type system (default: "")
;==========================GLOBAL SECTION OPTIONS=========================

59
configure vendored

@ -910,6 +910,10 @@ PBX_POPT
POPT_DIR
POPT_INCLUDE
POPT_LIB
PBX_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS
PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_DIR
PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_INCLUDE
PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_LIB
PBX_PJSIP_TSX_LAYER_FIND_TSX2
PJSIP_TSX_LAYER_FIND_TSX2_DIR
PJSIP_TSX_LAYER_FIND_TSX2_INCLUDE
@ -9254,6 +9258,9 @@ $as_echo "#define HAVE_PJSIP_AUTH_CLT_DEINIT 1" >>confdefs.h
$as_echo "#define HAVE_PJSIP_TSX_LAYER_FIND_TSX2 1" >>confdefs.h
$as_echo "#define HAVE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS 1" >>confdefs.h
@ -11384,6 +11391,18 @@ PBX_PJSIP_TSX_LAYER_FIND_TSX2=0
PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_DESCRIP="PJSIP INVITE Accept Multiple SDP Answers"
PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_OPTION=pjsip
PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_DIR=${PJPROJECT_DIR}
PBX_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS=0
fi
@ -25234,6 +25253,46 @@ $as_echo "#define HAVE_PJSIP_TLS_TRANSPORT_PROTO 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CPPFLAGS="${saved_cppflags}"
fi
if test "x${PBX_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS}" != "x1" -a "${USE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS}" != "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if \"pjsip_cfg()->endpt.accept_multiple_sdp_answers = 0;\" compiles using pjsip.h" >&5
$as_echo_n "checking if \"pjsip_cfg()->endpt.accept_multiple_sdp_answers = 0;\" compiles using pjsip.h... " >&6; }
saved_cppflags="${CPPFLAGS}"
if test "x${PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_DIR}" != "x"; then
PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_INCLUDE="-I${PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_DIR}/include"
fi
CPPFLAGS="${CPPFLAGS} ${PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS_INCLUDE}"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <pjsip.h>
int
main ()
{
pjsip_cfg()->endpt.accept_multiple_sdp_answers = 0;;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
PBX_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS=1
$as_echo "#define HAVE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }

@ -516,6 +516,7 @@ AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_EVSUB_GRP_LOCK], [PJSIP EVSUB Group Lock suppo
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_INV_SESSION_REF], [PJSIP INVITE Session Reference Count support], [PJPROJECT], [pjsip])
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_AUTH_CLT_DEINIT], [pjsip_auth_clt_deinit support], [PJPROJECT], [pjsip])
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TSX_LAYER_FIND_TSX2], [pjsip_tsx_layer_find_tsx2 support], [PJPROJECT], [pjsip])
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS], [PJSIP INVITE Accept Multiple SDP Answers], [PJPROJECT], [pjsip])
fi
AST_EXT_LIB_SETUP([POPT], [popt], [popt])
@ -2330,6 +2331,7 @@ if test "$USE_PJPROJECT" != "no" ; then
CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
LIBS="${LIBS} ${PJPROJECT_LIB}"
AST_C_COMPILE_CHECK([PJSIP_TLS_TRANSPORT_PROTO], [struct pjsip_tls_setting setting; int proto; proto = setting.proto;], [pjsip.h])
AST_C_COMPILE_CHECK([PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS], [pjsip_cfg()->endpt.accept_multiple_sdp_answers = 0;], [pjsip.h])
LIBS="${saved_libs}"
CPPFLAGS="${saved_cppflags}"

@ -0,0 +1,37 @@
"""Add early media options
Revision ID: 0be05c3a8225
Revises: d3e4284f8707
Create Date: 2018-06-18 17:26:16.737692
"""
# revision identifiers, used by Alembic.
revision = '0be05c3a8225'
down_revision = 'd3e4284f8707'
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import ENUM
YESNO_NAME = 'yesno_values'
YESNO_VALUES = ['yes', 'no']
def upgrade():
yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
op.add_column('ps_systems', sa.Column('follow_early_media_fork', yesno_values))
op.add_column('ps_systems', sa.Column('accept_multiple_sdp_answers', yesno_values))
op.add_column('ps_endpoints', sa.Column('follow_early_media_fork', yesno_values))
op.add_column('ps_endpoints', sa.Column('accept_multiple_sdp_answers', yesno_values))
def downgrade():
if op.get_context().bind.dialect.name == 'mssql':
op.drop_constraint('ck_ps_systems_follow_early_media_fork_yesno_values','ps_systems')
op.drop_constraint('ck_ps_systems_accept_multiple_sdp_answers_yesno_values','ps_systems')
op.drop_constraint('ck_ps_endpoints_follow_early_media_fork_yesno_values','ps_endpoints')
op.drop_constraint('ck_ps_endpoints_accept_multiple_sdp_answers_yesno_values','ps_endpoints')
op.drop_column('ps_systems', 'follow_early_media_fork')
op.drop_column('ps_systems', 'accept_multiple_sdp_answers')
op.drop_column('ps_endpoints', 'follow_early_media_fork')
op.drop_column('ps_endpoints', 'accept_multiple_sdp_answers')

@ -602,6 +602,10 @@
/* Define to 1 if PJPROJECT has the pjsip_get_dest_info support feature. */
#undef HAVE_PJSIP_GET_DEST_INFO
/* Define if your system has the PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS
headers. */
#undef HAVE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS
/* Define to 1 if PJPROJECT has the PJSIP INVITE Session Reference Count
support feature. */
#undef HAVE_PJSIP_INV_SESSION_REF

@ -791,6 +791,10 @@ struct ast_sip_endpoint {
unsigned int notify_early_inuse_ringing;
/*! If set, we'll push incoming MWI NOTIFYs to stasis using this mailbox */
AST_STRING_FIELD_EXTENDED(incoming_mwi_mailbox);
/*! Follow forked media with a different To tag */
unsigned int follow_early_media_fork;
/*! Accept updated SDPs on non-100rel 18X and 2XX responses with the same To tag */
unsigned int accept_multiple_sdp_answers;
};
/*! URI parameter for symmetric transport */

@ -1027,6 +1027,36 @@
changes. If not set, incoming MWI NOTIFYs are ignored.
</para></description>
</configOption>
<configOption name="follow_early_media_fork">
<synopsis>Follow SDP forked media when To tag is different</synopsis>
<description><para>
On outgoing calls, if the UAS responds with different SDP attributes
on subsequent 18X or 2XX responses (such as a port update) AND the
To tag on the subsequent response is different than that on the previous
one, follow it. This usually happens when the INVITE is forked to multiple
UASs and more than one sends an SDP answer.
</para>
<note><para>
This option must also be enabled in the <literal>system</literal>
section for it to take effect here.
</para></note>
</description>
</configOption>
<configOption name="accept_multiple_sdp_answers" default="no">
<synopsis>Accept multiple SDP answers on non-100rel responses</synopsis>
<description><para>
On outgoing calls, if the UAS responds with different SDP attributes
on non-100rel 18X or 2XX responses (such as a port update) AND the
To tag on the subsequent response is the same as that on the previous one,
process the updated SDP. This can happen when the UAS needs to change ports
for some reason such as using a separate port for custom ringback.
</para>
<note><para>
This option must also be enabled in the <literal>system</literal>
section for it to take effect here.
</para></note>
</description>
</configOption>
</configObject>
<configObject name="auth">
<synopsis>Authentication type</synopsis>
@ -1594,6 +1624,34 @@
request is too large. See RFC 3261 section 18.1.1.
</para></description>
</configOption>
<configOption name="follow_early_media_fork">
<synopsis>Follow SDP forked media when To tag is different</synopsis>
<description><para>
On outgoing calls, if the UAS responds with different SDP attributes
on subsequent 18X or 2XX responses (such as a port update) AND the
To tag on the subsequent response is different than that on the previous
one, follow it.
</para>
<note><para>
This option must also be enabled on endpoints that require
this functionality.
</para></note>
</description>
</configOption>
<configOption name="accept_multiple_sdp_answers">
<synopsis>Follow SDP forked media when To tag is the same</synopsis>
<description><para>
On outgoing calls, if the UAS responds with different SDP attributes
on non-100rel 18X or 2XX responses (such as a port update) AND the
To tag on the subsequent response is the same as that on the previous one,
process the updated SDP.
</para>
<note><para>
This option must also be enabled on endpoints that require
this functionality.
</para></note>
</description>
</configOption>
<configOption name="type">
<synopsis>Must be of type 'system'.</synopsis>
</configOption>

@ -52,6 +52,13 @@ struct system_config {
} threadpool;
/*! Nonzero to disable switching from UDP to TCP transport */
unsigned int disable_tcp_switch;
/*!
* Although early media is enabled in pjproject by default, it's only
* enabled when the To tags are different. These options allow turning
* on or off the feature for different tags and same tags.
*/
unsigned int follow_early_media_fork;
unsigned int accept_multiple_sdp_answers;
};
static struct ast_threadpool_options sip_threadpool_options = {
@ -96,6 +103,16 @@ static int system_apply(const struct ast_sorcery *system_sorcery, void *obj)
pjsip_cfg()->tsx.t1 = system->timert1;
pjsip_cfg()->tsx.td = system->timerb;
pjsip_cfg()->endpt.follow_early_media_fork = system->follow_early_media_fork;
#ifdef HAVE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS
pjsip_cfg()->endpt.accept_multiple_sdp_answers = system->accept_multiple_sdp_answers;
#else
if (system->accept_multiple_sdp_answers) {
ast_log(LOG_WARNING,
"The accept_multiple_sdp_answers flag is not supported in this version of pjproject. Ignoring\n");
}
#endif
if (system->compactheaders) {
extern pj_bool_t pjsip_use_compact_form;
@ -184,6 +201,10 @@ int ast_sip_initialize_system(void)
OPT_UINT_T, 0, FLDSET(struct system_config, threadpool.max_size));
ast_sorcery_object_field_register(system_sorcery, "system", "disable_tcp_switch", "yes",
OPT_BOOL_T, 1, FLDSET(struct system_config, disable_tcp_switch));
ast_sorcery_object_field_register(system_sorcery, "system", "follow_early_media_fork", "yes",
OPT_BOOL_T, 1, FLDSET(struct system_config, follow_early_media_fork));
ast_sorcery_object_field_register(system_sorcery, "system", "accept_multiple_sdp_answers", "no",
OPT_BOOL_T, 1, FLDSET(struct system_config, accept_multiple_sdp_answers));
ast_sorcery_load(system_sorcery);

@ -1854,6 +1854,8 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "refer_blind_progress", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, refer_blind_progress));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "notify_early_inuse_ringing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, notify_early_inuse_ringing));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "incoming_mwi_mailbox", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, incoming_mwi_mailbox));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "follow_early_media_fork", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, follow_early_media_fork));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accept_multiple_sdp_answers", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, accept_multiple_sdp_answers));
if (ast_sip_initialize_sorcery_transport()) {
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");

@ -3065,6 +3065,42 @@ static void session_inv_on_media_update(pjsip_inv_session *inv, pj_status_t stat
return;
}
if (session->endpoint) {
int bail = 0;
/*
* If following_fork is set, then this is probably the result of a
* forked INVITE and SDP asnwers coming from the different fork UAS
* destinations. In this case updated_sdp_answer will also be set.
*
* If only updated_sdp_answer is set, then this is the non-forking
* scenario where the same UAS just needs to change something like
* the media port.
*/
if (inv->following_fork) {
if (session->endpoint->follow_early_media_fork) {
ast_debug(3, "Following early media fork with different To tags\n");
} else {
ast_debug(3, "Not following early media fork with different To tags\n");
bail = 1;
}
}
#ifdef HAVE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS
else if (inv->updated_sdp_answer) {
if (session->endpoint->accept_multiple_sdp_answers) {
ast_debug(3, "Accepting updated SDP with same To tag\n");
} else {
ast_debug(3, "Ignoring updated SDP answer with same To tag\n");
bail = 1;
}
}
#endif
if (bail) {
return;
}
}
if ((status != PJ_SUCCESS) || (pjmedia_sdp_neg_get_active_local(inv->neg, &local) != PJ_SUCCESS) ||
(pjmedia_sdp_neg_get_active_remote(inv->neg, &remote) != PJ_SUCCESS)) {
ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);

@ -87,6 +87,7 @@ AC_DEFUN([_PJPROJECT_CONFIGURE],
AC_DEFINE([HAVE_PJSIP_INV_SESSION_REF], 1, [Define if your system has PJSIP_INV_SESSION_REF])
AC_DEFINE([HAVE_PJSIP_AUTH_CLT_DEINIT], 1, [Define if your system has pjsip_auth_clt_deinit declared.])
AC_DEFINE([HAVE_PJSIP_TSX_LAYER_FIND_TSX2], 1, [Define if your system has pjsip_tsx_layer_find_tsx2 declared.])
AC_DEFINE([HAVE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS], 1, [Define if your system has HAVE_PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS declared.])
AC_SUBST([PJPROJECT_BUNDLED])
AC_SUBST([PJPROJECT_DIR])

@ -0,0 +1,215 @@
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
Loading…
Cancel
Save