diff options
author | Joshua Colp <jcolp@digium.com> | 2016-01-20 11:46:13 -0600 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2016-01-20 11:46:14 -0600 |
commit | a2928b6093c5a32788cca0608913fe72bc4175c0 (patch) | |
tree | c741b898c7dc208b08cb44c166e5c09da9718362 | |
parent | de3d988b9e979ce2b298f3b2d172a6ed03abda61 (diff) | |
parent | 137fe5ae010df4ff808fa4aecd3f166c6698ba45 (diff) |
Merge "res_pjproject: Add module providing pjproject logging and utils" into 13
-rw-r--r-- | CHANGES | 8 | ||||
-rw-r--r-- | include/asterisk/res_pjproject.h | 62 | ||||
-rw-r--r-- | res/res_pjproject.c | 154 | ||||
-rw-r--r-- | res/res_pjproject.exports.in | 6 |
4 files changed, 168 insertions, 62 deletions
@@ -12,6 +12,14 @@ --- 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 index 000000000..2095caed2 --- /dev/null +++ b/include/asterisk/res_pjproject.h @@ -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 */ diff --git a/res/res_pjproject.c b/res/res_pjproject.c index 7a7128054..9ce112388 100644 --- a/res/res_pjproject.c +++ b/res/res_pjproject.c @@ -18,18 +18,18 @@ /*! \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 @@ -39,49 +39,33 @@ #include "asterisk.h" -ASTERISK_FILE_VERSION(__FILE__, "$Revision$") +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 index 000000000..f1821a6a2 --- /dev/null +++ b/res/res_pjproject.exports.in @@ -0,0 +1,6 @@ +{ + global: + LINKER_SYMBOL_PREFIXast_pjproject_*; + local: + *; +}; |