From 6b7697ed486fc3a8e5e7a72344437e66bd4ae507 Mon Sep 17 00:00:00 2001 From: Richard Begg <asterisk@meric.id.au> Date: Wed, 15 Mar 2017 08:45:06 +1100 Subject: [PATCH] res_pjsip_session: Enable RFC3578 overlap dialing support. Support for RFC3578 overlap dialling (i.e. 484 Response to partially matched destinations) as currently provided by chan_sip is missing from res_pjsip. This patch adds a new endpoint attribute (allow_overlap) [defaults to yes] which when set to yes enables 484 responses to partial destination matches rather than the current 404. ASTERISK-26864 Change-Id: Iea444da3ee7c7d4f1fde1d01d138a3d7b0fe40f6 --- CHANGES | 4 +++ configs/samples/pjsip.conf.sample | 1 + .../8fce4c573e15_add_pjsip_allow_overlap.py | 31 +++++++++++++++++++ include/asterisk/res_pjsip.h | 2 ++ res/res_pjsip.c | 6 ++++ res/res_pjsip/pjsip_configuration.c | 1 + res/res_pjsip_session.c | 24 +++++++++++--- 7 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 contrib/ast-db-manage/config/versions/8fce4c573e15_add_pjsip_allow_overlap.py diff --git a/CHANGES b/CHANGES index e391d1e174..244111fe7c 100644 --- a/CHANGES +++ b/CHANGES @@ -134,6 +134,10 @@ res_pjsip added to both transport and subscription_persistence, an alembic upgrade should be run to bring the database tables up to date. + * A new option, allow_overlap, has been added to endpoints which allows + overlap dialing functionality to be enabled or disabled. The option defaults + to enabled. + res_pjsip_transport_websocket ------------------ * Removed non-secure websocket support. Firefox and Chrome have not allowed diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index 120a7ef1c7..bb80768f55 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -595,6 +595,7 @@ ; "yes") ;aggregate_mwi=yes ; (default: "yes") ;allow= ; Media Codec s to allow (default: "") +;allow_overlap=yes ; Enable RFC3578 overlap dialing support. (default: "yes") ;aors= ; AoR s to be used with the endpoint (default: "") ;auth= ; Authentication Object s associated with the endpoint (default: "") ;callerid= ; CallerID information for the endpoint (default: "") diff --git a/contrib/ast-db-manage/config/versions/8fce4c573e15_add_pjsip_allow_overlap.py b/contrib/ast-db-manage/config/versions/8fce4c573e15_add_pjsip_allow_overlap.py new file mode 100644 index 0000000000..24057ecc87 --- /dev/null +++ b/contrib/ast-db-manage/config/versions/8fce4c573e15_add_pjsip_allow_overlap.py @@ -0,0 +1,31 @@ +"""add pjsip allow_overlap + +Revision ID: 8fce4c573e15 +Revises: f638dbe2eb23 +Create Date: 2017-03-21 15:14:27.612945 + +""" + +# revision identifiers, used by Alembic. +revision = '8fce4c573e15' +down_revision = 'f638dbe2eb23' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects.postgresql import ENUM + +YESNO_NAME = 'yesno_values' +YESNO_VALUES = ['yes', 'no'] + +def upgrade(): + ############################# Enums ############################## + + # yesno_values have already been created, so use postgres enum object + # type to get around "already created" issue - works okay with mysql + yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False) + + op.add_column('ps_endpoints', sa.Column('allow_overlap', yesno_values)) + + +def downgrade(): + op.drop_column('ps_endpoints', 'allow_overlap') diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index c6c308beef..6f44852b1e 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -765,6 +765,8 @@ struct ast_sip_endpoint { unsigned int preferred_codec_only; /*! Do we allow an asymmetric RTP codec? */ unsigned int asymmetric_rtp_codec; + /*! Do we allow overlap dialling? */ + unsigned int allow_overlap; }; /*! URI parameter for symmetric transport */ diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 962c4be4f6..e4bcb70382 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -100,6 +100,9 @@ <configOption name="allow"> <synopsis>Media Codec(s) to allow</synopsis> </configOption> + <configOption name="allow_overlap" default="yes"> + <synopsis>Enable RFC3578 overlap dialing support.</synopsis> + </configOption> <configOption name="aors"> <synopsis>AoR(s) to be used with the endpoint</synopsis> <description><para> @@ -2134,6 +2137,9 @@ <parameter name="SubscribeContext"> <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='subscribe_context']/synopsis/node())"/></para> </parameter> + <parameter name="Allowoverlap"> + <para><xi:include xpointer="xpointer(/docs/configInfo[@name='res_pjsip']/configFile[@name='pjsip.conf']/configObject[@name='endpoint']/configOption[@name='allow_overlap']/synopsis/node())"/></para> + </parameter> </syntax> </managerEventInstance> </managerEvent> diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index c8ff42708b..02562e7827 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1938,6 +1938,7 @@ int ast_res_pjsip_initialize_configuration(void) ast_sorcery_object_field_register(sip_sorcery, "endpoint", "preferred_codec_only", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, preferred_codec_only)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "asymmetric_rtp_codec", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, asymmetric_rtp_codec)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "rtcp_mux", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.rtcp_mux)); + ast_sorcery_object_field_register(sip_sorcery, "endpoint", "allow_overlap", "yes", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, allow_overlap)); if (ast_sip_initialize_sorcery_transport()) { ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n"); diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index de073d3048..5f42dab9f9 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -1986,10 +1986,17 @@ static enum sip_get_destination_result get_destination(struct ast_sip_session *s return SIP_GET_DEST_EXTEN_FOUND; } - /* XXX In reality, we'll likely have further options so that partial matches - * can be indicated here, but for getting something up and running, we're going - * to return a "not exists" error here. + + /* + * Check for partial match via overlap dialling (if enabled) */ + if (session->endpoint->allow_overlap && ( + !strncmp(session->exten, pickupexten, strlen(session->exten)) || + ast_canmatch_extension(NULL, session->endpoint->context, session->exten, 1, NULL))) { + /* Overlap partial match */ + return SIP_GET_DEST_EXTEN_PARTIAL; + } + return SIP_GET_DEST_EXTEN_NOT_FOUND; } @@ -2106,8 +2113,17 @@ static int new_invite(void *data) pjsip_inv_terminate(invite->session->inv_session, 416, PJ_TRUE); } goto end; - case SIP_GET_DEST_EXTEN_NOT_FOUND: case SIP_GET_DEST_EXTEN_PARTIAL: + ast_debug(1, "Call from '%s' (%s:%s:%d) to extension '%s' - partial match\n", ast_sorcery_object_get_id(invite->session->endpoint), + invite->rdata->tp_info.transport->type_name, invite->rdata->pkt_info.src_name, invite->rdata->pkt_info.src_port, invite->session->exten); + + if (pjsip_inv_initial_answer(invite->session->inv_session, invite->rdata, 484, NULL, NULL, &tdata) == PJ_SUCCESS) { + ast_sip_session_send_response(invite->session, tdata); + } else { + pjsip_inv_terminate(invite->session->inv_session, 484, PJ_TRUE); + } + goto end; + case SIP_GET_DEST_EXTEN_NOT_FOUND: default: ast_log(LOG_NOTICE, "Call from '%s' (%s:%s:%d) to extension '%s' rejected because extension not found in context '%s'.\n", ast_sorcery_object_get_id(invite->session->endpoint), invite->rdata->tp_info.transport->type_name, invite->rdata->pkt_info.src_name, -- GitLab