diff --git a/CHANGES b/CHANGES index 60d8a4dea1..4fd7b96cd7 100644 --- a/CHANGES +++ b/CHANGES @@ -106,6 +106,13 @@ res_pjsip RECOMMENDED), keep the current behavior, or trigger only on pjsip taskprocessor overloads. +chan_pjsip +------------------ + * A new configuration parameter 'ignore_183_without_sdp' has been added + to the pjsip.conf "endpoints" section. If enabled, will make chan_pjsip + discard 183s that do not contain an SDP body, which can resolve no + ringback tone issues as well as making the behavior match chan_sip. + MWI ------------------ * A new module "res_mwi_devstate" has been added that allows subscriptions diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index e44f3283dc..55cd9edd56 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -3014,7 +3014,14 @@ static void chan_pjsip_incoming_response(struct ast_sip_session *session, struct ast_channel_unlock(session->channel); break; case 183: - ast_queue_control(session->channel, AST_CONTROL_PROGRESS); + if (session->endpoint->ignore_183_without_sdp) { + pjsip_rdata_sdp_info *sdp = pjsip_rdata_get_sdp_info(rdata); + if (sdp && sdp->body.ptr) { + ast_queue_control(session->channel, AST_CONTROL_PROGRESS); + } + } else { + ast_queue_control(session->channel, AST_CONTROL_PROGRESS); + } break; case 200: ast_queue_control(session->channel, AST_CONTROL_ANSWER); diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index 6beb52bd7e..522a091eb1 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -858,6 +858,15 @@ ; headers are received. This option allows the ; 'Q.850' Reason header to be suppressed. ; (default: no) +;ignore_183_without_sdp = + ; Do not forward 183 when it doesn't contain SDP. + ; Certain SS7 internetworking scenarios can result in + ; a 183 to be generated for reasons other than early + ; media. Forwarding this 183 can cause loss of + ; ringback tone. This flag emulates the behavior of + ; chan_sip and prevents these 183 responses from + ; being forwarded. + ; (default: no) ;==========================AUTH SECTION OPTIONS========================= ;[auth] diff --git a/contrib/ast-db-manage/config/versions/80473bad3c16_ignore_183_without_sdp.py b/contrib/ast-db-manage/config/versions/80473bad3c16_ignore_183_without_sdp.py new file mode 100644 index 0000000000..d05e2d5658 --- /dev/null +++ b/contrib/ast-db-manage/config/versions/80473bad3c16_ignore_183_without_sdp.py @@ -0,0 +1,38 @@ +"""ignore 183 without sdp + +Revision ID: 80473bad3c16 +Revises: f3c0b8695b66 +Create Date: 2019-03-04 08:30:51.592907 + +""" + +# revision identifiers, used by Alembic. +revision = '80473bad3c16' +down_revision = 'f3c0b8695b66' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects.postgresql import ENUM + +AST_BOOL_NAME = 'ast_bool_values' +# We'll just ignore the n/y and f/t abbreviations as Asterisk does not write +# those aliases. +AST_BOOL_VALUES = [ '0', '1', + 'off', 'on', + 'false', 'true', + 'no', 'yes' ] + +def upgrade(): + ############################# Enums ############################## + + # ast_bool_values has already been created, so use postgres enum object + # type to get around "already created" issue - works okay with mysql + ast_bool_values = ENUM(*AST_BOOL_VALUES, name=AST_BOOL_NAME, create_type=False) + + op.add_column('ps_endpoints', sa.Column('ignore_183_without_sdp', ast_bool_values)) + +def downgrade(): + if op.get_context().bind.dialect.name == 'mssql': + op.drop_constraint('ck_ps_endpoints_ignore_183_without_sdp_ast_bool_values', 'ps_endpoints') + op.drop_column('ps_endpoints', 'ignore_183_without_sdp') + pass diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index fd053b36f8..335b3e53d7 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -845,6 +845,8 @@ struct ast_sip_endpoint { unsigned int notify_early_inuse_ringing; /*! Suppress Q.850 Reason headers on this endpoint */ unsigned int suppress_q850_reason_headers; + /*! Ignore 183 if no SDP is present */ + unsigned int ignore_183_without_sdp; }; /*! URI parameter for symmetric transport */ diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 24796fc13a..4621fe0e7d 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -1127,6 +1127,16 @@ option allows the 'Q.850' Reason header to be suppressed. + + Do not forward 183 when it doesn't contain SDP + + Certain SS7 internetworking scenarios can result in a 183 + to be generated for reasons other than early media. Forwarding + this 183 can cause loss of ringback tone. This flag emulates + the behavior of chan_sip and prevents these 183 responses from + being forwarded. + + Authentication type diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index e6ac8ecfad..050073b80a 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1949,6 +1949,7 @@ int ast_res_pjsip_initialize_configuration(void) ast_sorcery_object_field_register(sip_sorcery, "endpoint", "follow_early_media_fork", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtp.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, media.rtp.accept_multiple_sdp_answers)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "suppress_q850_reason_headers", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, suppress_q850_reason_headers)); + ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ignore_183_without_sdp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, ignore_183_without_sdp)); if (ast_sip_initialize_sorcery_transport()) { ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");