res_pjsip: Add contact_user to endpoint
authorGeorge Joseph <gjoseph@digium.com>
Tue, 16 Aug 2016 20:36:10 +0000 (14:36 -0600)
committerGeorge Joseph <gjoseph@digium.com>
Wed, 17 Aug 2016 21:21:19 +0000 (16:21 -0500)
contact_user, when specified on an endpoint, will override the user
portion of the Contact header on outgoing requests.

Change-Id: Icd4ebfda2f2e44d3ac749d0b4066630e988407d4

CHANGES
configs/samples/pjsip.conf.sample
contrib/ast-db-manage/config/versions/4e2493ef32e6_add_contact_user_to_endpoint.py [new file with mode: 0644]
include/asterisk/res_pjsip.h
res/res_pjsip.c
res/res_pjsip/pjsip_configuration.c

diff --git a/CHANGES b/CHANGES
index 7f3b0ad..1cfa7eb 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -42,6 +42,11 @@ chan_pjsip
    dialplan function PJSIP_MEDIA_OFFER, this allows the formats on a PJSIP
    channel to be re-negotiated and updated after session set up.
 
+res_pjsip
+------------------
+ * A new endpoint configuration parameter 'contact_user' has been added which
+   when set will override the default user set on Contact headers in outgoing
+   requests.
 
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13 to Asterisk 14 --------------------
@@ -407,7 +412,6 @@ cdr_csv
  * Added a new configuration option, "newcdrcolumns", which enables use of the
    post-1.8 CDR columns 'peeraccount', 'linkedid', and 'sequence'.
 
-
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.10.0 to Asterisk 13.11.0 ----------
 ------------------------------------------------------------------------------
index eac0549..0d1c039 100644 (file)
 ;rtp_timeout_hold= ; Hang up channel if RTP is not received for the specified
                    ; number of seconds when the channel is on hold (default:
                    ; "0" or not enabled)
+;contact_user= ; On outgoing requests, force the user portion of the Contact
+               ; header to this value (default: "")
 
 ;==========================AUTH SECTION OPTIONS=========================
 ;[auth]
diff --git a/contrib/ast-db-manage/config/versions/4e2493ef32e6_add_contact_user_to_endpoint.py b/contrib/ast-db-manage/config/versions/4e2493ef32e6_add_contact_user_to_endpoint.py
new file mode 100644 (file)
index 0000000..f91cff0
--- /dev/null
@@ -0,0 +1,22 @@
+"""Add contact_user to endpoint
+
+Revision ID: 4e2493ef32e6
+Revises: 3772f8f828da
+Create Date: 2016-08-16 14:19:58.918466
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '4e2493ef32e6'
+down_revision = '3772f8f828da'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.add_column('ps_endpoints', sa.Column('contact_user', sa.String(80)))
+
+
+def downgrade():
+    op.drop_column('ps_endpoints', 'contact_user')
index cd6b33d..4cede43 100644 (file)
@@ -755,6 +755,8 @@ struct ast_sip_endpoint {
        struct ast_acl_list *contact_acl;
        /*! The number of seconds into call to disable fax detection.  (0 = disabled) */
        unsigned int faxdetect_timeout;
+       /*! Override the user on the outgoing Contact header with this value. */
+       char *contact_user;
 };
 
 /*!
index 8a9a19d..34edc8c 100644 (file)
                                                then the <replaceable>context</replaceable> setting is used.
                                        </para></description>
                                </configOption>
+                               <configOption name="contact_user" default="">
+                                       <synopsis>Force the user on the outgoing Contact header to this value.</synopsis>
+                                       <description><para>
+                                               On outbound requests, force the user portion of the Contact header to this value.
+                                       </para></description>
+                               </configOption>
                        </configObject>
                        <configObject name="auth">
                                <synopsis>Authentication type</synopsis>
@@ -2865,8 +2871,16 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
        /* Update the dialog with the new local URI, we do it afterwards so we can use the dialog pool for construction */
        pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
        dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
+
        dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen, NULL);
 
+       if (!ast_strlen_zero(endpoint->contact_user)) {
+               pjsip_sip_uri *sip_uri;
+
+               sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
+               pj_strdup2(dlg->pool, &sip_uri->user, endpoint->contact_user);
+       }
+
        /* If a request user has been specified and we are permitted to change it, do so */
        if (!ast_strlen_zero(request_user)) {
                pjsip_sip_uri *sip_uri;
@@ -3168,6 +3182,18 @@ static int create_out_of_dialog_request(const pjsip_method *method, struct ast_s
                return -1;
        }
 
+       if (endpoint && !ast_strlen_zero(endpoint->contact_user)){
+               pjsip_contact_hdr *contact_hdr;
+               pjsip_sip_uri *contact_uri;
+               static const pj_str_t HCONTACT = { "Contact", 7 };
+
+               contact_hdr = pjsip_msg_find_hdr_by_name((*tdata)->msg, &HCONTACT, NULL);
+               if (contact_hdr) {
+                       contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
+                       pj_strdup2(pool, &contact_uri->user, endpoint->contact_user);
+               }
+       }
+
        /* Add the user=phone parameter if applicable */
        ast_sip_add_usereqphone(endpoint, (*tdata)->pool, (*tdata)->msg->line.req.uri);
 
index 9871b41..3bced11 100644 (file)
@@ -1208,6 +1208,31 @@ static int voicemail_extension_to_str(const void *obj, const intptr_t *args, cha
        return 0;
 }
 
+static int contact_user_handler(const struct aco_option *opt,
+       struct ast_variable *var, void *obj)
+{
+       struct ast_sip_endpoint *endpoint = obj;
+
+       endpoint->contact_user = ast_strdup(var->value);
+       if (!endpoint->contact_user) {
+               return -1;
+       }
+
+       return 0;
+}
+
+static int contact_user_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+       const struct ast_sip_endpoint *endpoint = obj;
+
+       *buf = ast_strdup(endpoint->contact_user);
+       if (!(*buf)) {
+               return -1;
+       }
+
+       return 0;
+}
+
 static void *sip_nat_hook_alloc(const char *name)
 {
        return ast_sorcery_generic_alloc(sizeof(struct ast_sip_nat_hook), NULL);
@@ -1905,6 +1930,7 @@ int ast_res_pjsip_initialize_configuration(void)
        ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
        ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_acl", "", endpoint_acl_handler, contact_acl_to_str, NULL, 0, 0);
        ast_sorcery_object_field_register(sip_sorcery, "endpoint", "subscribe_context", "", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct ast_sip_endpoint, subscription.context));
+       ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_user", "", contact_user_handler, contact_user_to_str, NULL, 0, 0);
 
        if (ast_sip_initialize_sorcery_transport()) {
                ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
@@ -2036,6 +2062,7 @@ static void endpoint_destructor(void* obj)
        ao2_cleanup(endpoint->persistent);
        ast_variables_destroy(endpoint->channel_vars);
        AST_VECTOR_FREE(&endpoint->ident_method_order);
+       ast_free(endpoint->contact_user);
 }
 
 static int init_subscription_configuration(struct ast_sip_endpoint_subscription_configuration *subscription)