mirror of http://gerrit.asterisk.org/asterisk
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 Beerchanges/77/9277/3
parent
017b7849bc
commit
880fbff6b7
@ -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')
|
@ -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…
Reference in new issue