@ -19,7 +19,7 @@
/*** MODULEINFO
< depend > pjproject < / depend >
< depend > res_pjsip < / depend >
< defaultenabled > no < / defaultenabled >
< defaultenabled > yes < / defaultenabled >
< support_level > core < / support_level >
* * */
@ -30,9 +30,79 @@
# include "asterisk/res_pjsip.h"
# include "asterisk/module.h"
# include "asterisk/logger.h"
# include "asterisk/cli.h"
# include "asterisk/netsock2.h"
enum pjsip_logging_mode {
LOGGING_MODE_DISABLED , /* No logging is enabled */
LOGGING_MODE_ENABLED , /* Logging is enabled */
} ;
static enum pjsip_logging_mode logging_mode ;
static struct ast_sockaddr log_addr ;
/*! \brief Return the first entry from ast_sockaddr_resolve filtered by address family
*
* \ warning Using this function probably means you have a faulty design .
* \ note This function was taken from the function of the same name in chan_sip . c
*/
static int ast_sockaddr_resolve_first_af ( struct ast_sockaddr * addr ,
const char * name , int flag , int family )
{
struct ast_sockaddr * addrs ;
int addrs_cnt ;
addrs_cnt = ast_sockaddr_resolve ( & addrs , name , flag , family ) ;
if ( addrs_cnt < = 0 ) {
return 1 ;
}
if ( addrs_cnt > 1 ) {
ast_debug ( 1 , " Multiple addresses, using the first one only \n " ) ;
}
ast_sockaddr_copy ( addr , & addrs [ 0 ] ) ;
ast_free ( addrs ) ;
return 0 ;
}
/*! \brief See if we pass debug IP filter */
static inline int pjsip_log_test_addr ( const char * address , int port )
{
struct ast_sockaddr test_addr ;
if ( logging_mode = = LOGGING_MODE_DISABLED ) {
return 0 ;
}
/* A null logging address means we'll debug any address */
if ( ast_sockaddr_isnull ( & log_addr ) ) {
return 1 ;
}
/* A null address was passed in. Just reject it. */
if ( ast_strlen_zero ( address ) ) {
return 0 ;
}
ast_sockaddr_parse ( & test_addr , address , PARSE_PORT_IGNORE ) ;
ast_sockaddr_set_port ( & test_addr , port ) ;
/* If no port was specified for a debug address, just compare the
* addresses , otherwise compare the address and port
*/
if ( ast_sockaddr_port ( & log_addr ) ) {
return ! ast_sockaddr_cmp ( & log_addr , & test_addr ) ;
} else {
return ! ast_sockaddr_cmp_addr ( & log_addr , & test_addr ) ;
}
}
static pj_status_t logging_on_tx_msg ( pjsip_tx_data * tdata )
{
if ( ! pjsip_log_test_addr ( tdata - > tp_info . dst_name , tdata - > tp_info . dst_port ) ) {
return PJ_SUCCESS ;
}
ast_verbose ( " <--- Transmitting SIP %s (%d bytes) to %s:%s:%d ---> \n %.*s \n " ,
tdata - > msg - > type = = PJSIP_REQUEST_MSG ? " request " : " response " ,
( int ) ( tdata - > buf . cur - tdata - > buf . start ) ,
@ -45,6 +115,10 @@ static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
static pj_bool_t logging_on_rx_msg ( pjsip_rx_data * rdata )
{
if ( ! pjsip_log_test_addr ( rdata - > pkt_info . src_name , rdata - > pkt_info . src_port ) ) {
return PJ_FALSE ;
}
ast_verbose ( " <--- Received SIP %s (%d bytes) from %s:%s:%d ---> \n %s \n " ,
rdata - > msg_info . msg - > type = = PJSIP_REQUEST_MSG ? " request " : " response " ,
rdata - > msg_info . len ,
@ -64,14 +138,71 @@ static pjsip_module logging_module = {
. on_tx_response = logging_on_tx_msg ,
} ;
static char * pjsip_enable_logger_host ( int fd , const char * arg )
{
if ( ast_sockaddr_resolve_first_af ( & log_addr , arg , 0 , AST_AF_UNSPEC ) ) {
return CLI_SHOWUSAGE ;
}
ast_cli ( fd , " PJSIP Logging Enabled for host: %s \n " , ast_sockaddr_stringify_addr ( & log_addr ) ) ;
logging_mode = LOGGING_MODE_ENABLED ;
return CLI_SUCCESS ;
}
static char * pjsip_set_logger ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
{
const char * what ;
if ( cmd = = CLI_INIT ) {
e - > command = " pjsip set logger {on|off|host} " ;
e - > usage =
" Usage: pjsip set logger {on|off} \n "
" Enables or disabling logging of SIP packets \n "
" read on ports bound to PJSIP transports either \n "
" globally or enables logging for an individual \n "
" host. \n " ;
return NULL ;
} else if ( cmd = = CLI_GENERATE ) {
return NULL ;
}
what = a - > argv [ e - > args - 1 ] ; /* Guaranteed to exist */
if ( a - > argc = = e - > args ) { /* on/off */
if ( ! strcasecmp ( what , " on " ) ) {
logging_mode = LOGGING_MODE_ENABLED ;
ast_cli ( a - > fd , " PJSIP Logging enabled \n " ) ;
ast_sockaddr_setnull ( & log_addr ) ;
return CLI_SUCCESS ;
} else if ( ! strcasecmp ( what , " off " ) ) {
logging_mode = LOGGING_MODE_DISABLED ;
ast_cli ( a - > fd , " PJSIP Logging disabled \n " ) ;
return CLI_SUCCESS ;
}
} else if ( a - > argc = = e - > args + 1 ) {
if ( ! strcasecmp ( what , " host " ) ) {
return pjsip_enable_logger_host ( a - > fd , a - > argv [ e - > args ] ) ;
}
}
return CLI_SHOWUSAGE ;
}
static struct ast_cli_entry cli_pjsip [ ] = {
AST_CLI_DEFINE ( pjsip_set_logger , " Enable/Disable PJSIP Logger Output " )
} ;
static int load_module ( void )
{
ast_sip_register_service ( & logging_module ) ;
ast_cli_register_multiple ( cli_pjsip , ARRAY_LEN ( cli_pjsip ) ) ;
return AST_MODULE_LOAD_SUCCESS ;
}
static int unload_module ( void )
{
ast_cli_unregister_multiple ( cli_pjsip , ARRAY_LEN ( cli_pjsip ) ) ;
ast_sip_unregister_service ( & logging_module ) ;
return 0 ;
}