Asterisk - The Open Source Telephony Project  21.4.1
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"

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 = "da6642af068ee5e6490c5b1d2cc1d238" , .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.

Function Documentation

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.

Referenced by rtp_reload().

485 {
486  pj_caching_pool_destroy(cp);
487 }
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.

References ast_option_pjproject_cache_pools.

Referenced by rtp_reload().

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
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:

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

Definition at line 256 of file res_pjproject.c.

References ast_alloca, AST_VECTOR_GET, and AST_VECTOR_SIZE.

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_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
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.

References pjproject_log_intercept_lock.

280 {
281  /* Protect from other CLI instances trying to do this at the same time. */
282  ast_mutex_lock(&pjproject_log_intercept_lock);
283 
284  pjproject_log_intercept.thread = pthread_self();
285  pjproject_log_intercept.fd = fd;
286 }
static ast_mutex_t pjproject_log_intercept_lock
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.

References pjproject_log_intercept_lock.

289 {
290  pjproject_log_intercept.fd = -1;
291  pjproject_log_intercept.thread = AST_PTHREADT_NULL;
292 
293  ast_mutex_unlock(&pjproject_log_intercept_lock);
294 }
static ast_mutex_t pjproject_log_intercept_lock
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.

Referenced by ast_sockaddr_pj_sockaddr_cmp().

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 }
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.

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

Referenced by __rtp_recvfrom().

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 }
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
Socket address structure.
Definition: netsock2.h:97
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#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_from_pj_sockaddr(struct ast_sockaddr *addr, const pj_sockaddr *pjaddr)
Fill an ast_sockaddr from a 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.

Referenced by rtp_add_candidates_to_ice().

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 }

Variable Documentation

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.

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().