From 7a46309d3df85a893b67a8ab9aa043e0c8f53805 Mon Sep 17 00:00:00 2001 From: Alexei Gradinari Date: Mon, 12 Jun 2017 10:23:56 -0400 Subject: [PATCH] res_pjsip: New endpoint option "notify_early_inuse_ringing" This option was added to control whether to notify dialog-info state 'early' or 'confirmed' on Ringing when already INUSE. The value "yes" is useful for some SIP phones (Cisco SPA) to be able to indicate and pick up ringing devices. ASTERISK-26919 #close Change-Id: Ie050bc30023543c7dfb4365c5be3ce58c738c711 --- CHANGES | 4 +++ configs/samples/pjsip.conf.sample | 5 ++++ ...96_add_ps_endpoints_notify_early_inuse_.py | 30 +++++++++++++++++++ include/asterisk/res_pjsip.h | 2 ++ include/asterisk/res_pjsip_presence_xml.h | 3 +- res/res_pjsip.c | 7 +++++ res/res_pjsip/pjsip_configuration.c | 1 + res/res_pjsip/presence_xml.c | 9 ++++-- res/res_pjsip_dialog_info_body_generator.c | 10 +++++-- res/res_pjsip_pidf_body_generator.c | 2 +- res/res_pjsip_pidf_eyebeam_body_supplement.c | 2 +- res/res_pjsip_xpidf_body_generator.c | 2 +- 12 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 contrib/ast-db-manage/config/versions/d7983954dd96_add_ps_endpoints_notify_early_inuse_.py diff --git a/CHANGES b/CHANGES index 9bfa506d33..9cd579b656 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,10 @@ res_pjsip Some SIP phones like Mitel/Aastra or Snom keep the line busy until receive "200 OK". + * A new endpoint option "notify_early_inuse_ringing" was added to control + whether to notify dialog-info state 'early' or 'confirmed' on Ringing + when already INUSE. + res_agi ------------------ * The EAGI() application will now look for a dialplan variable named diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index a992ff8b6b..3b93bb61fc 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -774,6 +774,11 @@ ; transfer (default: "yes"). The value "no" is useful ; for some SIP phones (Mitel/Aastra, Snom) which expect ; a sip/frag "200 OK" after REFER has been accepted. +;notify_early_inuse_ringing = ; Whether to notifies dialog-info 'early' + ; on INUSE && RINGING state (default: "no"). + ; The value "yes" is useful for some SIP phones + ; (Cisco SPA) to be able to indicate and pick up + ; ringing devices. ;==========================AUTH SECTION OPTIONS========================= ;[auth] diff --git a/contrib/ast-db-manage/config/versions/d7983954dd96_add_ps_endpoints_notify_early_inuse_.py b/contrib/ast-db-manage/config/versions/d7983954dd96_add_ps_endpoints_notify_early_inuse_.py new file mode 100644 index 0000000000..e1dcdd133b --- /dev/null +++ b/contrib/ast-db-manage/config/versions/d7983954dd96_add_ps_endpoints_notify_early_inuse_.py @@ -0,0 +1,30 @@ +"""add ps_endpoints.notify_early_inuse_ringing + +Revision ID: d7983954dd96 +Revises: 86bb1efa278d +Create Date: 2017-06-05 15:44:41.152280 + +""" + +# revision identifiers, used by Alembic. +revision = 'd7983954dd96' +down_revision = '86bb1efa278d' + +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('notify_early_inuse_ringing', yesno_values)) + +def downgrade(): + op.drop_column('ps_endpoints', 'notify_early_inuse_ringing') diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 8c589ef85e..b9c50addad 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -769,6 +769,8 @@ struct ast_sip_endpoint { unsigned int allow_overlap; /*! Whether to notifies all the progress details on blind transfer */ unsigned int refer_blind_progress; + /*! Whether to notifies dialog-info 'early' on INUSE && RINGING state */ + unsigned int notify_early_inuse_ringing; }; /*! URI parameter for symmetric transport */ diff --git a/include/asterisk/res_pjsip_presence_xml.h b/include/asterisk/res_pjsip_presence_xml.h index deed0901e4..55b79ad6e8 100644 --- a/include/asterisk/res_pjsip_presence_xml.h +++ b/include/asterisk/res_pjsip_presence_xml.h @@ -69,7 +69,8 @@ void ast_sip_sanitize_xml(const char *input, char *output, size_t len); * \param[out] local_state */ void ast_sip_presence_exten_state_to_str(int state, char **statestring, - char **pidfstate, char **pidfnote, enum ast_sip_pidf_state *local_state); + char **pidfstate, char **pidfnote, enum ast_sip_pidf_state *local_state, + unsigned int notify_early_inuse_ringing); /*! * \brief Create XML attribute diff --git a/res/res_pjsip.c b/res/res_pjsip.c index d994f28248..f6d63c6400 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -971,6 +971,13 @@ will not send the progress details, but immediately will send "200 OK". + + Whether to notifies dialog-info 'early' on InUse&Ringing state + + Control whether dialog-info subscriptions get 'early' state + on Ringing when already INUSE. + + Authentication type diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 679c8837d9..7a05f87f08 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1940,6 +1940,7 @@ int ast_res_pjsip_initialize_configuration(void) 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)); 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)); 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/presence_xml.c b/res/res_pjsip/presence_xml.c index c991a0d68c..1aca307e5a 100644 --- a/res/res_pjsip/presence_xml.c +++ b/res/res_pjsip/presence_xml.c @@ -82,7 +82,8 @@ void ast_sip_sanitize_xml(const char *input, char *output, size_t len) } void ast_sip_presence_exten_state_to_str(int state, char **statestring, char **pidfstate, - char **pidfnote, enum ast_sip_pidf_state *local_state) + char **pidfnote, enum ast_sip_pidf_state *local_state, + unsigned int notify_early_inuse_ringing) { switch (state) { case AST_EXTENSION_RINGING: @@ -92,7 +93,11 @@ void ast_sip_presence_exten_state_to_str(int state, char **statestring, char **p *pidfnote = "Ringing"; break; case (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING): - *statestring = "confirmed"; + if (notify_early_inuse_ringing) { + *statestring = "early"; + } else { + *statestring = "confirmed"; + } *local_state = NOTIFY_INUSE; *pidfstate = "busy"; *pidfnote = "Ringing"; diff --git a/res/res_pjsip_dialog_info_body_generator.c b/res/res_pjsip_dialog_info_body_generator.c index 5006b9efb4..7c386e3b2d 100644 --- a/res/res_pjsip_dialog_info_body_generator.c +++ b/res/res_pjsip_dialog_info_body_generator.c @@ -107,6 +107,8 @@ static int dialog_info_generate_body_content(void *body, void *data) enum ast_sip_pidf_state local_state; unsigned int version; char version_str[32], sanitized[PJSIP_MAX_URL_SIZE]; + struct ast_sip_endpoint *endpoint = NULL; + unsigned int notify_early_inuse_ringing = 0; if (!local || !state_data->datastores) { return -1; @@ -120,8 +122,12 @@ static int dialog_info_generate_body_content(void *body, void *data) stripped = ast_strip_quoted(local, "<", ">"); ast_sip_sanitize_xml(stripped, sanitized, sizeof(sanitized)); + if (state_data->sub && (endpoint = ast_sip_subscription_get_endpoint(state_data->sub))) { + notify_early_inuse_ringing = endpoint->notify_early_inuse_ringing; + ao2_cleanup(endpoint); + } ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring, - &pidfstate, &pidfnote, &local_state); + &pidfstate, &pidfnote, &local_state, notify_early_inuse_ringing); ast_sip_presence_xml_create_attr(state_data->pool, dialog_info, "xmlns", "urn:ietf:params:xml:ns:dialog-info"); @@ -133,7 +139,7 @@ static int dialog_info_generate_body_content(void *body, void *data) dialog = ast_sip_presence_xml_create_node(state_data->pool, dialog_info, "dialog"); ast_sip_presence_xml_create_attr(state_data->pool, dialog, "id", state_data->exten); - if (state_data->exten_state == AST_EXTENSION_RINGING) { + if (!ast_strlen_zero(statestring) && !strcmp(statestring, "early")) { ast_sip_presence_xml_create_attr(state_data->pool, dialog, "direction", "recipient"); } diff --git a/res/res_pjsip_pidf_body_generator.c b/res/res_pjsip_pidf_body_generator.c index 25f0639157..cc10082ad3 100644 --- a/res/res_pjsip_pidf_body_generator.c +++ b/res/res_pjsip_pidf_body_generator.c @@ -58,7 +58,7 @@ static int pidf_generate_body_content(void *body, void *data) struct ast_sip_exten_state_data *state_data = data; ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring, - &pidfstate, &pidfnote, &local_state); + &pidfstate, &pidfnote, &local_state, 0); if (!pjpidf_pres_add_note(state_data->pool, pres, pj_cstr(¬e, pidfnote))) { ast_log(LOG_WARNING, "Unable to add note to PIDF presence\n"); diff --git a/res/res_pjsip_pidf_eyebeam_body_supplement.c b/res/res_pjsip_pidf_eyebeam_body_supplement.c index cc6dfd125c..a0f50fddee 100644 --- a/res/res_pjsip_pidf_eyebeam_body_supplement.c +++ b/res/res_pjsip_pidf_eyebeam_body_supplement.c @@ -80,7 +80,7 @@ static int pidf_supplement_body(void *body, void *data) enum ast_sip_pidf_state local_state; ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring, - &pidfstate, &pidfnote, &local_state); + &pidfstate, &pidfnote, &local_state, 0); add_eyebeam(state_data->pool, pres, pidfstate); return 0; diff --git a/res/res_pjsip_xpidf_body_generator.c b/res/res_pjsip_xpidf_body_generator.c index 924046549a..41f6224d1a 100644 --- a/res/res_pjsip_xpidf_body_generator.c +++ b/res/res_pjsip_xpidf_body_generator.c @@ -63,7 +63,7 @@ static int xpidf_generate_body_content(void *body, void *data) pj_xml_node *msnsubstatus; ast_sip_presence_exten_state_to_str(state_data->exten_state, &statestring, - &pidfstate, &pidfnote, &local_state); + &pidfstate, &pidfnote, &local_state, 0); ast_sip_presence_xml_find_node_attr(state_data->pool, pres, "atom", "id", &atom, &attr);