@ -25,20 +25,20 @@
# include "asterisk/callerid.h"
# include "asterisk/callerid.h"
# include "asterisk/causes.h"
# include "asterisk/causes.h"
# include "asterisk/options.h"
# include "asterisk/options.h"
# include "asterisk/linkedlists.h"
# include "asterisk/utils.h"
# include "asterisk/utils.h"
int ast_default_amaflags = AST_CDR_DOCUMENTATION ;
int ast_default_amaflags = AST_CDR_DOCUMENTATION ;
char ast_default_accountcode [ 20 ] = " " ;
char ast_default_accountcode [ 20 ] = " " ;
AST_MUTEX_DEFINE_STATIC ( cdrlock ) ;
struct ast_cdr_beitem {
static struct ast_cdr_beitem {
char name [ 20 ] ;
char name [ 20 ] ;
char desc [ 80 ] ;
char desc [ 80 ] ;
ast_cdrbe be ;
ast_cdrbe be ;
struct ast_cdr_beitem * nex t;
AST_LIST_ENTRY ( ast_cdr_beitem ) lis t;
} * bes = NULL ;
} ;
static AST_LIST_HEAD_STATIC ( be_list , ast_cdr_beitem ) ;
/*
/*
* We do a lot of checking here in the CDR code to try to be sure we don ' t ever let a CDR slip
* We do a lot of checking here in the CDR code to try to be sure we don ' t ever let a CDR slip
@ -50,58 +50,58 @@ static struct ast_cdr_beitem {
int ast_cdr_register ( char * name , char * desc , ast_cdrbe be )
int ast_cdr_register ( char * name , char * desc , ast_cdrbe be )
{
{
struct ast_cdr_beitem * i ;
struct ast_cdr_beitem * i ;
if ( ! name )
if ( ! name )
return - 1 ;
return - 1 ;
if ( ! be ) {
if ( ! be ) {
ast_log ( LOG_WARNING , " CDR engine '%s' lacks backend \n " , name ) ;
ast_log ( LOG_WARNING , " CDR engine '%s' lacks backend \n " , name ) ;
return - 1 ;
return - 1 ;
}
}
ast_mutex_lock ( & cdrlock ) ;
i = bes ;
AST_LIST_LOCK ( & be_list ) ;
while ( i ) {
AST_LIST_TRAVERSE ( & be_list , i , list ) {
if ( ! strcasecmp ( name , i - > name ) )
if ( ! strcasecmp ( name , i - > name ) )
break ;
break ;
i = i - > next ;
}
}
ast_mutex_unlock ( & cdrlock ) ;
AST_LIST_UNLOCK ( & be_list ) ;
if ( i ) {
if ( i ) {
ast_log ( LOG_WARNING , " Already have a CDR backend called '%s' \n " , name ) ;
ast_log ( LOG_WARNING , " Already have a CDR backend called '%s' \n " , name ) ;
return - 1 ;
return - 1 ;
}
}
i = malloc ( sizeof ( struct ast_cdr_beitem ) ) ;
i = malloc ( sizeof ( * i ) ) ;
if ( ! i )
if ( ! i )
return - 1 ;
return - 1 ;
memset ( i , 0 , sizeof ( struct ast_cdr_beitem ) ) ;
strncpy ( i - > name , name , sizeof ( i - > name ) - 1 ) ;
memset ( i , 0 , sizeof ( * i ) ) ;
strncpy ( i - > desc , desc , sizeof ( i - > desc ) - 1 ) ;
i - > be = be ;
i - > be = be ;
ast_mutex_lock ( & cdrlock ) ;
ast_copy_string ( i - > name , name , sizeof ( i - > name ) ) ;
i - > next = bes ;
ast_copy_string ( i - > desc , desc , sizeof ( i - > desc ) ) ;
bes = i ;
ast_mutex_unlock ( & cdrlock ) ;
AST_LIST_LOCK ( & be_list ) ;
AST_LIST_INSERT_HEAD ( & be_list , i , list ) ;
AST_LIST_UNLOCK ( & be_list ) ;
return 0 ;
return 0 ;
}
}
void ast_cdr_unregister ( char * name )
void ast_cdr_unregister ( char * name )
{
{
struct ast_cdr_beitem * i , * prev = NULL ;
struct ast_cdr_beitem * i = NULL ;
ast_mutex_lock ( & cdrlock ) ;
i = bes ;
AST_LIST_LOCK ( & be_list ) ;
while ( i ) {
AST_LIST_TRAVERSE_SAFE_BEGIN ( & be_list , i , list ) {
if ( ! strcasecmp ( name , i - > name ) ) {
if ( ! strcasecmp ( name , i - > name ) ) {
if ( prev )
AST_LIST_REMOVE_CURRENT ( & be_list , list ) ;
prev - > next = i - > next ;
if ( option_verbose > 1 )
else
ast_verbose ( VERBOSE_PREFIX_2 " Unregistered '%s' CDR backend \n " , name ) ;
bes = i - > next ;
free ( i ) ;
break ;
break ;
}
}
i = i - > next ;
}
}
if ( option_verbose > 1 )
AST_LIST_TRAVERSE_SAFE_END ;
ast_verbose ( VERBOSE_PREFIX_2 " Unregistered '%s' CDR backend \n " , name ) ;
AST_LIST_UNLOCK ( & be_list ) ;
ast_mutex_unlock ( & cdrlock ) ;
if ( i )
free ( i ) ;
}
}
static const char * ast_cdr_getvar_internal ( struct ast_cdr * cdr , const char * name , int recur )
static const char * ast_cdr_getvar_internal ( struct ast_cdr * cdr , const char * name , int recur )
@ -109,110 +109,97 @@ static const char *ast_cdr_getvar_internal(struct ast_cdr *cdr, const char *name
struct ast_var_t * variables ;
struct ast_var_t * variables ;
struct varshead * headp ;
struct varshead * headp ;
while ( cdr ) {
if ( ! name | | ast_strlen_zero ( name ) )
return NULL ;
while ( cdr ) {
headp = & cdr - > varshead ;
headp = & cdr - > varshead ;
if ( name ) {
AST_LIST_TRAVERSE ( headp , variables , entries ) {
AST_LIST_TRAVERSE ( headp , variables , entries ) {
if ( ! strcasecmp ( name , ast_var_name ( variables ) ) )
if ( ! strcmp ( name , ast_var_name ( variables ) ) )
return ast_var_value ( variables ) ;
return ast_var_value ( variables ) ;
}
}
}
if ( ! recur ) {
if ( ! recur )
break ;
break ;
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
return NULL ;
return NULL ;
}
}
# define ast_val_or_null(val) do { \
if ( val [ 0 ] ) { \
strncpy ( workspace , val , workspacelen - 1 ) ; \
* ret = workspace ; \
} \
} while ( 0 )
void ast_cdr_getvar ( struct ast_cdr * cdr , const char * name , char * * ret , char * workspace , int workspacelen , int recur )
void ast_cdr_getvar ( struct ast_cdr * cdr , const char * name , char * * ret , char * workspace , int workspacelen , int recur )
{
{
struct tm tm ;
struct tm tm ;
time_t t ;
time_t t ;
const char * fmt = " %Y-%m-%d %T " ;
const char * fmt = " %Y-%m-%d %T " ;
const char * varbuf ;
* ret = NULL ;
* ret = NULL ;
/* special vars (the ones from the struct ast_cdr when requested by name)
/* special vars (the ones from the struct ast_cdr when requested by name)
I ' d almost say we should convert all the stringed vals to vars */
I ' d almost say we should convert all the stringed vals to vars */
if ( ! strcasecmp ( name , " clid " ) ) {
if ( ! strcasecmp ( name , " clid " ) )
ast_ val_or_null( cdr - > clid ) ;
ast_ copy_string( workspace , cdr - > clid , workspacelen ) ;
} else if ( ! strcasecmp ( name , " src " ) ) {
else if ( ! strcasecmp ( name , " src " ) )
ast_ val_or_null( cdr - > src ) ;
ast_ copy_string( workspace , cdr - > src , workspacelen ) ;
} else if ( ! strcasecmp ( name , " dst " ) ) {
else if ( ! strcasecmp ( name , " dst " ) )
ast_ val_or_null( cdr - > dst ) ;
ast_ copy_string( workspace , cdr - > dst , workspacelen ) ;
} else if ( ! strcasecmp ( name , " dcontext " ) ) {
else if ( ! strcasecmp ( name , " dcontext " ) )
ast_ val_or_null( cdr - > dcontext ) ;
ast_ copy_string( workspace , cdr - > dcontext , workspacelen ) ;
} else if ( ! strcasecmp ( name , " channel " ) ) {
else if ( ! strcasecmp ( name , " channel " ) )
ast_ val_or_null( cdr - > channel ) ;
ast_ copy_string( workspace , cdr - > channel , workspacelen ) ;
} else if ( ! strcasecmp ( name , " dstchannel " ) ) {
else if ( ! strcasecmp ( name , " dstchannel " ) )
ast_ val_or_null( cdr - > dstchannel ) ;
ast_ copy_string( workspace , cdr - > dstchannel , workspacelen ) ;
} else if ( ! strcasecmp ( name , " lastapp " ) ) {
else if ( ! strcasecmp ( name , " lastapp " ) )
ast_ val_or_null( cdr - > lastapp ) ;
ast_ copy_string( workspace , cdr - > lastapp , workspacelen ) ;
} else if ( ! strcasecmp ( name , " lastdata " ) ) {
else if ( ! strcasecmp ( name , " lastdata " ) )
ast_ val_or_null( cdr - > lastdata ) ;
ast_ copy_string( workspace , cdr - > lastdata , workspacelen ) ;
} else if ( ! strcasecmp ( name , " start " ) ) {
else if ( ! strcasecmp ( name , " start " ) ) {
t = cdr - > start . tv_sec ;
t = cdr - > start . tv_sec ;
if ( t ) {
if ( t ) {
localtime_r ( & t , & tm ) ;
localtime_r ( & t , & tm ) ;
strftime ( workspace , workspacelen , fmt , & tm ) ;
strftime ( workspace , workspacelen , fmt , & tm ) ;
* ret = workspace ;
}
}
} else if ( ! strcasecmp ( name , " answer " ) ) {
} else if ( ! strcasecmp ( name , " answer " ) ) {
t = cdr - > start . tv_sec ;
t = cdr - > start . tv_sec ;
if ( t ) {
if ( t ) {
localtime_r ( & t , & tm ) ;
localtime_r ( & t , & tm ) ;
strftime ( workspace , workspacelen , fmt , & tm ) ;
strftime ( workspace , workspacelen , fmt , & tm ) ;
* ret = workspace ;
}
}
} else if ( ! strcasecmp ( name , " end " ) ) {
} else if ( ! strcasecmp ( name , " end " ) ) {
t = cdr - > start . tv_sec ;
t = cdr - > start . tv_sec ;
if ( t ) {
if ( t ) {
localtime_r ( & t , & tm ) ;
localtime_r ( & t , & tm ) ;
strftime ( workspace , workspacelen , fmt , & tm ) ;
strftime ( workspace , workspacelen , fmt , & tm ) ;
* ret = workspace ;
}
}
} else if ( ! strcasecmp ( name , " duration " ) ) {
} else if ( ! strcasecmp ( name , " duration " ) )
snprintf ( workspace , workspacelen , " %d " , cdr - > duration ) ;
snprintf ( workspace , workspacelen , " %d " , cdr - > duration ) ;
* ret = workspace ;
else if ( ! strcasecmp ( name , " billsec " ) )
} else if ( ! strcasecmp ( name , " billsec " ) ) {
snprintf ( workspace , workspacelen , " %d " , cdr - > billsec ) ;
snprintf ( workspace , workspacelen , " %d " , cdr - > billsec ) ;
else if ( ! strcasecmp ( name , " disposition " ) )
ast_copy_string ( workspace , ast_cdr_disp2str ( cdr - > disposition ) , workspacelen ) ;
else if ( ! strcasecmp ( name , " amaflags " ) )
ast_copy_string ( workspace , ast_cdr_flags2str ( cdr - > amaflags ) , workspacelen ) ;
else if ( ! strcasecmp ( name , " accountcode " ) )
ast_copy_string ( workspace , cdr - > accountcode , workspacelen ) ;
else if ( ! strcasecmp ( name , " uniqueid " ) )
ast_copy_string ( workspace , cdr - > uniqueid , workspacelen ) ;
else if ( ! strcasecmp ( name , " userfield " ) )
ast_copy_string ( workspace , cdr - > userfield , workspacelen ) ;
else if ( ( varbuf = ast_cdr_getvar_internal ( cdr , name , recur ) ) )
ast_copy_string ( workspace , varbuf , workspacelen ) ;
if ( ! ast_strlen_zero ( workspace ) )
* ret = workspace ;
* ret = workspace ;
} else if ( ! strcasecmp ( name , " disposition " ) ) {
strncpy ( workspace , ast_cdr_disp2str ( cdr - > disposition ) , workspacelen - 1 ) ;
* ret = workspace ;
} else if ( ! strcasecmp ( name , " amaflags " ) ) {
strncpy ( workspace , ast_cdr_flags2str ( cdr - > amaflags ) , workspacelen - 1 ) ;
* ret = workspace ;
} else if ( ! strcasecmp ( name , " accountcode " ) ) {
ast_val_or_null ( cdr - > accountcode ) ;
} else if ( ! strcasecmp ( name , " uniqueid " ) ) {
ast_val_or_null ( cdr - > uniqueid ) ;
} else if ( ! strcasecmp ( name , " userfield " ) ) {
ast_val_or_null ( cdr - > userfield ) ;
} else {
if ( ( * ret = ( char * ) ast_cdr_getvar_internal ( cdr , name , recur ) ) ) {
strncpy ( workspace , * ret , workspacelen - 1 ) ;
* ret = workspace ;
}
}
}
}
int ast_cdr_setvar ( struct ast_cdr * cdr , const char * name , const char * value , int recur )
int ast_cdr_setvar ( struct ast_cdr * cdr , const char * name , const char * value , int recur )
{
{
struct ast_var_t * newvariable ;
struct ast_var_t * newvariable ;
struct varshead * headp ;
struct varshead * headp ;
const char * read_only [ ] = { " clid " , " src " , " dst " , " dcontext " , " channel " , " dstchannel " ,
const char * read_only [ ] = { " clid " , " src " , " dst " , " dcontext " , " channel " , " dstchannel " ,
" lastapp " , " lastdata " , " start " , " answer " , " end " , " duration " ,
" lastapp " , " lastdata " , " start " , " answer " , " end " , " duration " ,
" billsec " , " disposition " , " amaflags " , " accountcode " , " uniqueid " ,
" billsec " , " disposition " , " amaflags " , " accountcode " , " uniqueid " ,
" userfield " , NULL } ;
" userfield " , NULL } ;
int x ;
int x ;
for ( x = 0 ; read_only [ x ] ; x + + ) {
for ( x = 0 ; read_only [ x ] ; x + + ) {
@ -222,20 +209,22 @@ int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int
}
}
}
}
if ( ! cdr ) {
if ( ! cdr ) {
ast_log ( LOG_ERROR , " Attempt to set a variable on a nonexistent CDR record. \n " ) ;
ast_log ( LOG_ERROR , " Attempt to set a variable on a nonexistent CDR record. \n " ) ;
return - 1 ;
return - 1 ;
}
}
while ( cdr ) {
while ( cdr ) {
headp = & cdr - > varshead ;
headp = & cdr - > varshead ;
AST_LIST_TRAVERSE ( headp , newvariable , entries ) {
AST_LIST_TRAVERSE _SAFE_BEGIN ( headp , newvariable , entries ) {
if ( strcasecmp ( ast_var_name ( newvariable ) , name ) = = 0 ) {
if ( ! strcasecmp ( ast_var_name ( newvariable ) , name ) ) {
/* there is already such a variable, delete it */
/* there is already such a variable, delete it */
AST_LIST_REMOVE ( headp , newvariable , entries ) ;
AST_LIST_REMOVE _CURRENT ( headp , entries ) ;
ast_var_delete ( newvariable ) ;
ast_var_delete ( newvariable ) ;
break ;
break ;
}
}
}
}
AST_LIST_TRAVERSE_SAFE_END ;
if ( value ) {
if ( value ) {
newvariable = ast_var_assign ( name , value ) ;
newvariable = ast_var_assign ( name , value ) ;
@ -245,23 +234,27 @@ int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int
if ( ! recur ) {
if ( ! recur ) {
break ;
break ;
}
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
return 0 ;
return 0 ;
}
}
int ast_cdr_copy_vars ( struct ast_cdr * to_cdr , struct ast_cdr * from_cdr )
int ast_cdr_copy_vars ( struct ast_cdr * to_cdr , struct ast_cdr * from_cdr )
{
{
struct ast_var_t * variables , * newvariable = NULL ;
struct ast_var_t * variables , * newvariable = NULL ;
struct varshead * headpa , * headpb ;
struct varshead * headpa , * headpb ;
char * var , * val ;
char * var , * val ;
int x = 0 ;
int x = 0 ;
headpa = & from_cdr - > varshead ;
headpa = & from_cdr - > varshead ;
headpb = & to_cdr - > varshead ;
headpb = & to_cdr - > varshead ;
AST_LIST_TRAVERSE ( headpa , variables , entries ) {
AST_LIST_TRAVERSE ( headpa , variables , entries ) {
if ( variables & & ( var = ast_var_name ( variables ) ) & & ( val = ast_var_value ( variables ) ) & & ! ast_strlen_zero ( var ) & & ! ast_strlen_zero ( val ) ) {
if ( variables & &
( var = ast_var_name ( variables ) ) & & ( val = ast_var_value ( variables ) ) & &
! ast_strlen_zero ( var ) & & ! ast_strlen_zero ( val ) ) {
newvariable = ast_var_assign ( var , val ) ;
newvariable = ast_var_assign ( var , val ) ;
AST_LIST_INSERT_HEAD ( headpb , newvariable , entries ) ;
AST_LIST_INSERT_HEAD ( headpb , newvariable , entries ) ;
x + + ;
x + + ;
@ -309,9 +302,11 @@ int ast_cdr_serialize_variables(struct ast_cdr *cdr, char *buf, size_t size, cha
if ( x > 1 ) {
if ( x > 1 ) {
strncat ( buf , " \n " , size ) ;
strncat ( buf , " \n " , size ) ;
}
}
headp = & cdr - > varshead ;
headp = & cdr - > varshead ;
AST_LIST_TRAVERSE ( headp , variables , entries ) {
AST_LIST_TRAVERSE ( headp , variables , entries ) {
if ( cdr & & variables & & ( var = ast_var_name ( variables ) ) & & ( val = ast_var_value ( variables ) ) & & ! ast_strlen_zero ( var ) & & ! ast_strlen_zero ( val ) ) {
if ( cdr & & variables & &
( var = ast_var_name ( variables ) ) & & ( val = ast_var_value ( variables ) ) & &
! ast_strlen_zero ( var ) & & ! ast_strlen_zero ( val ) ) {
snprintf ( buf + strlen ( buf ) , size - strlen ( buf ) , " level %d: %s%c%s%c " , x , var , delim , val , sep ) ;
snprintf ( buf + strlen ( buf ) , size - strlen ( buf ) , " level %d: %s%c%s%c " , x , var , delim , val , sep ) ;
if ( strlen ( buf ) > = size ) {
if ( strlen ( buf ) > = size ) {
ast_log ( LOG_ERROR , " Data Buffer Size Exceeded! \n " ) ;
ast_log ( LOG_ERROR , " Data Buffer Size Exceeded! \n " ) ;
@ -338,8 +333,10 @@ int ast_cdr_serialize_variables(struct ast_cdr *cdr, char *buf, size_t size, cha
if ( ! recur ) {
if ( ! recur ) {
break ;
break ;
}
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
return total ;
return total ;
}
}
@ -350,15 +347,17 @@ void ast_cdr_free_vars(struct ast_cdr *cdr, int recur)
struct ast_var_t * vardata ;
struct ast_var_t * vardata ;
/* clear variables */
/* clear variables */
while ( cdr ) {
while ( cdr ) {
headp = & cdr - > varshead ;
headp = & cdr - > varshead ;
while ( ! AST_LIST_EMPTY ( headp ) ) {
while ( ! AST_LIST_EMPTY ( headp ) ) {
vardata = AST_LIST_REMOVE_HEAD ( headp , entries ) ;
vardata = AST_LIST_REMOVE_HEAD ( headp , entries ) ;
ast_var_delete ( vardata ) ;
ast_var_delete ( vardata ) ;
}
}
if ( ! recur ) {
if ( ! recur ) {
break ;
break ;
}
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
}
}
@ -387,16 +386,18 @@ void ast_cdr_free(struct ast_cdr *cdr)
struct ast_cdr * ast_cdr_alloc ( void )
struct ast_cdr * ast_cdr_alloc ( void )
{
{
struct ast_cdr * cdr ;
struct ast_cdr * cdr ;
cdr = malloc ( sizeof ( struct ast_cdr ) ) ;
if ( cdr ) {
cdr = malloc ( sizeof ( * cdr ) ) ;
memset ( cdr , 0 , sizeof ( struct ast_cdr ) ) ;
if ( cdr )
}
memset ( cdr , 0 , sizeof ( * cdr ) ) ;
return cdr ;
return cdr ;
}
}
void ast_cdr_start ( struct ast_cdr * cdr )
void ast_cdr_start ( struct ast_cdr * cdr )
{
{
char * chan ;
char * chan ;
while ( cdr ) {
while ( cdr ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
@ -406,13 +407,14 @@ void ast_cdr_start(struct ast_cdr *cdr)
ast_log ( LOG_WARNING , " CDR on channel '%s' already started \n " , chan ) ;
ast_log ( LOG_WARNING , " CDR on channel '%s' already started \n " , chan ) ;
gettimeofday ( & cdr - > start , NULL ) ;
gettimeofday ( & cdr - > start , NULL ) ;
}
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
}
}
void ast_cdr_answer ( struct ast_cdr * cdr )
void ast_cdr_answer ( struct ast_cdr * cdr )
{
{
char * chan ;
char * chan ;
while ( cdr ) {
while ( cdr ) {
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
@ -429,6 +431,7 @@ void ast_cdr_answer(struct ast_cdr *cdr)
void ast_cdr_busy ( struct ast_cdr * cdr )
void ast_cdr_busy ( struct ast_cdr * cdr )
{
{
char * chan ;
char * chan ;
while ( cdr ) {
while ( cdr ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
@ -444,6 +447,7 @@ void ast_cdr_busy(struct ast_cdr *cdr)
void ast_cdr_failed ( struct ast_cdr * cdr )
void ast_cdr_failed ( struct ast_cdr * cdr )
{
{
char * chan ;
char * chan ;
while ( cdr ) {
while ( cdr ) {
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
@ -457,22 +461,23 @@ void ast_cdr_failed(struct ast_cdr *cdr)
int ast_cdr_disposition ( struct ast_cdr * cdr , int cause )
int ast_cdr_disposition ( struct ast_cdr * cdr , int cause )
{
{
int res = 0 ;
int res = 0 ;
while ( cdr ) {
while ( cdr ) {
switch ( cause ) {
switch ( cause ) {
case AST_CAUSE_BUSY :
case AST_CAUSE_BUSY :
ast_cdr_busy ( cdr ) ;
ast_cdr_busy ( cdr ) ;
break ;
break ;
case AST_CAUSE_FAILURE :
case AST_CAUSE_FAILURE :
ast_cdr_failed ( cdr ) ;
ast_cdr_failed ( cdr ) ;
break ;
break ;
case AST_CAUSE_NORMAL :
case AST_CAUSE_NORMAL :
break ;
break ;
case AST_CAUSE_NOTDEFINED :
case AST_CAUSE_NOTDEFINED :
res = - 1 ;
res = - 1 ;
break ;
break ;
default :
default :
res = - 1 ;
res = - 1 ;
ast_log ( LOG_WARNING , " Cause not handled \n " ) ;
ast_log ( LOG_WARNING , " Cause not handled \n " ) ;
}
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
@ -482,12 +487,13 @@ int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
void ast_cdr_setdestchan ( struct ast_cdr * cdr , char * chann )
void ast_cdr_setdestchan ( struct ast_cdr * cdr , char * chann )
{
{
char * chan ;
char * chan ;
while ( cdr ) {
while ( cdr ) {
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
ast_log ( LOG_WARNING , " CDR on channel '%s' already posted \n " , chan ) ;
ast_log ( LOG_WARNING , " CDR on channel '%s' already posted \n " , chan ) ;
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) )
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) )
strncpy ( cdr - > dstchannel , chann , sizeof ( cdr - > dstchannel ) - 1 ) ;
ast_copy_string ( cdr - > dstchannel , chann , sizeof ( cdr - > dstchannel ) ) ;
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
}
}
@ -495,6 +501,7 @@ void ast_cdr_setdestchan(struct ast_cdr *cdr, char *chann)
void ast_cdr_setapp ( struct ast_cdr * cdr , char * app , char * data )
void ast_cdr_setapp ( struct ast_cdr * cdr , char * app , char * data )
{
{
char * chan ;
char * chan ;
while ( cdr ) {
while ( cdr ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
@ -502,10 +509,10 @@ void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data)
ast_log ( LOG_WARNING , " CDR on channel '%s' already posted \n " , chan ) ;
ast_log ( LOG_WARNING , " CDR on channel '%s' already posted \n " , chan ) ;
if ( ! app )
if ( ! app )
app = " " ;
app = " " ;
strncpy ( cdr - > lastapp , app , sizeof ( cdr - > lastapp ) - 1 ) ;
ast_copy_string ( cdr - > lastapp , app , sizeof ( cdr - > lastapp ) ) ;
if ( ! data )
if ( ! data )
data = " " ;
data = " " ;
strncpy ( cdr - > lastdata , data , sizeof ( cdr - > lastdata ) - 1 ) ;
ast_copy_string ( cdr - > lastdata , data , sizeof ( cdr - > lastdata ) ) ;
}
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
@ -515,13 +522,11 @@ int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c)
{
{
char tmp [ AST_MAX_EXTENSION ] = " " ;
char tmp [ AST_MAX_EXTENSION ] = " " ;
char * num ;
char * num ;
while ( cdr ) {
while ( cdr ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
/* Grab source from ANI or normal Caller*ID */
/* Grab source from ANI or normal Caller*ID */
if ( c - > cid . cid_ani )
num = c - > cid . cid_ani ? c - > cid . cid_ani : c - > cid . cid_num ;
num = c - > cid . cid_ani ;
else
num = c - > cid . cid_num ;
if ( c - > cid . cid_name & & num )
if ( c - > cid . cid_name & & num )
snprintf ( tmp , sizeof ( tmp ) , " \" %s \" <%s> " , c - > cid . cid_name , num ) ;
snprintf ( tmp , sizeof ( tmp ) , " \" %s \" <%s> " , c - > cid . cid_name , num ) ;
@ -529,16 +534,12 @@ int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c)
strncpy ( tmp , c - > cid . cid_name , sizeof ( tmp ) - 1 ) ;
strncpy ( tmp , c - > cid . cid_name , sizeof ( tmp ) - 1 ) ;
else if ( num )
else if ( num )
strncpy ( tmp , num , sizeof ( tmp ) - 1 ) ;
strncpy ( tmp , num , sizeof ( tmp ) - 1 ) ;
else
ast_copy_string ( cdr - > clid , tmp , sizeof ( cdr - > clid ) ) ;
strcpy ( tmp , " " ) ;
ast_copy_string ( cdr - > src , num ? num : " " , sizeof ( cdr - > src ) ) ;
strncpy ( cdr - > clid , tmp , sizeof ( cdr - > clid ) - 1 ) ;
if ( num )
strncpy ( cdr - > src , num , sizeof ( cdr - > src ) - 1 ) ;
else
strcpy ( cdr - > src , " " ) ;
}
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
return 0 ;
return 0 ;
}
}
@ -548,17 +549,15 @@ int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
char * chan ;
char * chan ;
char * num ;
char * num ;
char tmp [ AST_MAX_EXTENSION ] = " " ;
char tmp [ AST_MAX_EXTENSION ] = " " ;
while ( cdr ) {
while ( cdr ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
if ( ! ast_strlen_zero ( cdr - > channel ) )
if ( ! ast_strlen_zero ( cdr - > channel ) )
ast_log ( LOG_WARNING , " CDR already initialized on '%s' \n " , chan ) ;
ast_log ( LOG_WARNING , " CDR already initialized on '%s' \n " , chan ) ;
strncpy ( cdr - > channel , c - > name , sizeof ( cdr - > channel ) - 1 ) ;
ast_copy_string ( cdr - > channel , c - > name , sizeof ( cdr - > channel ) ) ;
/* Grab source from ANI or normal Caller*ID */
/* Grab source from ANI or normal Caller*ID */
if ( c - > cid . cid_ani )
num = c - > cid . cid_ani ? c - > cid . cid_ani : c - > cid . cid_num ;
num = c - > cid . cid_ani ;
else
num = c - > cid . cid_num ;
if ( c - > cid . cid_name & & num )
if ( c - > cid . cid_name & & num )
snprintf ( tmp , sizeof ( tmp ) , " \" %s \" <%s> " , c - > cid . cid_name , num ) ;
snprintf ( tmp , sizeof ( tmp ) , " \" %s \" <%s> " , c - > cid . cid_name , num ) ;
@ -566,28 +565,17 @@ int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
strncpy ( tmp , c - > cid . cid_name , sizeof ( tmp ) - 1 ) ;
strncpy ( tmp , c - > cid . cid_name , sizeof ( tmp ) - 1 ) ;
else if ( num )
else if ( num )
strncpy ( tmp , num , sizeof ( tmp ) - 1 ) ;
strncpy ( tmp , num , sizeof ( tmp ) - 1 ) ;
else
ast_copy_string ( cdr - > clid , tmp , sizeof ( cdr - > clid ) ) ;
strcpy ( tmp , " " ) ;
ast_copy_string ( cdr - > src , num ? num : " " , sizeof ( cdr - > src ) ) ;
strncpy ( cdr - > clid , tmp , sizeof ( cdr - > clid ) - 1 ) ;
if ( num )
cdr - > disposition = ( c - > _state = = AST_STATE_UP ) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER ;
strncpy ( cdr - > src , num , sizeof ( cdr - > src ) - 1 ) ;
cdr - > amaflags = c - > amaflags ? c - > amaflags : ast_default_amaflags ;
else
ast_copy_string ( cdr - > accountcode , c - > accountcode , sizeof ( cdr - > accountcode ) ) ;
strcpy ( cdr - > src , " " ) ;
if ( c - > _state = = AST_STATE_UP )
cdr - > disposition = AST_CDR_ANSWERED ;
else
cdr - > disposition = AST_CDR_NOANSWER ;
if ( c - > amaflags )
cdr - > amaflags = c - > amaflags ;
else
cdr - > amaflags = ast_default_amaflags ;
strncpy ( cdr - > accountcode , c - > accountcode , sizeof ( cdr - > accountcode ) - 1 ) ;
/* Destination information */
/* Destination information */
strncpy ( cdr - > dst , c - > exten , sizeof ( cdr - > dst ) - 1 ) ;
ast_copy_string ( cdr - > dst , c - > exten , sizeof ( cdr - > dst ) ) ;
strncpy ( cdr - > dcontext , c - > context , sizeof ( cdr - > dcontext ) - 1 ) ;
ast_copy_string ( cdr - > dcontext , c - > context , sizeof ( cdr - > dcontext ) ) ;
/* Unique call identifier */
/* Unique call identifier */
strncpy ( cdr - > uniqueid , c - > uniqueid , sizeof ( cdr - > uniqueid ) - 1 ) ;
ast_copy_string ( cdr - > uniqueid , c - > uniqueid , sizeof ( cdr - > uniqueid ) ) ;
}
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
@ -597,6 +585,7 @@ int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
void ast_cdr_end ( struct ast_cdr * cdr )
void ast_cdr_end ( struct ast_cdr * cdr )
{
{
char * chan ;
char * chan ;
while ( cdr ) {
while ( cdr ) {
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
@ -620,9 +609,8 @@ char *ast_cdr_disp2str(int disposition)
return " BUSY " ;
return " BUSY " ;
case AST_CDR_ANSWERED :
case AST_CDR_ANSWERED :
return " ANSWERED " ;
return " ANSWERED " ;
default :
return " UNKNOWN " ;
}
}
return " UNKNOWN " ;
}
}
char * ast_cdr_flags2str ( int flag )
char * ast_cdr_flags2str ( int flag )
@ -642,10 +630,10 @@ int ast_cdr_setaccount(struct ast_channel *chan, const char *account)
{
{
struct ast_cdr * cdr = chan - > cdr ;
struct ast_cdr * cdr = chan - > cdr ;
strncpy ( chan - > accountcode , account , sizeof ( chan - > accountcode ) - 1 ) ;
ast_copy_string ( chan - > accountcode , account , sizeof ( chan - > accountcode ) ) ;
while ( cdr ) {
while ( cdr ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) )
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) )
strncpy ( cdr - > accountcode , chan - > accountcode , sizeof ( cdr - > accountcode ) - 1 ) ;
ast_copy_string ( cdr - > accountcode , chan - > accountcode , sizeof ( cdr - > accountcode ) ) ;
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
return 0 ;
return 0 ;
@ -657,9 +645,9 @@ int ast_cdr_setamaflags(struct ast_channel *chan, const char *flag)
int newflag ;
int newflag ;
newflag = ast_cdr_amaflags2int ( flag ) ;
newflag = ast_cdr_amaflags2int ( flag ) ;
if ( newflag ) {
if ( newflag )
cdr - > amaflags = newflag ;
cdr - > amaflags = newflag ;
}
return 0 ;
return 0 ;
}
}
@ -669,9 +657,10 @@ int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield)
while ( cdr ) {
while ( cdr ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) )
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) )
strncpy ( cdr - > userfield , userfield , sizeof ( cdr - > userfield ) - 1 ) ;
ast_copy_string ( cdr - > userfield , userfield , sizeof ( cdr - > userfield ) ) ;
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
return 0 ;
return 0 ;
}
}
@ -679,14 +668,15 @@ int ast_cdr_appenduserfield(struct ast_channel *chan, const char *userfield)
{
{
struct ast_cdr * cdr = chan - > cdr ;
struct ast_cdr * cdr = chan - > cdr ;
while ( cdr )
while ( cdr ) {
{
int len = strlen ( cdr - > userfield ) ;
int len = strlen ( cdr - > userfield ) ;
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) )
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) )
strncpy ( cdr - > userfield + len , userfield , sizeof ( cdr - > userfield ) - len - 1 ) ;
strncpy ( cdr - > userfield + len , userfield , sizeof ( cdr - > userfield ) - len - 1 ) ;
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
return 0 ;
return 0 ;
}
}
@ -695,14 +685,10 @@ int ast_cdr_update(struct ast_channel *c)
struct ast_cdr * cdr = c - > cdr ;
struct ast_cdr * cdr = c - > cdr ;
char * num ;
char * num ;
char tmp [ AST_MAX_EXTENSION ] = " " ;
char tmp [ AST_MAX_EXTENSION ] = " " ;
/* Grab source from ANI or normal Caller*ID */
while ( cdr ) {
while ( cdr ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
if ( ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
/* Grab source from ANI or normal Caller*ID */
num = c - > cid . cid_ani ? c - > cid . cid_ani : c - > cid . cid_num ;
if ( c - > cid . cid_ani )
num = c - > cid . cid_ani ;
else
num = c - > cid . cid_num ;
if ( c - > cid . cid_name & & num )
if ( c - > cid . cid_name & & num )
snprintf ( tmp , sizeof ( tmp ) , " \" %s \" <%s> " , c - > cid . cid_name , num ) ;
snprintf ( tmp , sizeof ( tmp ) , " \" %s \" <%s> " , c - > cid . cid_name , num ) ;
@ -710,25 +696,14 @@ int ast_cdr_update(struct ast_channel *c)
strncpy ( tmp , c - > cid . cid_name , sizeof ( tmp ) - 1 ) ;
strncpy ( tmp , c - > cid . cid_name , sizeof ( tmp ) - 1 ) ;
else if ( num )
else if ( num )
strncpy ( tmp , num , sizeof ( tmp ) - 1 ) ;
strncpy ( tmp , num , sizeof ( tmp ) - 1 ) ;
else
ast_copy_string ( cdr - > clid , tmp , sizeof ( cdr - > clid ) ) ;
strcpy ( tmp , " " ) ;
ast_copy_string ( cdr - > src , num ? num : " " , sizeof ( cdr - > src ) ) ;
strncpy ( cdr - > clid , tmp , sizeof ( cdr - > clid ) - 1 ) ;
if ( num )
strncpy ( cdr - > src , num , sizeof ( cdr - > src ) - 1 ) ;
else
strcpy ( cdr - > src , " " ) ;
/* Copy account code et-al */
/* Copy account code et-al */
strncpy ( cdr - > accountcode , c - > accountcode , sizeof ( cdr - > accountcode ) - 1 ) ;
ast_copy_string ( cdr - > accountcode , c - > accountcode , sizeof ( cdr - > accountcode ) ) ;
/* Destination information */
/* Destination information */
if ( ast_strlen_zero ( c - > macroexten ) )
ast_copy_string ( cdr - > dst , ( ast_strlen_zero ( c - > macroexten ) ) ? c - > exten : c - > macroexten , sizeof ( cdr - > dst ) ) ;
strncpy ( cdr - > dst , c - > exten , sizeof ( cdr - > dst ) - 1 ) ;
ast_copy_string ( cdr - > dcontext , ( ast_strlen_zero ( c - > macrocontext ) ) ? c - > context : c - > macrocontext , sizeof ( cdr - > dcontext ) ) ;
else
strncpy ( cdr - > dst , c - > macroexten , sizeof ( cdr - > dst ) - 1 ) ;
if ( ast_strlen_zero ( c - > macrocontext ) )
strncpy ( cdr - > dcontext , c - > context , sizeof ( cdr - > dcontext ) - 1 ) ;
else
strncpy ( cdr - > dcontext , c - > macrocontext , sizeof ( cdr - > dcontext ) - 1 ) ;
}
}
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
@ -753,6 +728,7 @@ void ast_cdr_post(struct ast_cdr *cdr)
{
{
char * chan ;
char * chan ;
struct ast_cdr_beitem * i ;
struct ast_cdr_beitem * i ;
while ( cdr ) {
while ( cdr ) {
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
chan = ! ast_strlen_zero ( cdr - > channel ) ? cdr - > channel : " <unknown> " ;
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
if ( ast_test_flag ( cdr , AST_CDR_FLAG_POSTED ) )
@ -762,18 +738,16 @@ void ast_cdr_post(struct ast_cdr *cdr)
if ( ! cdr - > start . tv_sec & & ! cdr - > start . tv_usec )
if ( ! cdr - > start . tv_sec & & ! cdr - > start . tv_usec )
ast_log ( LOG_WARNING , " CDR on channel '%s' lacks start \n " , chan ) ;
ast_log ( LOG_WARNING , " CDR on channel '%s' lacks start \n " , chan ) ;
cdr - > duration = cdr - > end . tv_sec - cdr - > start . tv_sec + ( cdr - > end . tv_usec - cdr - > start . tv_usec ) / 1000000 ;
cdr - > duration = cdr - > end . tv_sec - cdr - > start . tv_sec + ( cdr - > end . tv_usec - cdr - > start . tv_usec ) / 1000000 ;
if ( cdr - > answer . tv_sec | | cdr - > answer . tv_usec ) {
if ( cdr - > answer . tv_sec | | cdr - > answer . tv_usec )
cdr - > billsec = cdr - > end . tv_sec - cdr - > answer . tv_sec + ( cdr - > end . tv_usec - cdr - > answer . tv_usec ) / 1000000 ;
cdr - > billsec = cdr - > end . tv_sec - cdr - > answer . tv_sec + ( cdr - > end . tv_usec - cdr - > answer . tv_usec ) / 1000000 ;
} else
else
cdr - > billsec = 0 ;
cdr - > billsec = 0 ;
ast_set_flag ( cdr , AST_CDR_FLAG_POSTED ) ;
ast_set_flag ( cdr , AST_CDR_FLAG_POSTED ) ;
ast_mutex_lock ( & cdrlock ) ;
AST_LIST_LOCK ( & be_list ) ;
i = bes ;
AST_LIST_TRAVERSE ( & be_list , i , list ) {
while ( i ) {
i - > be ( cdr ) ;
i - > be ( cdr ) ;
i = i - > next ;
}
}
ast_mutex_unlock( & cdrlock ) ;
AST_LIST_UNLOCK( & be_list ) ;
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
}
}
@ -781,6 +755,7 @@ void ast_cdr_post(struct ast_cdr *cdr)
void ast_cdr_reset ( struct ast_cdr * cdr , int flags )
void ast_cdr_reset ( struct ast_cdr * cdr , int flags )
{
{
struct ast_flags tmp = { flags } ;
struct ast_flags tmp = { flags } ;
while ( cdr ) {
while ( cdr ) {
/* Post if requested */
/* Post if requested */
if ( ast_test_flag ( & tmp , AST_CDR_FLAG_LOCKED ) | | ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
if ( ast_test_flag ( & tmp , AST_CDR_FLAG_LOCKED ) | | ! ast_test_flag ( cdr , AST_CDR_FLAG_LOCKED ) ) {
@ -790,7 +765,7 @@ void ast_cdr_reset(struct ast_cdr *cdr, int flags)
}
}
/* clear variables */
/* clear variables */
if ( ! ast_test_flag ( & tmp , AST_CDR_FLAG_KEEP_VARS ) ) {
if ( ! ast_test_flag ( & tmp , AST_CDR_FLAG_KEEP_VARS ) ) {
ast_cdr_free_vars ( cdr , 0 ) ;
ast_cdr_free_vars ( cdr , 0 ) ;
}
}
@ -807,19 +782,21 @@ void ast_cdr_reset(struct ast_cdr *cdr, int flags)
cdr = cdr - > next ;
cdr = cdr - > next ;
}
}
}
}
struct ast_cdr * ast_cdr_append ( struct ast_cdr * cdr , struct ast_cdr * newcdr )
struct ast_cdr * ast_cdr_append ( struct ast_cdr * cdr , struct ast_cdr * newcdr )
{
{
struct ast_cdr * ret ;
struct ast_cdr * ret ;
if ( cdr ) {
if ( cdr ) {
ret = cdr ;
ret = cdr ;
while ( cdr - > next )
while ( cdr - > next )
cdr = cdr - > next ;
cdr = cdr - > next ;
cdr - > next = newcdr ;
cdr - > next = newcdr ;
} else {
} else {
ret = newcdr ;
ret = newcdr ;
}
}
return ret ;
return ret ;
}
}