]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjproject: Add module providing pjproject logging and utils 42/2042/3
authorGeorge Joseph <george.joseph@fairview5.com>
Tue, 19 Jan 2016 01:27:57 +0000 (18:27 -0700)
committerGeorge Joseph <george.joseph@fairview5.com>
Wed, 20 Jan 2016 16:56:13 +0000 (09:56 -0700)
res_pjsip_log_forwarder has been renamed to res_pjproject
and enhanced as follows:

As a follow-on to the recent 'Add CLI "pjsip show buildopts"' patch,
a new ast_pjproject_get_buildopt function has been added.  It
allows the caller to get the value of one of the buildopts.

The initial use case is retrieving the runtime value of
PJ_MAX_HOSTNAME to insure we don't send a hostname greater
than pjproject can handle.  Since it can differ between
the version of pjproject that Asterisk was compiled against
and the version of pjproject that Asterisk is running against,
we can't use the PJ_MAX_HOSTNAME macro directly in Asterisk
source code.

Change-Id: Iab6e82fec3d7cf00c1cf6185c42be3e7569dee1e

CHANGES
include/asterisk/res_pjproject.h [new file with mode: 0644]
res/res_pjproject.c
res/res_pjproject.exports.in [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 93ecf94c193c1ec1e8334fb09259bfe612e50491..173a41127c721d80a5c0a03f1c10f721218e3669 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -205,6 +205,14 @@ Queue
 --- Functionality changes from Asterisk 13.7.0 to Asterisk 13.8.0 ------------
 ------------------------------------------------------------------------------
 
+res_pjproject
+------------------
+ * This module is the successor of res_pjsip_log_forwarder.  As well as
+   handling the log forwarding (which now displays as 'pjproject:0' instead
+   of 'pjsip:0'), it also adds a 'pjproject show buildopts' command to the CLI.
+   This displays the compiled-in options of the pjproject installation
+   Asterisk is currently running against.
+
 res_pjsip
 ------------------
 
diff --git a/include/asterisk/res_pjproject.h b/include/asterisk/res_pjproject.h
new file mode 100644 (file)
index 0000000..2095cae
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2016, Fairview 5 Engineering, LLC
+ *
+ * George Joseph <george.joseph@fairview5.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#ifndef _RES_PJPROJECT_H
+#define _RES_PJPROJECT_H
+
+/*!
+ * \brief Retrieve a pjproject build option
+ *
+ * \param option The build option requested
+ * \param format_string A scanf-style format string to parse the option value into
+ * \param ... Pointers to variables to receive the values parsed
+ *
+ * \retval The number of values parsed
+ *
+ * \since 13.8.0
+ *
+ * \note The option requested must be from those returned by pj_dump_config()
+ * which can be displayed with the 'pjsip show buildopts' CLI command.
+ *
+ *   <b>Sample Usage:</b>
+ *   \code
+ *
+ *   int max_hostname;
+ *
+ *   ast_sip_get_pjproject_buildopt("PJ_MAX_HOSTNAME", "%d", &max_hostname);
+ *
+ *   \endcode
+ *
+ */
+int ast_pjproject_get_buildopt(char *option, char *format_string, ...) __attribute__((format(scanf, 2,3)));
+
+/*!
+ * \brief Increment the res_pjproject reference count.
+ *
+ * This ensures graceful shutdown happens in the proper order.
+ */
+void ast_pjproject_ref(void);
+
+/*!
+ * \brief Decrement the res_pjproject reference count.
+ *
+ * This ensures graceful shutdown happens in the proper order.
+ */
+void ast_pjproject_unref(void);
+
+#endif /* _RES_PJPROJECT_H */
index c6b396afc5f013f5865b8d947cfede269889d23a..de1cecbc8e776a50c52cd808d3cee5d9a164d53b 100644 (file)
 
 /*! \file
  *
- * \brief Bridge PJSIP logging to Asterisk logging.
+ * \brief Bridge PJPROJECT logging to Asterisk logging.
  * \author David M. Lee, II <dlee@digium.com>
  *
- * PJSIP logging doesn't exactly match Asterisk logging, but mapping the two is
- * not too bad. PJSIP log levels are identified by a single int. Limits are
- * not specified by PJSIP, but their implementation used 1 through 6.
+ * PJPROJECT logging doesn't exactly match Asterisk logging, but mapping the two is
+ * not too bad. PJPROJECT log levels are identified by a single int. Limits are
+ * not specified by PJPROJECT, but their implementation used 1 through 6.
  *
  * The mapping is as follows:
  *  - 0: LOG_ERROR
  *  - 1: LOG_ERROR
  *  - 2: LOG_WARNING
- *  - 3 and above: equivalent to ast_debug(level, ...) for res_pjsip.so
+ *  - 3 and above: equivalent to ast_debug(level, ...) for res_pjproject.so
  */
 
 /*** MODULEINFO
 
 ASTERISK_REGISTER_FILE()
 
+#include <stdarg.h>
+#include <pjlib.h>
 #include <pjsip.h>
 #include <pj/log.h>
 
 #include "asterisk/logger.h"
 #include "asterisk/module.h"
 #include "asterisk/cli.h"
+#include "asterisk/res_pjproject.h"
+#include "asterisk/vector.h"
 
 static pj_log_func *log_cb_orig;
 static unsigned decor_orig;
 
-/*! Protection from other CLI instances. */
-AST_MUTEX_DEFINE_STATIC(show_buildopts_lock);
+static AST_VECTOR(buildopts, char *) buildopts;
 
-struct pjsip_show_buildopts {
-       pthread_t thread;
-       int fd;
-};
-
-static struct pjsip_show_buildopts show_buildopts = {
-       .thread = AST_PTHREADT_NULL,
-       .fd = -1,
-};
-
-static void log_cb(int level, const char *data, int len)
+static void log_forwarder(int level, const char *data, int len)
 {
        int ast_level;
-       /* PJSIP doesn't provide much in the way of source info */
-       const char * log_source = "pjsip";
+       /* PJPROJECT doesn't provide much in the way of source info */
+       const char * log_source = "pjproject";
        int log_line = 0;
        const char *log_func = "<?>";
        int mod_level;
 
-       if (show_buildopts.fd != -1 && show_buildopts.thread == pthread_self()) {
-               /*
-                * We are handling the CLI command dumping the
-                * PJPROJECT compile time config option settings.
-                */
-               ast_cli(show_buildopts.fd, "%s\n", data);
-               return;
-       }
-
        /* Lower number indicates higher importance */
        switch (level) {
        case 0: /* level zero indicates fatal error, according to docs */
@@ -94,29 +78,72 @@ static void log_cb(int level, const char *data, int len)
        default:
                ast_level = __LOG_DEBUG;
 
-               /* For levels 3 and up, obey the debug level for res_pjsip */
+               /* For levels 3 and up, obey the debug level for res_pjproject */
                mod_level = ast_opt_dbg_module ?
-                       ast_debug_get_by_module("res_pjsip") : 0;
+                       ast_debug_get_by_module("res_pjproject") : 0;
                if (option_debug < level && mod_level < level) {
                        return;
                }
                break;
        }
 
-       /* PJSIP uses indention to indicate function call depth. We'll prepend
+       /* PJPROJECT uses indention to indicate function call depth. We'll prepend
         * log statements with a tab so they'll have a better shot at lining
         * up */
        ast_log(ast_level, log_source, log_line, log_func, "\t%s\n", data);
 }
 
-static char *handle_pjsip_show_buildopts(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static void capture_buildopts_cb(int level, const char *data, int len)
+{
+       if (strstr(data, "Teluu") || strstr(data, "Dumping")) {
+               return;
+       }
+
+       AST_VECTOR_ADD_SORTED(&buildopts, ast_strdup(ast_skip_blanks(data)), strcmp);
+}
+
+int ast_pjproject_get_buildopt(char *option, char *format_string, ...)
+{
+       int res = 0;
+       char *format_temp;
+       int i;
+
+       format_temp = ast_alloca(strlen(option) + strlen(" : ") + strlen(format_string) + 1);
+       sprintf(format_temp, "%s : %s", option, format_string);
+
+       for (i = 0; i < AST_VECTOR_SIZE(&buildopts); i++) {
+               va_list arg_ptr;
+               va_start(arg_ptr, format_string);
+               res = vsscanf(AST_VECTOR_GET(&buildopts, i), format_temp, arg_ptr);
+               va_end(arg_ptr);
+               if (res) {
+                       break;
+               }
+       }
+
+       return res;
+}
+
+void ast_pjproject_ref(void)
 {
-       switch(cmd) {
+       ast_module_ref(ast_module_info->self);
+}
+
+void ast_pjproject_unref(void)
+{
+       ast_module_unref(ast_module_info->self);
+}
+
+static char *handle_pjproject_show_buildopts(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       int i;
+
+       switch (cmd) {
        case CLI_INIT:
-               e->command = "pjsip show buildopts";
+               e->command = "pjproject show buildopts";
                e->usage =
-                       "Usage: pjsip show buildopts\n"
-                       "       Show the compile time config of pjproject that res_pjsip is\n"
+                       "Usage: pjproject show buildopts\n"
+                       "       Show the compile time config of the pjproject that Asterisk is\n"
                        "       running against.\n";
                return NULL;
        case CLI_GENERATE:
@@ -125,60 +152,63 @@ static char *handle_pjsip_show_buildopts(struct ast_cli_entry *e, int cmd, struc
 
        ast_cli(a->fd, "PJPROJECT compile time config currently running against:\n");
 
-       /* Protect from other CLI instances trying to do this at the same time. */
-       ast_mutex_lock(&show_buildopts_lock);
-
-       show_buildopts.thread = pthread_self();
-       show_buildopts.fd = a->fd;
-       pj_dump_config();
-       show_buildopts.fd = -1;
-       show_buildopts.thread = AST_PTHREADT_NULL;
-
-       ast_mutex_unlock(&show_buildopts_lock);
+       for (i = 0; i < AST_VECTOR_SIZE(&buildopts); i++) {
+               ast_cli(a->fd, "%s\n", AST_VECTOR_GET(&buildopts, i));
+       }
 
        return CLI_SUCCESS;
 }
 
-static struct ast_cli_entry pjsip_cli[] = {
-       AST_CLI_DEFINE(handle_pjsip_show_buildopts, "Show the compiled config of pjproject in use"),
+static struct ast_cli_entry pjproject_cli[] = {
+       AST_CLI_DEFINE(handle_pjproject_show_buildopts, "Show the compiled config of the pjproject in use"),
 };
 
 static int load_module(void)
 {
+       ast_debug(3, "Starting PJPROJECT logging to Asterisk logger\n");
+
        pj_init();
 
        decor_orig = pj_log_get_decor();
        log_cb_orig = pj_log_get_log_func();
 
-       ast_debug(3, "Forwarding PJSIP logger to Asterisk logger\n");
-       /* SENDER prepends the source to the log message. This could be a
-        * filename, object reference, or simply a string
-        *
-        * INDENT is assumed to be on by most log statements in PJSIP itself.
+       if (AST_VECTOR_INIT(&buildopts, 64)) {
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
+       /*
+        * On startup, we want to capture the dump once and store it.
         */
+       pj_log_set_log_func(capture_buildopts_cb);
+       pj_log_set_decor(0);
+       pj_dump_config();
        pj_log_set_decor(PJ_LOG_HAS_SENDER | PJ_LOG_HAS_INDENT);
-       pj_log_set_log_func(log_cb);
+       pj_log_set_log_func(log_forwarder);
 
-       ast_cli_register_multiple(pjsip_cli, ARRAY_LEN(pjsip_cli));
+       ast_cli_register_multiple(pjproject_cli, ARRAY_LEN(pjproject_cli));
 
        return AST_MODULE_LOAD_SUCCESS;
 }
 
+#define NOT_EQUALS(a, b) (a != b)
+
 static int unload_module(void)
 {
-       ast_cli_unregister_multiple(pjsip_cli, ARRAY_LEN(pjsip_cli));
-
+       ast_cli_unregister_multiple(pjproject_cli, ARRAY_LEN(pjproject_cli));
        pj_log_set_log_func(log_cb_orig);
        pj_log_set_decor(decor_orig);
 
+       AST_VECTOR_REMOVE_CMP_UNORDERED(&buildopts, NULL, NOT_EQUALS, ast_free);
+       AST_VECTOR_FREE(&buildopts);
+
+       ast_debug(3, "Stopped PJPROJECT logging to Asterisk logger\n");
+
        pj_shutdown();
 
        return 0;
 }
 
-/* While we don't really export global symbols, we want to load before other
- * modules that do */
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "PJSIP Log Forwarder",
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "PJPROJECT Log and Utility Support",
        .support_level = AST_MODULE_SUPPORT_CORE,
        .load = load_module,
        .unload = unload_module,
diff --git a/res/res_pjproject.exports.in b/res/res_pjproject.exports.in
new file mode 100644 (file)
index 0000000..f1821a6
--- /dev/null
@@ -0,0 +1,6 @@
+{
+       global:
+               LINKER_SYMBOL_PREFIXast_pjproject_*;
+       local:
+               *;
+};