2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2013, Digium, Inc.
6 * David M. Lee, II <dlee@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Bridge PJSIP logging to Asterisk logging.
22 * \author David M. Lee, II <dlee@digium.com>
24 * PJSIP logging doesn't exactly match Asterisk logging, but mapping the two is
25 * not too bad. PJSIP log levels are identified by a single int. Limits are
26 * not specified by PJSIP, but their implementation used 1 through 6.
28 * The mapping is as follows:
32 * - 3 and above: equivalent to ast_debug(level, ...) for res_pjsip.so
36 <depend>pjproject</depend>
37 <support_level>core</support_level>
42 ASTERISK_REGISTER_FILE()
47 #include "asterisk/logger.h"
48 #include "asterisk/module.h"
49 #include "asterisk/cli.h"
51 static pj_log_func *log_cb_orig;
52 static unsigned decor_orig;
54 /*! Protection from other CLI instances. */
55 AST_MUTEX_DEFINE_STATIC(show_buildopts_lock);
57 struct pjsip_show_buildopts {
62 static struct pjsip_show_buildopts show_buildopts = {
63 .thread = AST_PTHREADT_NULL,
67 static void log_cb(int level, const char *data, int len)
70 /* PJSIP doesn't provide much in the way of source info */
71 const char * log_source = "pjsip";
73 const char *log_func = "<?>";
76 if (show_buildopts.fd != -1 && show_buildopts.thread == pthread_self()) {
78 * We are handling the CLI command dumping the
79 * PJPROJECT compile time config option settings.
81 ast_cli(show_buildopts.fd, "%s\n", data);
85 /* Lower number indicates higher importance */
87 case 0: /* level zero indicates fatal error, according to docs */
88 case 1: /* 1 seems to be used for errors */
89 ast_level = __LOG_ERROR;
91 case 2: /* 2 seems to be used for warnings and errors */
92 ast_level = __LOG_WARNING;
95 ast_level = __LOG_DEBUG;
97 /* For levels 3 and up, obey the debug level for res_pjsip */
98 mod_level = ast_opt_dbg_module ?
99 ast_debug_get_by_module("res_pjsip") : 0;
100 if (option_debug < level && mod_level < level) {
106 /* PJSIP uses indention to indicate function call depth. We'll prepend
107 * log statements with a tab so they'll have a better shot at lining
109 ast_log(ast_level, log_source, log_line, log_func, "\t%s\n", data);
112 static char *handle_pjsip_show_buildopts(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
116 e->command = "pjsip show buildopts";
118 "Usage: pjsip show buildopts\n"
119 " Show the compile time config of pjproject that res_pjsip is\n"
120 " running against.\n";
126 ast_cli(a->fd, "PJPROJECT compile time config currently running against:\n");
128 /* Protect from other CLI instances trying to do this at the same time. */
129 ast_mutex_lock(&show_buildopts_lock);
131 show_buildopts.thread = pthread_self();
132 show_buildopts.fd = a->fd;
134 show_buildopts.fd = -1;
135 show_buildopts.thread = AST_PTHREADT_NULL;
137 ast_mutex_unlock(&show_buildopts_lock);
142 static struct ast_cli_entry pjsip_cli[] = {
143 AST_CLI_DEFINE(handle_pjsip_show_buildopts, "Show the compiled config of pjproject in use"),
146 static int load_module(void)
150 decor_orig = pj_log_get_decor();
151 log_cb_orig = pj_log_get_log_func();
153 ast_debug(3, "Forwarding PJSIP logger to Asterisk logger\n");
154 /* SENDER prepends the source to the log message. This could be a
155 * filename, object reference, or simply a string
157 * INDENT is assumed to be on by most log statements in PJSIP itself.
159 pj_log_set_decor(PJ_LOG_HAS_SENDER | PJ_LOG_HAS_INDENT);
160 pj_log_set_log_func(log_cb);
162 ast_cli_register_multiple(pjsip_cli, ARRAY_LEN(pjsip_cli));
164 return AST_MODULE_LOAD_SUCCESS;
167 static int unload_module(void)
169 ast_cli_unregister_multiple(pjsip_cli, ARRAY_LEN(pjsip_cli));
171 pj_log_set_log_func(log_cb_orig);
172 pj_log_set_decor(decor_orig);
179 /* While we don't really export global symbols, we want to load before other
181 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "PJSIP Log Forwarder",
182 .support_level = AST_MODULE_SUPPORT_CORE,
184 .unload = unload_module,
185 .load_pri = AST_MODPRI_CHANNEL_DEPEND - 6,