]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip: Allow configuration of endpoint identifier query order
authorKevin Harwell <kharwell@digium.com>
Tue, 17 Mar 2015 18:43:03 +0000 (18:43 +0000)
committerKevin Harwell <kharwell@digium.com>
Tue, 17 Mar 2015 18:43:03 +0000 (18:43 +0000)
This patch fixes previously reverted code that caused binary incompatibility
problems with some modules. And like the original patch it makes sure that
no matter what order the endpoint identifier modules were loaded, priority is
given based on the ones specified in the new global 'endpoint_identifier_order'
option.

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

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

git-svn-id: https://origsvn.digium.com/svn/asterisk/certified/branches/13.1@433033 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
configs/samples/pjsip.conf.sample
contrib/ast-db-manage/config/versions/45e3f47c6c44_add_pjsip_endpoint_identifier_order.py
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 c1a5379ed1a7a561317f39867c6960baa8a7109e..6dd767e59cf8c51e6eed9d80be38c9d59036dfbf 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,15 @@
 === and the other UPGRADE files for older releases.
 ===
 ==============================================================================
+------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 13.1.0 to Asterisk 13.1-cert2 --------
+------------------------------------------------------------------------------
+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.1-cert1 --------
 ------------------------------------------------------------------------------
index 92a75b2aad3609ae2a2eabdc457e1181d3cabc8e..d5641473ded2a3844598edbaa4b018c1a1466385 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
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..213da92fb270fcf431b3fe01a4d93ea0ad2badbd 100644 (file)
@@ -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 e708fd8ab395105de3eca4d14eef80597a103349..5c6d349313bf299ec844ba804374869c1b24b1d3 100644 (file)
@@ -775,6 +775,23 @@ int ast_sip_register_outbound_authenticator(struct ast_sip_outbound_authenticato
  */
 void ast_sip_unregister_outbound_authenticator(struct ast_sip_outbound_authenticator *auth);
 
+/*!
+ * \brief Register a SIP endpoint identifier with a name.
+ *
+ * An endpoint identifier's purpose is to determine which endpoint a given SIP
+ * message has come from.
+ *
+ * Multiple endpoint identifiers may be registered so that if an endpoint
+ * cannot be identified by one identifier, it may be identified by another.
+ *
+ * \param identifier The SIP endpoint identifier to register
+ * \param name The name of the endpoint identifier
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sip_register_endpoint_identifier_by_name(struct ast_sip_endpoint_identifier *identifier,
+                                                const char *name);
+
 /*!
  * \brief Register a SIP endpoint identifier
  *
@@ -1958,6 +1975,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 033f14995c4ddd37a325d4a12ae48f0ad2cef2b6..4227a7e72bceab83b172ddce94f908bfa85f9357 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>
@@ -1916,15 +1922,19 @@ int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pj
 }
 
 struct endpoint_identifier_list {
+       const char *name;
+       unsigned int priority;
        struct ast_sip_endpoint_identifier *identifier;
        AST_RWLIST_ENTRY(endpoint_identifier_list) list;
 };
 
 static AST_RWLIST_HEAD_STATIC(endpoint_identifiers, endpoint_identifier_list);
 
-int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
+int ast_sip_register_endpoint_identifier_by_name(struct ast_sip_endpoint_identifier *identifier,
+                                                const char *name)
 {
-       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));
@@ -1933,14 +1943,78 @@ int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *ide
                return -1;
        }
        id_list_item->identifier = identifier;
+       id_list_item->name = name;
+
+       ast_debug(1, "Register endpoint identifier %s (%p)\n", name, identifier);
+
+       if (ast_strlen_zero(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)) {
+               id_list_item->priority = UINT_MAX;
+               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, name, current - prev)) {
+                       break;
+               }
+               prev = ++current;
+       }
+
+       if (!current) {
+               /* check to see if it is the only or last item */
+               if (!strcmp(prev, name)) {
+                       ++id_list_item->priority;
+               } else {
+                       id_list_item->priority = UINT_MAX;
+               }
+       }
 
-       AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
-       ast_debug(1, "Registered endpoint identifier %p\n", identifier);
+       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;
 }
 
+int ast_sip_register_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
+{
+       return ast_sip_register_endpoint_identifier_by_name(identifier, NULL);
+}
+
 void ast_sip_unregister_endpoint_identifier(struct ast_sip_endpoint_identifier *identifier)
 {
        struct endpoint_identifier_list *iter;
@@ -1972,6 +2046,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->name ? iter->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);
 
 int ast_sip_register_endpoint_formatter(struct ast_sip_endpoint_formatter *obj)
@@ -3243,6 +3352,7 @@ static int load_module(void)
        }
 
        ast_res_pjsip_init_options_handling(0);
+       ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
 
        ast_module_ref(ast_module_info->self);
 
@@ -3265,6 +3375,7 @@ static int reload_module(void)
 
 static int unload_module(void)
 {
+       ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
        /* This will never get called as this module can't be unloaded */
        return 0;
 }
index cf8d66bd175b607b32439163dd7b2e5230baf04e..a18cecb3cb2cf69fe73784b13115200664cd4265 100644 (file)
@@ -29,6 +29,7 @@
 #define DEFAULT_MAX_FORWARDS 70
 #define DEFAULT_USERAGENT_PREFIX "Asterisk PBX"
 #define DEFAULT_OUTBOUND_ENDPOINT "default_outbound_endpoint"
+#define DEFAULT_ENDPOINT_IDENTIFIER_ORDER "ip,username,anonymous"
 
 static char default_useragent[128];
 
@@ -39,6 +40,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;
@@ -116,6 +119,21 @@ char *ast_sip_get_debug(void)
        return res;
 }
 
+char *ast_sip_get_endpoint_identifier_order(void)
+{
+       char *res;
+       struct global_config *cfg;
+
+       cfg = get_global_cfg();
+       if (!cfg) {
+               return ast_strdup(DEFAULT_ENDPOINT_IDENTIFIER_ORDER);
+       }
+
+       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,8 +170,9 @@ 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", DEFAULT_ENDPOINT_IDENTIFIER_ORDER,
+                       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));
-
        return 0;
 }
index a7956b5896397d9c69bcb3b15c11626a7af35965..f191d99cfb41475946edf9c3eb4984f016d663bb 100644 (file)
@@ -110,7 +110,7 @@ static int load_module(void)
 {
        CHECK_PJSIP_MODULE_LOADED();
 
-       ast_sip_register_endpoint_identifier(&anonymous_identifier);
+       ast_sip_register_endpoint_identifier_by_name(&anonymous_identifier, "anonymous");
        return AST_MODULE_LOAD_SUCCESS;
 }
 
index 4bd4f122e1adbcea400d8f04b7d3c76eddb52c92..b97724e3fe56f8079507fe5569f19fe15719655b 100644 (file)
@@ -491,7 +491,7 @@ static int load_module(void)
        ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "identify", "match", "", ip_identify_match_handler, match_to_str, match_to_var_list, 0, 0);
        ast_sorcery_reload_object(ast_sip_get_sorcery(), "identify");
 
-       ast_sip_register_endpoint_identifier(&ip_identifier);
+       ast_sip_register_endpoint_identifier_by_name(&ip_identifier, "ip");
        ast_sip_register_endpoint_formatter(&endpoint_identify_formatter);
 
        cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
index beae1cdd4591ee5a68e60f3d04a304fc7fc5baca..a60057e1478a93087b825585390318dc9a715286 100644 (file)
@@ -116,7 +116,7 @@ static int load_module(void)
 {
        CHECK_PJSIP_MODULE_LOADED();
 
-       ast_sip_register_endpoint_identifier(&username_identifier);
+       ast_sip_register_endpoint_identifier_by_name(&username_identifier, "username");
        return AST_MODULE_LOAD_SUCCESS;
 }