diff --git a/CHANGES b/CHANGES
index 8258b25f1d..396eba9ac7 100644
--- a/CHANGES
+++ b/CHANGES
@@ -8,6 +8,16 @@
===
==============================================================================
+------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 13.1.0-cert8 to Asterisk 13.1-cert9 --
+------------------------------------------------------------------------------
+
+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.1.0-cert4 to Asterisk 13.1-cert8 --
------------------------------------------------------------------------------
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index 8ab654351b..e97a395b8f 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -725,6 +725,8 @@
;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
index 0000000000..6ac610361b
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/4e2493ef32e6_add_contact_user_to_endpoint.py
@@ -0,0 +1,22 @@
+"""Add contact_user to endpoint
+
+Revision ID: 4e2493ef32e6
+Revises: 28ce1e718f05
+Create Date: 2016-08-16 14:19:58.918466
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '4e2493ef32e6'
+down_revision = '28ce1e718f05'
+
+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')
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 0ce50912c0..cffb78a79a 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -619,6 +619,8 @@ struct ast_sip_endpoint {
struct ast_variable *channel_vars;
/*! Whether to place a 'user=phone' parameter into the request URI if user is a number */
unsigned int usereqphone;
+ /*! Override the user on the outgoing Contact header with this value. */
+ char *contact_user;
};
/*!
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index d5b68bccde..7ad47e5402 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -775,6 +775,12 @@
channel is hung up. By default this option is set to 0, which means do not check.
+
+ Force the user on the outgoing Contact header to this value.
+
+ On outbound requests, force the user portion of the Contact header to this value.
+
+
Authentication type
@@ -2381,8 +2387,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;
@@ -2638,6 +2652,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);
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 866bfaa2c7..5275e5f409 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -877,6 +877,30 @@ static int set_var_to_vl(const void *obj, struct ast_variable **fields)
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)
{
@@ -1747,6 +1771,7 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, set_var_to_vl, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "message_context", "", OPT_STRINGFIELD_T, 1, STRFLDSET(struct ast_sip_endpoint, message_context));
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "accountcode", "", OPT_STRINGFIELD_T, 1, STRFLDSET(struct ast_sip_endpoint, accountcode));
+ 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");
@@ -1878,6 +1903,7 @@ static void endpoint_destructor(void* obj)
endpoint->pickup.named_pickupgroups = ast_unref_namedgroups(endpoint->pickup.named_pickupgroups);
ao2_cleanup(endpoint->persistent);
ast_variables_destroy(endpoint->channel_vars);
+ ast_free(endpoint->contact_user);
}
static int init_subscription_configuration(struct ast_sip_endpoint_subscription_configuration *subscription)