diff --git a/CHANGES b/CHANGES index cb3fe951d355c209bfef71bb4ba10b723b4fe301..886cd00d3db3cf52c70b2fa1f402323d2dc70b68 100644 --- a/CHANGES +++ b/CHANGES @@ -63,7 +63,24 @@ RTP implementation, please report this and go back to rtp_pt_dynamic = 96. ------------------------------------------------------------------------------ ---- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ---------- +--- Functionality changes from Asterisk 14.2.0 to Asterisk 14.3.0 ------------ +------------------------------------------------------------------------------ + +res_pjproject +------------------ + * Added new CLI command "pjproject set log level". The new command allows + the maximum PJPROJECT log levels to be adjusted dynamically and + independently from the set debug logging level like many other similar + module debug logging commands. + + * Added new companion CLI command "pjproject show log level" to allow the + user to see the current maximum pjproject logging level. + + * Added new pjproject.conf startup section "log_level' option to set the + initial maximum PJPROJECT logging level. + +------------------------------------------------------------------------------ +--- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ------------ ------------------------------------------------------------------------------ AMI @@ -143,7 +160,7 @@ res_ari ARI event. ------------------------------------------------------------------------------ ---- Functionality changes from Asterisk 14.0.0 to Asterisk 14.1.0 ---------- +--- Functionality changes from Asterisk 14.0.0 to Asterisk 14.1.0 ------------ ------------------------------------------------------------------------------ Build System diff --git a/configs/samples/pjproject.conf.sample b/configs/samples/pjproject.conf.sample index 97af7345f40d5fefae4c0921f9b2b738a944235f..82c81a1f6e0c16fcd4a0a132e04080e2d0982efa 100644 --- a/configs/samples/pjproject.conf.sample +++ b/configs/samples/pjproject.conf.sample @@ -1,15 +1,36 @@ ; Common pjproject options ; +;[startup] +; NOTES: The name of this section in the pjproject.conf configuration file must +; remain startup or the configuration will not be applied. +; +;log_level=default ; Initial maximum pjproject logging level to log + ; Valid values are: 0-6, and default + ; + ; Note: This option is needed very early in the startup + ; process so it can only be read from config files because + ; the modules for other methods have not been loaded yet. +;type= ; Must be of type startup (default: "") + ;========================LOG_MAPPINGS SECTION OPTIONS=============================== ;[log_mappings] ; SYNOPSIS: Provides pjproject to Asterisk log level mappings. ; NOTES: The name of this section in the pjproject.conf configuration file must ; remain log_mappings or the configuration will not be applied. ; The defaults mentioned below only apply if this file or the 'log_mappings' -; object can'tbe found. If the object is found, there are no defaults. If +; object can't be found. If the object is found, there are no defaults. If ; you don't specify an entry, nothing will be logged for that level. ; +; These logging level meanings are typically used by pjproject: +; - 0: fatal error +; - 1: error +; - 2: warning +; - 3: info +; - 4: debug +; - 5: trace +; - 6: more detailed trace +; ;asterisk_error = ; A comma separated list of pjproject log levels to map to ; Asterisk errors. ; (default: "0,1") @@ -24,5 +45,5 @@ ; (default: "") ;asterisk_debug = ; A comma separated list of pjproject log levels to map to ; Asterisk debug - ; (default: "3,4,5") + ; (default: "3,4,5,6") ;type= ; Must be of type log_mappings (default: "") diff --git a/include/asterisk/options.h b/include/asterisk/options.h index 345bacf6c58de95173464ce80f5b0c9bd0bb1fde..ff35c16c435beaded9b7676f7e389789340028df 100644 --- a/include/asterisk/options.h +++ b/include/asterisk/options.h @@ -132,6 +132,20 @@ enum ast_option_flags { #define ast_opt_generic_plc ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) #define ast_opt_ref_debug ast_test_flag(&ast_options, AST_OPT_FLAG_REF_DEBUG) +/*! Maximum log level defined by PJPROJECT. */ +#define MAX_PJ_LOG_MAX_LEVEL 6 +/*! + * Normal PJPROJECT active log level used by Asterisk. + * + * These levels are usually mapped to Error and + * Warning Asterisk log levels which shouldn't + * normally be suppressed. + */ +#define DEFAULT_PJ_LOG_MAX_LEVEL 2 + +/*! Current pjproject logging level */ +extern int ast_option_pjproject_log_level; + extern struct ast_flags ast_options; extern int option_verbose; diff --git a/main/asterisk.c b/main/asterisk.c index 98ae8811f945a47a326b45177f5da8efc9116021..338c1f53b94c4a161f21cc1e8d50aa7d27cb06a4 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -330,6 +330,7 @@ int ast_verb_sys_level; int option_verbose; /*!< Verbosity level */ int option_debug; /*!< Debug level */ +int ast_option_pjproject_log_level; double ast_option_maxload; /*!< Max load avg on system */ int ast_option_maxcalls; /*!< Max number of active calls */ int ast_option_maxfiles; /*!< Max number of open file handles (files, sockets) */ @@ -3757,6 +3758,37 @@ static void ast_readconfig(void) ast_config_destroy(cfg); } +static void read_pjproject_startup_options(void) +{ + struct ast_config *cfg; + struct ast_variable *v; + struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE | CONFIG_FLAG_NOREALTIME }; + + ast_option_pjproject_log_level = DEFAULT_PJ_LOG_MAX_LEVEL; + + cfg = ast_config_load2("pjproject.conf", "" /* core, can't reload */, config_flags); + if (!cfg + || cfg == CONFIG_STATUS_FILEUNCHANGED + || cfg == CONFIG_STATUS_FILEINVALID) { + /* We'll have to use defaults */ + return; + } + + for (v = ast_variable_browse(cfg, "startup"); v; v = v->next) { + if (!strcasecmp(v->name, "log_level")) { + if (sscanf(v->value, "%30d", &ast_option_pjproject_log_level) != 1) { + ast_option_pjproject_log_level = DEFAULT_PJ_LOG_MAX_LEVEL; + } else if (ast_option_pjproject_log_level < 0) { + ast_option_pjproject_log_level = 0; + } else if (MAX_PJ_LOG_MAX_LEVEL < ast_option_pjproject_log_level) { + ast_option_pjproject_log_level = MAX_PJ_LOG_MAX_LEVEL; + } + } + } + + ast_config_destroy(cfg); +} + static void *monitor_sig_flags(void *unused) { for (;;) { @@ -4513,6 +4545,7 @@ static void asterisk_daemon(int isroot, const char *runuser, const char *rungrou check_init(ast_timing_init(), "Timing"); check_init(ast_ssl_init(), "SSL"); + read_pjproject_startup_options(); check_init(ast_pj_init(), "Embedded PJProject"); check_init(app_init(), "App Core"); check_init(devstate_init(), "Device State Core"); diff --git a/main/libasteriskpj.c b/main/libasteriskpj.c index 22660e686a654a3ac5dd11930d9e111db602e6a4..0f893a2cf72038a519dcfd942b99f7555e0fe822 100644 --- a/main/libasteriskpj.c +++ b/main/libasteriskpj.c @@ -35,6 +35,7 @@ #include <pjlib.h> #endif +#include "asterisk/options.h" #include "asterisk/_private.h" /* ast_pj_init() */ /*! @@ -44,6 +45,7 @@ int ast_pj_init(void) { #ifdef HAVE_PJPROJECT_BUNDLED + pj_log_set_level(ast_option_pjproject_log_level); pj_init(); #endif return 0; diff --git a/res/res_pjproject.c b/res/res_pjproject.c index 66c95f2b7543daccf3cd957fdb203fee321d3e61..476defb416828aca9916ac6ebb574a2b3d554a1a 100644 --- a/res/res_pjproject.c +++ b/res/res_pjproject.c @@ -41,6 +41,27 @@ <configInfo name="res_pjproject" language="en_US"> <synopsis>pjproject common configuration</synopsis> <configFile name="pjproject.conf"> + <configObject name="startup"> + <synopsis>Asterisk startup time options for PJPROJECT</synopsis> + <description> + <note><para>The id of this object, as well as its type, must be + 'startup' or it won't be found.</para></note> + </description> + <configOption name="type"> + <synopsis>Must be of type 'startup'.</synopsis> + </configOption> + <configOption name="log_level" default="2"> + <synopsis>Initial maximum pjproject logging level to log.</synopsis> + <description> + <para>Valid values are: 0-6, and default</para> + <note><para> + This option is needed very early in the startup process + so it can only be read from config files because the + modules for other methods have not been loaded yet. + </para></note> + </description> + </configOption> + </configObject> <configObject name="log_mappings"> <synopsis>PJPROJECT to Asterisk Log Level Mapping</synopsis> <description><para>Warnings and errors in the pjproject libraries are generally handled @@ -64,7 +85,7 @@ <configOption name="asterisk_notice" default=""> <synopsis>A comma separated list of pjproject log levels to map to Asterisk LOG_NOTICE.</synopsis> </configOption> - <configOption name="asterisk_debug" default="3,4,5"> + <configOption name="asterisk_debug" default="3,4,5,6"> <synopsis>A comma separated list of pjproject log levels to map to Asterisk LOG_DEBUG.</synopsis> </configOption> <configOption name="asterisk_verbose" default=""> @@ -82,6 +103,7 @@ #include <pjsip.h> #include <pj/log.h> +#include "asterisk/options.h" #include "asterisk/logger.h" #include "asterisk/module.h" #include "asterisk/cli.h" @@ -144,9 +166,11 @@ static struct log_mappings *get_log_mappings(void) static int get_log_level(int pj_level) { - RAII_VAR(struct log_mappings *, mappings, get_log_mappings(), ao2_cleanup); + int mapped_level; unsigned char l; + struct log_mappings *mappings; + mappings = get_log_mappings(); if (!mappings) { return __LOG_ERROR; } @@ -154,18 +178,21 @@ static int get_log_level(int pj_level) l = '0' + fmin(pj_level, 9); if (strchr(mappings->asterisk_error, l)) { - return __LOG_ERROR; + mapped_level = __LOG_ERROR; } else if (strchr(mappings->asterisk_warning, l)) { - return __LOG_WARNING; + mapped_level = __LOG_WARNING; } else if (strchr(mappings->asterisk_notice, l)) { - return __LOG_NOTICE; + mapped_level = __LOG_NOTICE; } else if (strchr(mappings->asterisk_verbose, l)) { - return __LOG_VERBOSE; + mapped_level = __LOG_VERBOSE; } else if (strchr(mappings->asterisk_debug, l)) { - return __LOG_DEBUG; + mapped_level = __LOG_DEBUG; + } else { + mapped_level = __LOG_SUPPRESS; } - return __LOG_SUPPRESS; + ao2_ref(mappings, -1); + return mapped_level; } static void log_forwarder(int level, const char *data, int len) @@ -192,13 +219,6 @@ static void log_forwarder(int level, const char *data, int len) return; } - if (ast_level == __LOG_DEBUG) { - /* Obey the debug level for res_pjproject */ - if (!DEBUG_ATLEAST(level)) { - return; - } - } - /* 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 */ @@ -349,9 +369,95 @@ static char *handle_pjproject_show_log_mappings(struct ast_cli_entry *e, int cmd return CLI_SUCCESS; } +struct max_pjproject_log_level_check { + /*! + * Compile time sanity check to determine if + * MAX_PJ_LOG_MAX_LEVEL matches CLI syntax. + */ + char check[1 / (6 == MAX_PJ_LOG_MAX_LEVEL)]; +}; + +static char *handle_pjproject_set_log_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + int level_new; + int level_old; + + switch (cmd) { + case CLI_INIT: + e->command = "pjproject set log level {default|0|1|2|3|4|5|6}"; + e->usage = + "Usage: pjproject set log level {default|<level>}\n" + "\n" + " Set the maximum active pjproject logging level.\n" + " See pjproject.conf.sample for additional information\n" + " about the various levels pjproject uses.\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + + if (a->argc != 5) { + return CLI_SHOWUSAGE; + } + + if (!strcasecmp(a->argv[4], "default")) { + level_new = DEFAULT_PJ_LOG_MAX_LEVEL; + } else { + if (sscanf(a->argv[4], "%30d", &level_new) != 1 + || level_new < 0 || MAX_PJ_LOG_MAX_LEVEL < level_new) { + return CLI_SHOWUSAGE; + } + } + + /* Update pjproject logging level */ + level_old = ast_option_pjproject_log_level; + if (level_old == level_new) { + ast_cli(a->fd, "pjproject log level is still %d.\n", level_old); + } else { + ast_cli(a->fd, "pjproject log level was %d and is now %d.\n", + level_old, level_new); + pj_log_set_level(level_new); + } + ast_option_pjproject_log_level = pj_log_get_level(); + if (ast_option_pjproject_log_level != level_new) { + ast_log(LOG_WARNING, "Asterisk built with pjproject PJ_LOG_MAX_LEVEL set too low.\n"); + } + + return CLI_SUCCESS; +} + +static char *handle_pjproject_show_log_level(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "pjproject show log level"; + e->usage = + "Usage: pjproject show log level\n" + "\n" + " Show the current maximum active pjproject logging level.\n" + " See pjproject.conf.sample for additional information\n" + " about the various levels pjproject uses.\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + + if (a->argc != 4) { + return CLI_SHOWUSAGE; + } + + ast_cli(a->fd, "pjproject log level is %d.%s\n", + ast_option_pjproject_log_level, + ast_option_pjproject_log_level == DEFAULT_PJ_LOG_MAX_LEVEL ? " (default)" : ""); + + return CLI_SUCCESS; +} + static struct ast_cli_entry pjproject_cli[] = { + AST_CLI_DEFINE(handle_pjproject_set_log_level, "Set the maximum active pjproject logging level"), AST_CLI_DEFINE(handle_pjproject_show_buildopts, "Show the compiled config of the pjproject in use"), AST_CLI_DEFINE(handle_pjproject_show_log_mappings, "Show pjproject to Asterisk log mappings"), + AST_CLI_DEFINE(handle_pjproject_show_log_level, "Show the maximum active pjproject logging level"), }; static int load_module(void) @@ -385,10 +491,11 @@ static int load_module(void) } ast_string_field_set(default_log_mappings, asterisk_error, "0,1"); ast_string_field_set(default_log_mappings, asterisk_warning, "2"); - ast_string_field_set(default_log_mappings, asterisk_debug, "3,4,5"); + ast_string_field_set(default_log_mappings, asterisk_debug, "3,4,5,6"); ast_sorcery_load(pjproject_sorcery); + pj_log_set_level(ast_option_pjproject_log_level); pj_init(); decor_orig = pj_log_get_decor(); @@ -403,9 +510,15 @@ static int load_module(void) */ pj_log_set_log_func(capture_buildopts_cb); pj_log_set_decor(0); + pj_log_set_level(MAX_PJ_LOG_MAX_LEVEL);/* Set level to guarantee the dump output. */ pj_dump_config(); + pj_log_set_level(ast_option_pjproject_log_level); pj_log_set_decor(PJ_LOG_HAS_SENDER | PJ_LOG_HAS_INDENT); pj_log_set_log_func(log_forwarder); + if (!AST_VECTOR_SIZE(&buildopts) + || ast_option_pjproject_log_level != pj_log_get_level()) { + ast_log(LOG_WARNING, "Asterisk built or linked with pjproject PJ_LOG_MAX_LEVEL set too low.\n"); + } ast_cli_register_multiple(pjproject_cli, ARRAY_LEN(pjproject_cli)); diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 4136f7e7bf0717cd7a622687e2eae46a90e4432e..58c217ecb48e3f06f62689c001c9ab279dccb6d0 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -52,6 +52,7 @@ #include <ifaddrs.h> #endif +#include "asterisk/options.h" #include "asterisk/stun.h" #include "asterisk/pbx.h" #include "asterisk/frame.h" @@ -5665,6 +5666,7 @@ static int load_module(void) #ifdef HAVE_PJPROJECT pj_lock_t *lock; + pj_log_set_level(ast_option_pjproject_log_level); if (pj_init() != PJ_SUCCESS) { return AST_MODULE_LOAD_DECLINE; } diff --git a/third-party/pjproject/patches/config_site.h b/third-party/pjproject/patches/config_site.h index 1a48695bfb2d0ad088197171a49413f1882080f4..66e8e84d3f1daff5cbb7c5e51d201901d0bb8020 100644 --- a/third-party/pjproject/patches/config_site.h +++ b/third-party/pjproject/patches/config_site.h @@ -34,7 +34,7 @@ #define PJ_SCANNER_USE_BITWISE 0 #define PJ_OS_HAS_CHECK_STACK 0 -#define PJ_LOG_MAX_LEVEL 3 +#define PJ_LOG_MAX_LEVEL 6 #define PJ_ENABLE_EXTRA_CHECK 1 #define PJSIP_MAX_TSX_COUNT ((64*1024)-1) #define PJSIP_MAX_DIALOG_COUNT ((64*1024)-1)