]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip: allow configuration of endpoint identifier query order
authorKevin Harwell <kharwell@digium.com>
Mon, 9 Mar 2015 16:13:40 +0000 (16:13 +0000)
committerKevin Harwell <kharwell@digium.com>
Mon, 9 Mar 2015 16:13:40 +0000 (16:13 +0000)
It's possible to have a scenario that will create a conflict between endpoint
identifiers. For instance an incoming call could be identified by two different
endpoint identifiers and the one chosen depended upon which identifier module
loaded first. This of course causes problems when, for example, the incoming
call is expected to be identified by username, but instead is identified by ip.
This patch adds a new 'global' option to res_pjsip called
'endpoint_identifier_order'. It is a comma separated list of endpoint
identifier names that specifies the order by which identifiers are processed
and checked.

ASTERISK-24840 #close
Reported by: Mark Michelson
Review: https://reviewboard.asterisk.org/r/4455/
........

Merged revisions 432638 from http://svn.asterisk.org/svn/asterisk/branches/13

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@432639 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
configs/samples/pjsip.conf.sample
contrib/ast-db-manage/config/versions/45e3f47c6c44_add_pjsip_endpoint_identifier_order.py [new file with mode: 0644]
include/asterisk/res_pjsip.h
res/res_pjsip.c
res/res_pjsip/config_global.c
res/res_pjsip_endpoint_identifier_anonymous.c
res/res_pjsip_endpoint_identifier_ip.c
res/res_pjsip_endpoint_identifier_user.c

diff --git a/CHANGES b/CHANGES
index 5f08d5ab3facdf07428ee74073f96659b4d5d0ae..ed1b3781c01f507c8165de686d791962af92a97f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -118,6 +118,13 @@ res_ari_channels
    technologies, this is either a 302 Redirect response to an on-going INVITE
    dialog or a SIP REFER request.
 
+res_pjsip
+------------------
+ * A new 'endpoint_identifier_order' option has been added that allows one to
+   set the order by which endpoint identifiers are processed and checked. This
+   option is specified under the 'global' type configuration section.
+
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.1.0 to Asterisk 13.2.0 ------------
 ------------------------------------------------------------------------------
index 782fbab361e765d700eadc189693453c4f799174..ba8bf751ba720e6d0db313aa2f8de12f7e79ad45 100644 (file)
 ;keep_alive_interval=20 ; The interval (in seconds) at which to send keepalive
                         ; messages on all active connection-oriented transports
                         ; (default: "0")
+;endpoint_identifier_order=ip,username,anonymous
+            ; The order by which endpoint identifiers are given priority.
+            ; Identifier names are derived from res_pjsip_endpoint_identifier_*
+            ; modules. (default: ip,username,anonymous)
 
 
 ; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl
diff --git a/contrib/ast-db-manage/config/versions/45e3f47c6c44_add_pjsip_endpoint_identifier_order.py b/contrib/ast-db-manage/config/versions/45e3f47c6c44_add_pjsip_endpoint_identifier_order.py
new file mode 100644 (file)
index 0000000..213da92
--- /dev/null
@@ -0,0 +1,21 @@
+"""add pjsip endpoint_identifier_order
+
+Revision ID: 45e3f47c6c44
+Revises: 371a3bf4143e
+Create Date: 2015-03-02 09:32:20.632015
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '45e3f47c6c44'
+down_revision = '371a3bf4143e'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.add_column('ps_globals', sa.Column('endpoint_identifier_order', sa.String(40)))
+
+def downgrade():
+    op.drop_column('ps_globals', 'endpoint_identifier_order')
index 43194fe2f912e17082449f71ed25992b9f27c145..b3cd23e6b54323744218a995c9f6ee94f599772a 100644 (file)
@@ -699,6 +699,8 @@ struct ast_sip_outbound_authenticator {
  * \brief An entity responsible for identifying the source of a SIP message
  */
 struct ast_sip_endpoint_identifier {
+    /*! Name of the endpoint identifier */
+    const char *name;
     /*!
      * \brief Callback used to identify the source of a message.
      * See ast_sip_identify_endpoint for more details
@@ -1972,6 +1974,15 @@ void ast_sip_unregister_supplement(struct ast_sip_supplement *supplement);
  */
 char *ast_sip_get_debug(void);
 
+/*!
+ * \brief Retrieve the global endpoint_identifier_order setting.
+ *
+ * Specifies the order by which endpoint identifiers should be regarded.
+ *
+ * \retval the global endpoint_identifier_order value
+ */
+char *ast_sip_get_endpoint_identifier_order(void);
+
 /*! \brief Determines whether the res_pjsip module is loaded */
 #define CHECK_PJSIP_MODULE_LOADED()                            \
        do {                                                    \
index f063d7963577771f9cc14af06984647875b11b39..423576ee0cab8d8fa595c6214f8316997ed4bdff 100644 (file)
@@ -36,6 +36,7 @@
 #include "asterisk/uuid.h"
 #include "asterisk/sorcery.h"
 #include "asterisk/file.h"
+#include "asterisk/cli.h"
 
 /*** MODULEINFO
        <depend>pjproject</depend>
                                        <synopsis>Enable/Disable SIP debug logging.  Valid options include yes|no or
                                         a host address</synopsis>
                                </configOption>
+                               <configOption name="endpoint_identifier_order" default="ip,username,anonymous">
+                                       <synopsis>The order by which endpoint identifiers are processed and checked.
+                                        Identifier names are usually derived from and can be found in the endpoint
+                                        identifier module itself (res_pjsip_endpoint_identifier_*)</synopsis>
+                               </configOption>
                        </configObject>
                </configFile>
        </configInfo>
@@ -1964,6 +1970,7 @@ int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pj
 }
 
 struct endpoint_identifier_list {
+       unsigned int priority;
        struct ast_sip_endpoint_identifier *identifier;
        AST_RWLIST_ENTRY(endpoint_identifier_list) list;
 };
@@ -1972,7 +1979,8 @@ static AST_RWLIST_HEAD_STATIC(endpoint_identifiers, endpoint_identifier_list);
 
 int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
 {
-       struct endpoint_identifier_list *id_list_item;
+       char *prev, *current, *identifier_order;
+       struct endpoint_identifier_list *iter, *id_list_item;
        SCOPED_LOCK(lock, &endpoint_identifiers, AST_RWLIST_WRLOCK, AST_RWLIST_UNLOCK);
 
        id_list_item = ast_calloc(1, sizeof(*id_list_item));
@@ -1982,10 +1990,67 @@ int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *ide
        }
        id_list_item->identifier = identifier;
 
-       AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
-       ast_debug(1, "Registered endpoint identifier %p\n", identifier);
+       ast_debug(1, "Register endpoint identifier %s (%p)\n", identifier->name, identifier);
+
+       if (ast_strlen_zero(identifier->name)) {
+               /* if an identifier has no name then place in front */
+               AST_RWLIST_INSERT_HEAD(&endpoint_identifiers, id_list_item, list);
+               ast_module_ref(ast_module_info->self);
+               return 0;
+       }
+
+       /* see if the name of the identifier is in the global endpoint_identifier_order list */
+       identifier_order = prev = current = ast_sip_get_endpoint_identifier_order();
+
+       if (ast_strlen_zero(identifier_order)) {
+               AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
+               ast_module_ref(ast_module_info->self);
+               ast_free(identifier_order);
+               return 0;
+       }
+
+       id_list_item->priority = 0;
+       while ((current = strchr(current, ','))) {
+               ++id_list_item->priority;
+               if (!strncmp(prev, identifier->name, current - prev)) {
+                       break;
+               }
+               prev = ++current;
+       }
+
+       if (!current) {
+               /* check to see if it the only or last item */
+               if (!strcmp(prev, identifier->name)) {
+                       ++id_list_item->priority;
+               } else {
+                       id_list_item->priority = UINT_MAX;
+               }
+       }
+
+       if (id_list_item->priority == UINT_MAX || AST_RWLIST_EMPTY(&endpoint_identifiers)) {
+               /* if not in the endpoint_identifier_order list then consider it less in
+                  priority and add it to the end */
+               AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
+               ast_module_ref(ast_module_info->self);
+               ast_free(identifier_order);
+               return 0;
+       }
+
+       AST_RWLIST_TRAVERSE_SAFE_BEGIN(&endpoint_identifiers, iter, list) {
+               if (id_list_item->priority < iter->priority) {
+                       AST_RWLIST_INSERT_BEFORE_CURRENT(id_list_item, list);
+                       break;
+               }
+
+               if (!AST_RWLIST_NEXT(iter, list)) {
+                       AST_RWLIST_INSERT_AFTER(&endpoint_identifiers, iter, id_list_item, list);
+                       break;
+               }
+       }
+       AST_RWLIST_TRAVERSE_SAFE_END;
 
        ast_module_ref(ast_module_info->self);
+       ast_free(identifier_order);
        return 0;
 }
 
@@ -2020,6 +2085,41 @@ struct ast_sip_endpoint *ast_sip_identify_endpoint(pjsip_rx_data *rdata)
        return endpoint;
 }
 
+static char *cli_show_endpoint_identifiers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+#define ENDPOINT_IDENTIFIER_FORMAT "%-20.20s\n"
+       struct endpoint_identifier_list *iter;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "pjsip show identifiers";
+               e->usage = "Usage: pjsip show identifiers\n"
+                           "      List all registered endpoint identifiers\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc != 3) {
+                return CLI_SHOWUSAGE;
+        }
+
+       ast_cli(a->fd, ENDPOINT_IDENTIFIER_FORMAT, "Identifier Names:");
+       {
+               SCOPED_LOCK(lock, &endpoint_identifiers, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK);
+               AST_RWLIST_TRAVERSE(&endpoint_identifiers, iter, list) {
+                       ast_cli(a->fd, ENDPOINT_IDENTIFIER_FORMAT,
+                               iter->identifier->name ? iter->identifier->name : "name not specified");
+               }
+       }
+       return CLI_SUCCESS;
+#undef ENDPOINT_IDENTIFIER_FORMAT
+}
+
+static struct ast_cli_entry cli_commands[] = {
+        AST_CLI_DEFINE(cli_show_endpoint_identifiers, "List registered endpoint identifiers")
+};
+
 AST_RWLIST_HEAD_STATIC(endpoint_formatters, ast_sip_endpoint_formatter);
 
 void internal_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
@@ -3356,6 +3456,7 @@ static int load_module(void)
        }
 
        ast_res_pjsip_init_options_handling(0);
+       ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
 
        return AST_MODULE_LOAD_SUCCESS;
 }
@@ -3376,6 +3477,7 @@ static int reload_module(void)
 
 static int unload_pjsip(void *data)
 {
+       ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
        if (memory_pool) {
                pj_pool_release(memory_pool);
                memory_pool = NULL;
index 1779c535d3af4cd37d46d64f774cf2290534199f..21800850eed9c18d0f4b056031922ead5a5868a2 100644 (file)
@@ -39,6 +39,8 @@ struct global_config {
                AST_STRING_FIELD(default_outbound_endpoint);
                /*! Debug logging yes|no|host */
                AST_STRING_FIELD(debug);
+               /*! Order by which endpoint identifiers are checked (comma separated list) */
+               AST_STRING_FIELD(endpoint_identifier_order);
        );
        /* Value to put in Max-Forwards header */
        unsigned int max_forwards;
@@ -57,7 +59,7 @@ static void *global_alloc(const char *name)
 {
        struct global_config *cfg = ast_sorcery_generic_alloc(sizeof(*cfg), global_destructor);
 
-       if (!cfg || ast_string_field_init(cfg, 80)) {
+       if (!cfg || ast_string_field_init(cfg, 100)) {
                return NULL;
        }
 
@@ -116,6 +118,21 @@ char *ast_sip_get_debug(void)
        return res;
 }
 
+char *ast_sip_get_endpoint_identifier_order(void)
+{
+       char *res;
+       struct global_config *cfg = get_global_cfg();
+
+       if (!cfg) {
+               return ast_strdup("ip,username,anonymous");
+       }
+
+       res = ast_strdup(cfg->endpoint_identifier_order);
+       ao2_ref(cfg, -1);
+
+       return res;
+}
+
 unsigned int ast_sip_get_keep_alive_interval(void)
 {
        unsigned int interval;
@@ -152,6 +169,8 @@ int ast_sip_initialize_sorcery_global(void)
                        OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, default_outbound_endpoint));
        ast_sorcery_object_field_register(sorcery, "global", "debug", "no",
                        OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, debug));
+       ast_sorcery_object_field_register(sorcery, "global", "endpoint_identifier_order", "ip,username,anonymous",
+                       OPT_STRINGFIELD_T, 0, STRFLDSET(struct global_config, endpoint_identifier_order));
        ast_sorcery_object_field_register(sorcery, "global", "keep_alive_interval", "",
                        OPT_UINT_T, 0, FLDSET(struct global_config, keep_alive_interval));
 
index a7956b5896397d9c69bcb3b15c11626a7af35965..4ce945a7b151362a51cd6633d6ceee3f74a218e3 100644 (file)
@@ -103,6 +103,7 @@ done:
 }
 
 static struct ast_sip_endpoint_identifier anonymous_identifier = {
+       .name = "anonymous",
        .identify_endpoint = anonymous_identify,
 };
 
index 4bd4f122e1adbcea400d8f04b7d3c76eddb52c92..d1c91a27c5f08b40993aedd2707086e2fec69ad4 100644 (file)
@@ -150,6 +150,7 @@ static struct ast_sip_endpoint *ip_identify(pjsip_rx_data *rdata)
 }
 
 static struct ast_sip_endpoint_identifier ip_identifier = {
+       .name = "ip",
        .identify_endpoint = ip_identify,
 };
 
index beae1cdd4591ee5a68e60f3d04a304fc7fc5baca..a5c9411f9ac10911ac4736f5e120464b5bc56278 100644 (file)
@@ -109,6 +109,7 @@ done:
 }
 
 static struct ast_sip_endpoint_identifier username_identifier = {
+       .name = "username",
        .identify_endpoint = username_identify,
 };