Asterisk - The Open Source Telephony Project GIT-master-7e7a603
Data Structures | Macros | Functions | Variables
res_pjproject.c File Reference

Bridge PJPROJECT logging to Asterisk logging. More...

#include "asterisk.h"
#include <stdarg.h>
#include <pjlib.h>
#include <pjsip.h>
#include <pj/log.h>
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/res_pjproject.h"
#include "asterisk/vector.h"
#include "asterisk/sorcery.h"
#include "asterisk/test.h"
#include "asterisk/netsock2.h"
Include dependency graph for res_pjproject.c:

Go to the source code of this file.

Data Structures

struct  buildopts
 
struct  log_mappings
 
struct  max_pjproject_log_level_check
 
struct  pjproject_log_intercept_data
 

Macros

#define __LOG_SUPPRESS   -1
 
#define NOT_EQUALS(a, b)   (a != b)
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
void ast_pjproject_caching_pool_destroy (pj_caching_pool *cp)
 Destroy caching pool factory and all cached pools. More...
 
void ast_pjproject_caching_pool_init (pj_caching_pool *cp, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
 Initialize the caching pool factory. More...
 
int ast_pjproject_get_buildopt (char *option, char *format_string,...)
 Retrieve a pjproject build option. More...
 
void ast_pjproject_log_intercept_begin (int fd)
 Begin PJPROJECT log interception for CLI output. More...
 
void ast_pjproject_log_intercept_end (void)
 End PJPROJECT log interception for CLI output. More...
 
int ast_sockaddr_from_pj_sockaddr (struct ast_sockaddr *addr, const pj_sockaddr *pjaddr)
 Fill an ast_sockaddr from a pj_sockaddr. More...
 
int ast_sockaddr_pj_sockaddr_cmp (const struct ast_sockaddr *addr, const pj_sockaddr *pjaddr)
 Compare an ast_sockaddr to a pj_sockaddr. More...
 
int ast_sockaddr_to_pj_sockaddr (const struct ast_sockaddr *addr, pj_sockaddr *pjaddr)
 Fill a pj_sockaddr from an ast_sockaddr. More...
 
static void capture_buildopts_cb (int level, const char *data, int len)
 
static int get_log_level (int pj_level)
 
static struct log_mappingsget_log_mappings (void)
 
static char * handle_pjproject_set_log_level (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_pjproject_show_buildopts (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_pjproject_show_log_level (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_pjproject_show_log_mappings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int load_module (void)
 
static void log_forwarder (int level, const char *data, int len)
 
static void * mapping_alloc (const char *name)
 
static void mapping_destroy (void *object)
 
static int reload_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PJPROJECT Log and Utility Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND - 6, .requires = "res_sorcery_config", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct buildopts buildopts
 
static unsigned decor_orig
 
static struct log_mappingsdefault_log_mappings
 
static pj_log_func * log_cb_orig
 
static struct ast_cli_entry pjproject_cli []
 
static struct pjproject_log_intercept_data pjproject_log_intercept
 
static ast_mutex_t pjproject_log_intercept_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static struct ast_sorcerypjproject_sorcery
 

Detailed Description

Bridge PJPROJECT logging to Asterisk logging.

Author
David M. Lee, II dlee@.nosp@m.digi.nosp@m.um.co.nosp@m.m

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:

Definition in file res_pjproject.c.

Macro Definition Documentation

◆ __LOG_SUPPRESS

#define __LOG_SUPPRESS   -1

Definition at line 176 of file res_pjproject.c.

◆ NOT_EQUALS

#define NOT_EQUALS (   a,
  b 
)    (a != b)

Definition at line 766 of file res_pjproject.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 808 of file res_pjproject.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 808 of file res_pjproject.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 808 of file res_pjproject.c.

◆ ast_pjproject_caching_pool_destroy()

void ast_pjproject_caching_pool_destroy ( pj_caching_pool *  cp)

Destroy caching pool factory and all cached pools.

Since
13.21.0
Parameters
cpCaching pool factory to destroy

Definition at line 484 of file res_pjproject.c.

485{
486 pj_caching_pool_destroy(cp);
487}

Referenced by unload_module(), and unload_pjsip().

◆ ast_pjproject_caching_pool_init()

void ast_pjproject_caching_pool_init ( pj_caching_pool *  cp,
const pj_pool_factory_policy *  policy,
pj_size_t  max_capacity 
)

Initialize the caching pool factory.

Since
13.21.0
Parameters
cpCaching pool factory to initialize
policyPool factory policy
max_capacityTotal capacity to be retained in the cache. Zero disables caching.

Definition at line 477 of file res_pjproject.c.

479{
480 /* Passing a max_capacity of zero disables caching pools */
481 pj_caching_pool_init(cp, policy, ast_option_pjproject_cache_pools ? max_capacity : 0);
482}
int ast_option_pjproject_cache_pools
Definition: options.c:75

References ast_option_pjproject_cache_pools.

Referenced by load_module(), and load_pjsip().

◆ ast_pjproject_get_buildopt()

int ast_pjproject_get_buildopt ( char *  option,
char *  format_string,
  ... 
)

Retrieve a pjproject build option.

Parameters
optionThe build option requested
format_stringA scanf-style format string to parse the option value into
...Pointers to variables to receive the values parsed
Return values
Thenumber 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.

Sample Usage:

int max_hostname;
ast_sip_get_pjproject_buildopt("PJ_MAX_HOSTNAME", "%d", &max_hostname);

Definition at line 256 of file res_pjproject.c.

257{
258 int res = 0;
259 char *format_temp;
260 int i;
261
262 format_temp = ast_alloca(strlen(option) + strlen(" : ") + strlen(format_string) + 1);
263 sprintf(format_temp, "%s : %s", option, format_string);
264
265 for (i = 0; i < AST_VECTOR_SIZE(&buildopts); i++) {
266 va_list arg_ptr;
267 va_start(arg_ptr, format_string);
268 res = vsscanf(AST_VECTOR_GET(&buildopts, i), format_temp, arg_ptr);
269 va_end(arg_ptr);
270 if (res) {
271 break;
272 }
273 }
274
275 return res;
276}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References ast_alloca, AST_VECTOR_GET, and AST_VECTOR_SIZE.

Referenced by ast_sip_initialize_sorcery_location(), and load_module().

◆ ast_pjproject_log_intercept_begin()

void ast_pjproject_log_intercept_begin ( int  fd)

Begin PJPROJECT log interception for CLI output.

Since
13.8.0
Parameters
fdCLI file descriptior to send intercepted output.
Note
ast_pjproject_log_intercept_begin() and ast_pjproject_log_intercept_end() must always be called in pairs.

Definition at line 279 of file res_pjproject.c.

280{
281 /* Protect from other CLI instances trying to do this at the same time. */
283
284 pjproject_log_intercept.thread = pthread_self();
286}
#define ast_mutex_lock(a)
Definition: lock.h:189
static struct pjproject_log_intercept_data pjproject_log_intercept
static ast_mutex_t pjproject_log_intercept_lock

References ast_mutex_lock, pjproject_log_intercept_data::fd, pjproject_log_intercept, pjproject_log_intercept_lock, and pjproject_log_intercept_data::thread.

Referenced by do_cli_dump_endpt().

◆ ast_pjproject_log_intercept_end()

void ast_pjproject_log_intercept_end ( void  )

End PJPROJECT log interception for CLI output.

Since
13.8.0
Note
ast_pjproject_log_intercept_begin() and ast_pjproject_log_intercept_end() must always be called in pairs.

Definition at line 288 of file res_pjproject.c.

289{
292
294}
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_mutex_unlock(a)
Definition: lock.h:190

References ast_mutex_unlock, AST_PTHREADT_NULL, pjproject_log_intercept_data::fd, pjproject_log_intercept, pjproject_log_intercept_lock, and pjproject_log_intercept_data::thread.

Referenced by do_cli_dump_endpt().

◆ ast_sockaddr_from_pj_sockaddr()

int ast_sockaddr_from_pj_sockaddr ( struct ast_sockaddr addr,
const pj_sockaddr *  pjaddr 
)

Fill an ast_sockaddr from a pj_sockaddr.

Since
13.24.0
Parameters
addrThe target address to receive the copied address
pjaddrThe source address to copy
Return values
0Success
-1Failure

Definition at line 514 of file res_pjproject.c.

515{
516 if (pjaddr->addr.sa_family == pj_AF_INET()) {
517 struct sockaddr_in *sin = (struct sockaddr_in *) &addr->ss;
518 sin->sin_family = AF_INET;
519#if defined(HAVE_PJPROJECT_BUNDLED) && !defined(HAVE_PJPROJECT_BUNDLED_OOT)
520 sin->sin_addr = pjaddr->ipv4.sin_addr;
521#else
522 sin->sin_addr.s_addr = pjaddr->ipv4.sin_addr.s_addr;
523#endif
524 sin->sin_port = pjaddr->ipv4.sin_port;
525 memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
526 addr->len = sizeof(struct sockaddr_in);
527 } else if (pjaddr->addr.sa_family == pj_AF_INET6()) {
528 struct sockaddr_in6 *sin = (struct sockaddr_in6 *) &addr->ss;
529 sin->sin6_family = AF_INET6;
530 sin->sin6_port = pjaddr->ipv6.sin6_port;
531 sin->sin6_flowinfo = pjaddr->ipv6.sin6_flowinfo;
532 sin->sin6_scope_id = pjaddr->ipv6.sin6_scope_id;
533 memcpy(&sin->sin6_addr, &pjaddr->ipv6.sin6_addr, sizeof(sin->sin6_addr));
534 addr->len = sizeof(struct sockaddr_in6);
535 } else {
536 memset(addr, 0, sizeof(*addr));
537 return -1;
538 }
539 return 0;
540}
struct sockaddr_storage ss
Definition: netsock2.h:98
socklen_t len
Definition: netsock2.h:99

References ast_sockaddr::len, and ast_sockaddr::ss.

Referenced by ast_sockaddr_pj_sockaddr_cmp().

◆ ast_sockaddr_pj_sockaddr_cmp()

int ast_sockaddr_pj_sockaddr_cmp ( const struct ast_sockaddr addr,
const pj_sockaddr *  pjaddr 
)

Compare an ast_sockaddr to a pj_sockaddr.

Parameters
addrpointer to ast_sockaddr structure
pjaddrpointer to pj_sockaddr structure
Return values
-1addr is lexicographically smaller than pjaddr
0addr is equal to pjaddr
1pjaddr is lexicographically smaller than addr

Definition at line 542 of file res_pjproject.c.

544{
545 struct ast_sockaddr temp_pjaddr;
546 int rc = 0;
547
548 rc = ast_sockaddr_from_pj_sockaddr(&temp_pjaddr, pjaddr);
549 if (rc != 0) {
550 return -1;
551 }
552
553 rc = ast_sockaddr_cmp(addr, &temp_pjaddr);
554 if (DEBUG_ATLEAST(4)) {
555 char *a_str = ast_strdupa(ast_sockaddr_stringify(addr));
556 char *pj_str = ast_strdupa(ast_sockaddr_stringify(&temp_pjaddr));
557 ast_debug(4, "Comparing %s -> %s rc: %d\n", a_str, pj_str, rc);
558 }
559
560 return rc;
561}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
int ast_sockaddr_from_pj_sockaddr(struct ast_sockaddr *addr, const pj_sockaddr *pjaddr)
Fill an ast_sockaddr from a pj_sockaddr.
Socket address structure.
Definition: netsock2.h:97

References ast_debug, ast_sockaddr_cmp(), ast_sockaddr_from_pj_sockaddr(), ast_sockaddr_stringify(), ast_strdupa, and DEBUG_ATLEAST.

Referenced by __rtp_recvfrom().

◆ ast_sockaddr_to_pj_sockaddr()

int ast_sockaddr_to_pj_sockaddr ( const struct ast_sockaddr addr,
pj_sockaddr *  pjaddr 
)

Fill a pj_sockaddr from an ast_sockaddr.

Since
13.24.0
Parameters
addrThe source address to copy
pjaddrThe target address to receive the copied address
Return values
0Success
-1Failure

Definition at line 489 of file res_pjproject.c.

490{
491 if (addr->ss.ss_family == AF_INET) {
492 struct sockaddr_in *sin = (struct sockaddr_in *) &addr->ss;
493 pjaddr->ipv4.sin_family = pj_AF_INET();
494#if defined(HAVE_PJPROJECT_BUNDLED) && !defined(HAVE_PJPROJECT_BUNDLED_OOT)
495 pjaddr->ipv4.sin_addr = sin->sin_addr;
496#else
497 pjaddr->ipv4.sin_addr.s_addr = sin->sin_addr.s_addr;
498#endif
499 pjaddr->ipv4.sin_port = sin->sin_port;
500 } else if (addr->ss.ss_family == AF_INET6) {
501 struct sockaddr_in6 *sin = (struct sockaddr_in6 *) &addr->ss;
502 pjaddr->ipv6.sin6_family = pj_AF_INET6();
503 pjaddr->ipv6.sin6_port = sin->sin6_port;
504 pjaddr->ipv6.sin6_flowinfo = sin->sin6_flowinfo;
505 pjaddr->ipv6.sin6_scope_id = sin->sin6_scope_id;
506 memcpy(&pjaddr->ipv6.sin6_addr, &sin->sin6_addr, sizeof(pjaddr->ipv6.sin6_addr));
507 } else {
508 memset(pjaddr, 0, sizeof(*pjaddr));
509 return -1;
510 }
511 return 0;
512}

References ast_sockaddr::ss.

◆ capture_buildopts_cb()

static void capture_buildopts_cb ( int  level,
const char *  data,
int  len 
)
static

Definition at line 241 of file res_pjproject.c.

242{
243 char *dup;
244
245 if (strstr(data, "Teluu") || strstr(data, "Dumping")) {
246 return;
247 }
248
249 dup = ast_strdup(ast_skip_blanks(data));
250 if (dup && AST_VECTOR_ADD_SORTED(&buildopts, dup, strcmp)) {
251 ast_free(dup);
252 }
253}
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:371

References ast_free, ast_skip_blanks(), ast_strdup, and AST_VECTOR_ADD_SORTED.

Referenced by load_module().

◆ get_log_level()

static int get_log_level ( int  pj_level)
static

Definition at line 178 of file res_pjproject.c.

179{
180 int mapped_level;
181 unsigned char l;
182 struct log_mappings *mappings;
183
185 if (!mappings) {
186 return __LOG_ERROR;
187 }
188
189 l = '0' + fmin(pj_level, 9);
190
191 if (strchr(mappings->asterisk_error, l)) {
192 mapped_level = __LOG_ERROR;
193 } else if (strchr(mappings->asterisk_warning, l)) {
194 mapped_level = __LOG_WARNING;
195 } else if (strchr(mappings->asterisk_notice, l)) {
196 mapped_level = __LOG_NOTICE;
197 } else if (strchr(mappings->asterisk_verbose, l)) {
198 mapped_level = __LOG_VERBOSE;
199 } else if (strchr(mappings->asterisk_debug, l)) {
200 mapped_level = __LOG_DEBUG;
201 } else if (strchr(mappings->asterisk_trace, l)) {
202 mapped_level = __LOG_TRACE;
203 } else {
204 mapped_level = __LOG_SUPPRESS;
205 }
206
207 ao2_ref(mappings, -1);
208 return mapped_level;
209}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define __LOG_ERROR
#define __LOG_TRACE
#define __LOG_VERBOSE
#define __LOG_NOTICE
#define __LOG_DEBUG
#define __LOG_WARNING
static struct mappings mappings
#define __LOG_SUPPRESS
static struct log_mappings * get_log_mappings(void)

References __LOG_DEBUG, __LOG_ERROR, __LOG_NOTICE, __LOG_SUPPRESS, __LOG_TRACE, __LOG_VERBOSE, __LOG_WARNING, ao2_ref, get_log_mappings(), and mappings.

Referenced by log_forwarder().

◆ get_log_mappings()

static struct log_mappings * get_log_mappings ( void  )
static

Definition at line 164 of file res_pjproject.c.

165{
166 struct log_mappings *mappings;
167
168 mappings = ast_sorcery_retrieve_by_id(pjproject_sorcery, "log_mappings", "log_mappings");
169 if (!mappings) {
171 }
172
173 return mappings;
174}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static struct ast_sorcery * pjproject_sorcery
static struct log_mappings * default_log_mappings
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853

References ao2_bump, ast_sorcery_retrieve_by_id(), default_log_mappings, mappings, and pjproject_sorcery.

Referenced by get_log_level(), and handle_pjproject_show_log_mappings().

◆ handle_pjproject_set_log_level()

static char * handle_pjproject_set_log_level ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 388 of file res_pjproject.c.

389{
390 int level_new;
391 int level_old;
392
393 switch (cmd) {
394 case CLI_INIT:
395 e->command = "pjproject set log level {default|0|1|2|3|4|5|6}";
396 e->usage =
397 "Usage: pjproject set log level {default|<level>}\n"
398 "\n"
399 " Set the maximum active pjproject logging level.\n"
400 " See pjproject.conf.sample for additional information\n"
401 " about the various levels pjproject uses.\n"
402 " Note: setting this level at 4 or above may result in\n"
403 " raw packet logging.\n";
404 return NULL;
405 case CLI_GENERATE:
406 return NULL;
407 }
408
409 if (a->argc != 5) {
410 return CLI_SHOWUSAGE;
411 }
412
413 if (!strcasecmp(a->argv[4], "default")) {
414 level_new = DEFAULT_PJ_LOG_MAX_LEVEL;
415 } else {
416 if (sscanf(a->argv[4], "%30d", &level_new) != 1
417 || level_new < 0 || MAX_PJ_LOG_MAX_LEVEL < level_new) {
418 return CLI_SHOWUSAGE;
419 }
420 }
421
422 /* Update pjproject logging level */
423 if (ast_pjproject_max_log_level < level_new) {
424 level_new = ast_pjproject_max_log_level;
425 ast_cli(a->fd,
426 "Asterisk built or linked with pjproject PJ_LOG_MAX_LEVEL=%d.\n"
427 "Lowering request to the max supported level.\n",
429 }
431 if (level_old == level_new) {
432 ast_cli(a->fd, "pjproject log level is still %d.\n", level_old);
433 } else {
434 ast_cli(a->fd, "pjproject log level was %d and is now %d.\n",
435 level_old, level_new);
437 pj_log_set_level(level_new);
438 }
439
440 return CLI_SUCCESS;
441}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
int ast_pjproject_max_log_level
Definition: options.c:73
int ast_option_pjproject_log_level
Definition: options.c:74
#define MAX_PJ_LOG_MAX_LEVEL
Definition: options.h:141
#define DEFAULT_PJ_LOG_MAX_LEVEL
Definition: options.h:149
#define NULL
Definition: resample.c:96
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ast_cli(), ast_option_pjproject_log_level, ast_pjproject_max_log_level, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, DEFAULT_PJ_LOG_MAX_LEVEL, MAX_PJ_LOG_MAX_LEVEL, NULL, and ast_cli_entry::usage.

◆ handle_pjproject_show_buildopts()

static char * handle_pjproject_show_buildopts ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 296 of file res_pjproject.c.

297{
298 int i;
299
300 switch (cmd) {
301 case CLI_INIT:
302 e->command = "pjproject show buildopts";
303 e->usage =
304 "Usage: pjproject show buildopts\n"
305 " Show the compile time config of the pjproject that Asterisk is\n"
306 " running against.\n";
307 return NULL;
308 case CLI_GENERATE:
309 return NULL;
310 }
311
312 ast_cli(a->fd, "PJPROJECT compile time config currently running against:\n");
313
314 for (i = 0; i < AST_VECTOR_SIZE(&buildopts); i++) {
315 ast_cli(a->fd, "%s\n", AST_VECTOR_GET(&buildopts, i));
316 }
317
318 return CLI_SUCCESS;
319}

References a, ast_cli(), AST_VECTOR_GET, AST_VECTOR_SIZE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_pjproject_show_log_level()

static char * handle_pjproject_show_log_level ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 443 of file res_pjproject.c.

444{
445 switch (cmd) {
446 case CLI_INIT:
447 e->command = "pjproject show log level";
448 e->usage =
449 "Usage: pjproject show log level\n"
450 "\n"
451 " Show the current maximum active pjproject logging level.\n"
452 " See pjproject.conf.sample for additional information\n"
453 " about the various levels pjproject uses.\n";
454 return NULL;
455 case CLI_GENERATE:
456 return NULL;
457 }
458
459 if (a->argc != 4) {
460 return CLI_SHOWUSAGE;
461 }
462
463 ast_cli(a->fd, "pjproject log level is %d.%s\n",
466
467 return CLI_SUCCESS;
468}

References a, ast_cli(), ast_option_pjproject_log_level, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, DEFAULT_PJ_LOG_MAX_LEVEL, NULL, and ast_cli_entry::usage.

◆ handle_pjproject_show_log_mappings()

static char * handle_pjproject_show_log_mappings ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 339 of file res_pjproject.c.

340{
341 struct ast_variable *objset;
342 struct ast_variable *i;
343 struct log_mappings *mappings;
344
345 switch (cmd) {
346 case CLI_INIT:
347 e->command = "pjproject show log mappings";
348 e->usage =
349 "Usage: pjproject show log mappings\n"
350 " Show pjproject to Asterisk log mappings\n";
351 return NULL;
352 case CLI_GENERATE:
353 return NULL;
354 }
355
356 ast_cli(a->fd, "PJPROJECT to Asterisk log mappings:\n");
357 ast_cli(a->fd, "Asterisk Level : PJPROJECT log levels\n");
358
360 if (!mappings) {
361 ast_log(LOG_ERROR, "Unable to retrieve pjproject log_mappings\n");
362 return CLI_SUCCESS;
363 }
364
366 if (!objset) {
367 ao2_ref(mappings, -1);
368 return CLI_SUCCESS;
369 }
370
371 for (i = objset; i; i = i->next) {
372 ast_cli(a->fd, "%-16s : %s\n", i->name, i->value);
373 }
374 ast_variables_destroy(objset);
375
376 ao2_ref(mappings, -1);
377 return CLI_SUCCESS;
378}
#define ast_log
Definition: astobj2.c:42
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define LOG_ERROR
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
Definition: sorcery.h:1137
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next

References a, ao2_ref, ast_cli(), ast_log, ast_sorcery_objectset_create, ast_variables_destroy(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, get_log_mappings(), LOG_ERROR, mappings, ast_variable::name, ast_variable::next, NULL, pjproject_sorcery, ast_cli_entry::usage, and ast_variable::value.

◆ load_module()

static int load_module ( void  )
static

Definition at line 689 of file res_pjproject.c.

690{
691 ast_debug(3, "Starting PJPROJECT logging to Asterisk logger\n");
692
694 ast_log(LOG_ERROR, "Failed to open SIP sorcery failed to open\n");
696 }
697
698 ast_sorcery_apply_default(pjproject_sorcery, "log_mappings", "config", "pjproject.conf,criteria=type=log_mappings");
700 ast_log(LOG_WARNING, "Failed to register pjproject log_mappings object with sorcery\n");
704 }
705
706 ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "type", "", OPT_NOOP_T, 0, 0);
707 ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_debug", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_debug));
708 ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_error", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_error));
709 ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_warning", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_warning));
710 ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_notice", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_notice));
711 ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_verbose", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_verbose));
712 ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_trace", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_trace));
713
714 default_log_mappings = ast_sorcery_alloc(pjproject_sorcery, "log_mappings", "log_mappings");
716 ast_log(LOG_ERROR, "Unable to allocate memory for pjproject log_mappings\n");
718 }
719 ast_string_field_set(default_log_mappings, asterisk_error, "0,1");
720 ast_string_field_set(default_log_mappings, asterisk_warning, "2");
721 ast_string_field_set(default_log_mappings, asterisk_debug, "3,4");
722 ast_string_field_set(default_log_mappings, asterisk_trace, "5,6");
723
725
727 pj_init();
728
729 decor_orig = pj_log_get_decor();
730 log_cb_orig = pj_log_get_log_func();
731
732 if (AST_VECTOR_INIT(&buildopts, 64)) {
734 }
735
736 /*
737 * On startup, we want to capture the dump once and store it.
738 */
739 pj_log_set_log_func(capture_buildopts_cb);
740 pj_log_set_decor(0);
741 pj_log_set_level(MAX_PJ_LOG_MAX_LEVEL);/* Set level to guarantee the dump output. */
742 pj_dump_config();
743 pj_log_set_decor(PJ_LOG_HAS_SENDER | PJ_LOG_HAS_INDENT);
744 pj_log_set_log_func(log_forwarder);
747 "Asterisk built or linked with pjproject PJ_LOG_MAX_LEVEL=%d which is too low for startup level: %d.\n",
750 }
751 pj_log_set_level(ast_option_pjproject_log_level);
752 if (!AST_VECTOR_SIZE(&buildopts)) {
754 "Asterisk built or linked with pjproject PJ_LOG_MAX_LEVEL=%d which is too low to get buildopts.\n",
756 }
757
759
760 AST_TEST_REGISTER(ast_sockaddr_to_pj_sockaddr_test);
761 AST_TEST_REGISTER(ast_sockaddr_from_pj_sockaddr_test);
762
764}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
@ OPT_NOOP_T
Type for a default handler that should do nothing.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
#define LOG_NOTICE
#define LOG_WARNING
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define AST_PJPROJECT_INIT_LOG_LEVEL()
Get maximum log level pjproject was compiled with.
Definition: options.h:167
static pj_log_func * log_cb_orig
static unsigned decor_orig
static void * mapping_alloc(const char *name)
static void capture_buildopts_cb(int level, const char *data, int len)
static struct ast_cli_entry pjproject_cli[]
static void log_forwarder(int level, const char *data, int len)
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
Definition: sorcery.h:1500
void ast_sorcery_load(const struct ast_sorcery *sorcery)
Inform any wizards to load persistent objects.
Definition: sorcery.c:1377
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
Definition: sorcery.h:837
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object.
Definition: sorcery.h:955
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition: sorcery.c:1744
#define ast_sorcery_apply_default(sorcery, type, name, data)
Definition: sorcery.h:476
#define ast_sorcery_open()
Open a new sorcery structure.
Definition: sorcery.h:406
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ARRAY_LEN(a)
Definition: utils.h:666
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

References ARRAY_LEN, ast_cli_register_multiple, ast_debug, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_option_pjproject_log_level, AST_PJPROJECT_INIT_LOG_LEVEL, ast_pjproject_max_log_level, ast_sorcery_alloc(), ast_sorcery_apply_default, ast_sorcery_load(), ast_sorcery_object_field_register, ast_sorcery_object_register, ast_sorcery_open, ast_sorcery_unref, ast_string_field_set, AST_TEST_REGISTER, AST_VECTOR_INIT, AST_VECTOR_SIZE, capture_buildopts_cb(), decor_orig, default_log_mappings, log_cb_orig, LOG_ERROR, log_forwarder(), LOG_NOTICE, LOG_WARNING, mapping_alloc(), MAX_PJ_LOG_MAX_LEVEL, NULL, OPT_NOOP_T, OPT_STRINGFIELD_T, pjproject_cli, pjproject_sorcery, and STRFLDSET.

◆ log_forwarder()

static void log_forwarder ( int  level,
const char *  data,
int  len 
)
static

Definition at line 211 of file res_pjproject.c.

212{
213 int ast_level;
214 /* PJPROJECT doesn't provide much in the way of source info */
215 const char * log_source = "pjproject";
216 int log_line = 0;
217 const char *log_func = "<?>";
218
220 && pjproject_log_intercept.thread == pthread_self()) {
221 /*
222 * We are handling a CLI command intercepting PJPROJECT
223 * log output.
224 */
225 ast_cli(pjproject_log_intercept.fd, "%s\n", data);
226 return;
227 }
228
229 ast_level = get_log_level(level);
230
231 if (ast_level == __LOG_SUPPRESS) {
232 return;
233 }
234
235 /* PJPROJECT uses indention to indicate function call depth. We'll prepend
236 * log statements with a tab so they'll have a better shot at lining
237 * up */
238 ast_log(ast_level, log_source, log_line, log_func, "\t%s\n", data);
239}
static int get_log_level(int pj_level)

References __LOG_SUPPRESS, ast_cli(), ast_log, pjproject_log_intercept_data::fd, get_log_level(), pjproject_log_intercept, and pjproject_log_intercept_data::thread.

Referenced by load_module().

◆ mapping_alloc()

static void * mapping_alloc ( const char *  name)
static

Definition at line 328 of file res_pjproject.c.

329{
331 if (!mappings) {
332 return NULL;
333 }
335
336 return mappings;
337}
static void mapping_destroy(void *object)
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359

References ast_sorcery_generic_alloc(), ast_string_field_init, mapping_destroy(), mappings, and NULL.

Referenced by load_module().

◆ mapping_destroy()

static void mapping_destroy ( void *  object)
static

Definition at line 321 of file res_pjproject.c.

322{
323 struct log_mappings *mappings = object;
324
326}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

References ast_string_field_free_memory.

Referenced by mapping_alloc().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 792 of file res_pjproject.c.

793{
794 if (pjproject_sorcery) {
796 }
797
799}
void ast_sorcery_reload(const struct ast_sorcery *sorcery)
Inform any wizards to reload persistent objects.
Definition: sorcery.c:1408

References AST_MODULE_LOAD_SUCCESS, ast_sorcery_reload(), and pjproject_sorcery.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 768 of file res_pjproject.c.

769{
771 pj_log_set_log_func(log_cb_orig);
772 pj_log_set_decor(decor_orig);
773
776
777 ast_debug(3, "Stopped PJPROJECT logging to Asterisk logger\n");
778
779 pj_shutdown();
780
783
785
786 AST_TEST_UNREGISTER(ast_sockaddr_to_pj_sockaddr_test);
787 AST_TEST_UNREGISTER(ast_sockaddr_from_pj_sockaddr_test);
788
789 return 0;
790}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:862

References ao2_cleanup, ARRAY_LEN, ast_cli_unregister_multiple(), ast_debug, ast_free, ast_sorcery_unref, AST_TEST_UNREGISTER, AST_VECTOR_CALLBACK_VOID, AST_VECTOR_FREE, decor_orig, default_log_mappings, log_cb_orig, NULL, pjproject_cli, and pjproject_sorcery.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PJPROJECT Log and Utility Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND - 6, .requires = "res_sorcery_config", }
static

Definition at line 808 of file res_pjproject.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 808 of file res_pjproject.c.

◆ buildopts

struct buildopts buildopts
static

◆ decor_orig

unsigned decor_orig
static

Definition at line 125 of file res_pjproject.c.

Referenced by load_module(), and unload_module().

◆ default_log_mappings

struct log_mappings* default_log_mappings
static

Definition at line 162 of file res_pjproject.c.

Referenced by get_log_mappings(), load_module(), and unload_module().

◆ log_cb_orig

pj_log_func* log_cb_orig
static

Definition at line 124 of file res_pjproject.c.

Referenced by load_module(), and unload_module().

◆ pjproject_cli

struct ast_cli_entry pjproject_cli[]
static

Definition at line 470 of file res_pjproject.c.

Referenced by load_module(), and unload_module().

◆ pjproject_log_intercept

struct pjproject_log_intercept_data pjproject_log_intercept
static
Initial value:
= {
.thread = AST_PTHREADT_NULL,
.fd = -1,
}

Definition at line 137 of file res_pjproject.c.

Referenced by ast_pjproject_log_intercept_begin(), ast_pjproject_log_intercept_end(), and log_forwarder().

◆ pjproject_log_intercept_lock

ast_mutex_t pjproject_log_intercept_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Protection from other log intercept instances. There can be only one at a time.

Definition at line 130 of file res_pjproject.c.

Referenced by ast_pjproject_log_intercept_begin(), and ast_pjproject_log_intercept_end().

◆ pjproject_sorcery

struct ast_sorcery* pjproject_sorcery
static