@ -217,6 +217,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
< parameter name = " Variables " >
< parameter name = " Variables " >
< para > Comma < literal > , < / literal > separated list of variable to include . < / para >
< para > Comma < literal > , < / literal > separated list of variable to include . < / para >
< / parameter >
< / parameter >
< parameter name = " AllVariables " >
< para > If set to " true " , the Status event will include all channel variables for
the requested channel ( s ) . < / para >
< enumlist >
< enum name = " true " / >
< enum name = " false " / >
< / enumlist >
< / parameter >
< / syntax >
< / syntax >
< description >
< description >
< para > Will return the status information of each channel along with the
< para > Will return the status information of each channel along with the
@ -3929,115 +3937,78 @@ static int action_getvar(struct mansession *s, const struct message *m)
return 0 ;
return 0 ;
}
}
/*! \brief Manager "status" command to show channels */
static void generate_status ( struct mansession * s , struct ast_channel * chan , char * * vars , int varc , int all_variables , char * id_text )
/* Needs documentation... */
static int action_status ( struct mansession * s , const struct message * m )
{
{
const char * name = astman_get_header ( m , " Channel " ) ;
struct timeval now ;
const char * chan_variables = astman_get_header ( m , " Variables " ) ;
long elapsed_seconds ;
const char * id = astman_get_header ( m , " ActionID " ) ;
struct ast_bridge * bridge ;
char * variables = ast_strdupa ( S_OR ( chan_variables , " " ) ) ;
RAII_VAR ( struct ast_str * , variable_str , NULL , ast_free ) ;
struct ast_str * variable_str = ast_str_create ( 1024 ) ;
struct ast_str * write_transpath = ast_str_alloca ( 256 ) ;
struct ast_str * write_transpath = ast_str_alloca ( 256 ) ;
struct ast_str * read_transpath = ast_str_alloca ( 256 ) ;
struct ast_str * read_transpath = ast_str_alloca ( 256 ) ;
struct ast_channel * chan ;
struct ast_str * codec_buf = ast_str_alloca ( 128 ) ;
struct ast_str * codec_buf = ast_str_alloca ( 64 ) ;
struct ast_party_id effective_id ;
int channels = 0 ;
int i ;
int all = ast_strlen_zero ( name ) ; /* set if we want all channels */
RAII_VAR ( struct ast_channel_snapshot * , snapshot ,
char id_text [ 256 ] ;
ast_channel_snapshot_get_latest ( ast_channel_uniqueid ( chan ) ) ,
struct ast_channel_iterator * it_chans = NULL ;
ao2_cleanup ) ;
AST_DECLARE_APP_ARGS ( vars ,
RAII_VAR ( struct ast_str * , snapshot_str , NULL , ast_free ) ;
AST_APP_ARG ( name ) [ 100 ] ;
) ;
if ( ! variable_str ) {
astman_send_error ( s , m , " Memory Allocation Failure " ) ;
return 1 ;
}
if ( ! ( function_capable_string_allowed_with_auths ( variables , s - > session - > writeperm ) ) ) {
if ( ! snapshot ) {
ast_free ( variable_str ) ;
return ;
astman_send_error ( s , m , " Status Access Forbidden: Variables " ) ;
return 0 ;
}
}
if ( all ) {
snapshot_str = ast_manager_build_channel_state_string ( snapshot ) ;
if ( ! ( it_chans = ast_channel_iterator_all_new ( ) ) ) {
if ( ! snapshot_str ) {
ast_free ( variable_str ) ;
return ;
astman_send_error ( s , m , " Memory Allocation Failure " ) ;
return 1 ;
}
chan = ast_channel_iterator_next ( it_chans ) ;
} else {
chan = ast_channel_get_by_name ( name ) ;
if ( ! chan ) {
astman_send_error ( s , m , " No such channel " ) ;
ast_free ( variable_str ) ;
return 0 ;
}
}
}
astman_send_ack ( s , m , " Channel status will follow " ) ;
if ( all_variables ) {
variable_str = ast_str_create ( 2048 ) ;
if ( ! ast_strlen_zero ( id ) ) {
snprintf ( id_text , sizeof ( id_text ) , " ActionID: %s \r \n " , id ) ;
} else {
} else {
id_text[ 0 ] = ' \0 ' ;
variable_str = ast_str_create ( 1024 ) ;
}
}
if ( ! ast_strlen_zero ( chan_variables ) ) {
if ( ! variable_str ) {
AST_STANDARD_APP_ARGS ( vars , variables ) ;
return ;
}
}
/* if we look by name, we break after the first iteration */
for ( ; chan ; all ? chan = ast_channel_iterator_next ( it_chans ) : 0 ) {
struct timeval now ;
long elapsed_seconds ;
struct ast_bridge * bridge ;
ast_channel_lock ( chan ) ;
now = ast_tvnow ( ) ;
now = ast_tvnow ( ) ;
elapsed_seconds = ast_tvdiff_sec ( now , ast_channel_creationtime ( chan ) ) ;
elapsed_seconds = ast_tvdiff_sec ( now , ast_channel_creationtime ( chan ) ) ;
if ( ! ast_strlen_zero ( chan_variables ) ) {
/* Even if all_variables has been specified, explicitly requested variables
int i ;
* may be global variables or dialplan functions */
ast_str_reset ( variable_str ) ;
for ( i = 0 ; i < varc ; i + + ) {
for ( i = 0 ; i < vars . argc ; i + + ) {
char valbuf [ 512 ] , * ret = NULL ;
char valbuf [ 512 ] , * ret = NULL ;
if ( vars .name [i ] [ strlen ( vars . name [ i ] ) - 1 ] = = ' ) ' ) {
if ( vars [i ] [ strlen ( vars [ i ] ) - 1 ] = = ' ) ' ) {
if ( ast_func_read ( chan , vars . name [ i ] , valbuf , sizeof ( valbuf ) ) < 0 ) {
if ( ast_func_read ( chan , vars [ i ] , valbuf , sizeof ( valbuf ) ) < 0 ) {
valbuf [ 0 ] = ' \0 ' ;
valbuf [ 0 ] = ' \0 ' ;
}
}
ret = valbuf ;
ret = valbuf ;
} else {
} else {
pbx_retrieve_variable ( chan , vars . name [ i ] , & ret , valbuf , sizeof ( valbuf ) , NULL ) ;
pbx_retrieve_variable ( chan , vars [ i ] , & ret , valbuf , sizeof ( valbuf ) , NULL ) ;
}
}
ast_str_append ( & variable_str , 0 , " Variable: %s=%s \r \n " , vars . name [ i ] , ret ) ;
ast_str_append ( & variable_str , 0 , " Variable: %s=%s \r \n " , vars [ i ] , ret ) ;
}
}
}
channels + + ;
/* Walk all channel variables and add them */
if ( all_variables ) {
struct ast_var_t * variables ;
AST_LIST_TRAVERSE ( ast_channel_varshead ( chan ) , variables , entries ) {
ast_str_append ( & variable_str , 0 , " Variable: %s=%s \r \n " ,
ast_var_name ( variables ) , ast_var_value ( variables ) ) ;
}
}
bridge = ast_channel_get_bridge ( chan ) ;
bridge = ast_channel_get_bridge ( chan ) ;
effective_id = ast_channel_connected_effective_id ( chan ) ;
astman_append ( s ,
astman_append ( s ,
" Event: Status \r \n "
" Event: Status \r \n "
" Privilege: Call \r \n "
" Privilege: Call \r \n "
" Channel: %s \r \n "
" %s "
" ChannelState: %u \r \n "
" ChannelStateDesc: %s \r \n "
" CallerIDNum: %s \r \n "
" CallerIDName: %s \r \n "
" ConnectedLineNum: %s \r \n "
" ConnectedLineName: %s \r \n "
" Accountcode: %s \r \n "
" Context: %s \r \n "
" Exten: %s \r \n "
" Priority: %d \r \n "
" Uniqueid: %s \r \n "
" Type: %s \r \n "
" Type: %s \r \n "
" DNID: %s \r \n "
" DNID: %s \r \n "
" EffectiveConnectedLineNum: %s \r \n "
" EffectiveConnectedLineNum: %s \r \n "
@ -4058,22 +4029,11 @@ static int action_status(struct mansession *s, const struct message *m)
" %s "
" %s "
" %s "
" %s "
" \r \n " ,
" \r \n " ,
ast_channel_name ( chan ) ,
ast_str_buffer ( snapshot_str ) ,
ast_channel_state ( chan ) ,
ast_state2str ( ast_channel_state ( chan ) ) ,
S_COR ( ast_channel_caller ( chan ) - > id . number . valid , ast_channel_caller ( chan ) - > id . number . str , " <unknown> " ) ,
S_COR ( ast_channel_caller ( chan ) - > id . name . valid , ast_channel_caller ( chan ) - > id . name . str , " <unknown> " ) ,
S_COR ( ast_channel_connected ( chan ) - > id . number . valid , ast_channel_connected ( chan ) - > id . number . str , " <unknown> " ) ,
S_COR ( ast_channel_connected ( chan ) - > id . name . valid , ast_channel_connected ( chan ) - > id . name . str , " <unknown> " ) ,
ast_channel_accountcode ( chan ) ,
ast_channel_context ( chan ) ,
ast_channel_exten ( chan ) ,
ast_channel_priority ( chan ) ,
ast_channel_uniqueid ( chan ) ,
ast_channel_tech ( chan ) - > type ,
ast_channel_tech ( chan ) - > type ,
S_OR ( ast_channel_dialed ( chan ) - > number . str , " " ) ,
S_OR ( ast_channel_dialed ( chan ) - > number . str , " " ) ,
S_COR ( ast_channel_connected_effective_id ( chan ) . number . valid , ast_channel_connected_effective_id ( chan ) . number . str , " <unknown> " ) ,
S_COR ( effective_id . number . valid , effective_id . number . str , " <unknown> " ) ,
S_COR ( ast_channel_connected_effective_id ( chan ) . name . valid , ast_channel_connected_effective_id ( chan ) . name . str , " <unknown> " ) ,
S_COR ( effective_id . name . valid , effective_id . name . str , " <unknown> " ) ,
ast_channel_whentohangup ( chan ) - > tv_sec ,
ast_channel_whentohangup ( chan ) - > tv_sec ,
bridge ? bridge - > uniqueid : " " ,
bridge ? bridge - > uniqueid : " " ,
ast_channel_linkedid ( chan ) ,
ast_channel_linkedid ( chan ) ,
@ -4091,6 +4051,67 @@ static int action_status(struct mansession *s, const struct message *m)
id_text ) ;
id_text ) ;
ao2_cleanup ( bridge ) ;
ao2_cleanup ( bridge ) ;
}
/*! \brief Manager "status" command to show channels */
static int action_status ( struct mansession * s , const struct message * m )
{
const char * name = astman_get_header ( m , " Channel " ) ;
const char * chan_variables = astman_get_header ( m , " Variables " ) ;
const char * all_chan_variables = astman_get_header ( m , " AllVariables " ) ;
int all_variables = 0 ;
const char * id = astman_get_header ( m , " ActionID " ) ;
char * variables = ast_strdupa ( S_OR ( chan_variables , " " ) ) ;
struct ast_channel * chan ;
int channels = 0 ;
int all = ast_strlen_zero ( name ) ; /* set if we want all channels */
char id_text [ 256 ] ;
struct ast_channel_iterator * it_chans = NULL ;
AST_DECLARE_APP_ARGS ( vars ,
AST_APP_ARG ( name ) [ 100 ] ;
) ;
if ( ! ast_strlen_zero ( all_chan_variables ) ) {
all_variables = ast_true ( all_chan_variables ) ;
}
if ( ! ( function_capable_string_allowed_with_auths ( variables , s - > session - > writeperm ) ) ) {
astman_send_error ( s , m , " Status Access Forbidden: Variables " ) ;
return 0 ;
}
if ( all ) {
if ( ! ( it_chans = ast_channel_iterator_all_new ( ) ) ) {
astman_send_error ( s , m , " Memory Allocation Failure " ) ;
return 1 ;
}
chan = ast_channel_iterator_next ( it_chans ) ;
} else {
chan = ast_channel_get_by_name ( name ) ;
if ( ! chan ) {
astman_send_error ( s , m , " No such channel " ) ;
return 0 ;
}
}
astman_send_ack ( s , m , " Channel status will follow " ) ;
if ( ! ast_strlen_zero ( id ) ) {
snprintf ( id_text , sizeof ( id_text ) , " ActionID: %s \r \n " , id ) ;
} else {
id_text [ 0 ] = ' \0 ' ;
}
if ( ! ast_strlen_zero ( chan_variables ) ) {
AST_STANDARD_APP_ARGS ( vars , variables ) ;
}
/* if we look by name, we break after the first iteration */
for ( ; chan ; all ? chan = ast_channel_iterator_next ( it_chans ) : 0 ) {
ast_channel_lock ( chan ) ;
generate_status ( s , chan , vars . name , vars . argc , all_variables , id_text ) ;
channels + + ;
ast_channel_unlock ( chan ) ;
ast_channel_unlock ( chan ) ;
chan = ast_channel_unref ( chan ) ;
chan = ast_channel_unref ( chan ) ;
@ -4106,8 +4127,6 @@ static int action_status(struct mansession *s, const struct message *m)
" Items: %d \r \n "
" Items: %d \r \n "
" \r \n " , id_text , channels ) ;
" \r \n " , id_text , channels ) ;
ast_free ( variable_str ) ;
return 0 ;
return 0 ;
}
}