@ -42,21 +42,82 @@ static char *synopsis =
" Forks the Call Data Record " ;
static char * descrip =
" ForkCDR([options]): Causes the Call Data Record to fork an additional \n "
" cdr record starting from the time of the fork call \n "
" cdr record starting from the time of the fork call. This new cdr record will \n "
" be linked to end of the list of cdr records attached to the channel. The original CDR is \n "
" has a LOCKED flag set, which forces most cdr operations to skip it, except \n "
" for the functions that set the answer and end times, which ignore the LOCKED \n "
" flag. This allows all the cdr records in the channel to be 'ended' together \n "
" when the channel is closed. \n "
" The CDR() func (when setting CDR values) normally ignores the LOCKED flag also, \n "
" but has options to vary its behavior. The 'T' option (described below), can \n "
" override this behavior, but beware the risks. \n "
" \n "
" Detailed Behavior Description: \n "
" First, this app finds the last cdr record in the list, and makes \n "
" a copy of it. This new copy will be the newly forked cdr record. \n "
" Next, this new record is linked to the end of the cdr record list. \n "
" Next, The new cdr record is RESET (unless you use an option to prevent this) \n "
" This means that: \n "
" 1. All flags are unset on the cdr record \n "
" 2. the start, end, and answer times are all set to zero. \n "
" 3. the billsec and duration fields are set to zero. \n "
" 4. the start time is set to the current time. \n "
" 5. the disposition is set to NULL. \n "
" Next, unless you specified the 'v' option, all variables will be \n "
" removed from the original cdr record. Thus, the 'v' option allows \n "
" any CDR variables to be replicated to all new forked cdr records. \n "
" Without the 'v' option, the variables on the original are effectively \n "
" moved to the new forked cdr record. \n "
" Next, if the 's' option is set, the provided variable and value \n "
" are set on the original cdr record. \n "
" Next, if the 'a' option is given, and the original cdr record has an \n "
" answer time set, then the new forked cdr record will have its answer \n "
" time set to its start time. If the old answer time were carried forward, \n "
" the answer time would be earlier than the start time, giving strange \n "
" duration and billsec times. \n "
" Next, if the 'd' option was specified, the disposition is copied from \n "
" the original cdr record to the new forked cdr. \n "
" Next, if the 'D' option was specified, the destination channel field \n "
" in the new forked CDR is erased. \n "
" Next, if the 'e' option was specified, the 'end' time for the original \n "
" cdr record is set to the current time. Future hang-up or ending events \n "
" will not override this time stamp. \n "
" Next, If the 'A' option is specified, the original cdr record will have \n "
" it ANS_LOCKED flag set, which prevent future call dispostion events \n "
" from updating the original cdr record's disposition. Normally, an \n "
" 'ANSWERED' event would mark all cdr records in the chain as 'ANSWERED'. \n "
" Next, if the 'T' option is specified, the original cdr record will have \n "
" its 'DONT_TOUCH' flag set, which will force the cdr_answer, cdr_end, and \n "
" cdr_setvar functions to leave that cdr record alone. \n "
" And, last but not least, the original cdr record has its LOCKED flag \n "
" set. Almost all internal CDR functions (except for the funcs that set \n "
" the end, and answer times, and set a variable) will honor this flag \n "
" and leave a LOCKED cdr record alone. \n "
" This means that the newly created forked cdr record will affected \n "
" by events transpiring within Asterisk, with the previously noted \n "
" exceptions. \n "
" Options: \n "
" a - update the answer time on the NEW CDR just after it's been inited.. \n "
" a - update the answer time on the NEW CDR just after it's been inited..\n "
" The new CDR may have been answered already, the reset that forkcdr. \n "
" does will erase the answer time. This will bring it back, but. \n "
" does will erase the answer time. This will bring it back, but \n "
" the answer time will be a copy of the fork/start time. It will. \n "
" only do this if the initial cdr was indeed already answered.. \n "
" D - Copy the disposition forward from the old cdr, after the . \n "
" A - Lock the original CDR against the answer time being updated. \n "
" This will allow the disposition on the original CDR to remain the same. \n "
" d - Copy the disposition forward from the old cdr, after the . \n "
" init.. \n "
" d - Clear the dstchannel on the new CDR after reset.. \n "
" e - end the original CDR. Do this after all the necc. data. \n "
" D - Clear the dstchannel on the new CDR after reset..\n "
" e - end the original CDR. Do this after all the necc. data.\n "
" is copied from the original CDR to the new forked CDR.. \n "
" R - do NOT reset the new cdr.. \n "
" s(name=val) - Set the CDR var 'name' in the original CDR, with value. \n "
" 'val'. \n "
" T - Mark the original CDR with a DONT_TOUCH flag. setvar, answer, and end \n "
" cdr funcs will obey this flag; normally they don't honor the LOCKED \n "
" flag set on the original CDR record. \n "
" Beware-- using this flag may cause CDR's not to have their end times \n "
" updated! It is suggested that if you specify this flag, you might \n "
" wish to use the 'e' flag as well! \n "
" v - When the new CDR is forked, it gets a copy of the vars attached \n "
" to the current CDR. The vars attached to the original CDR are removed \n "
" unless this option is specified. \n " ;
@ -70,6 +131,8 @@ enum {
OPT_NORESET = ( 1 < < 4 ) ,
OPT_KEEPVARS = ( 1 < < 5 ) ,
OPT_VARSET = ( 1 < < 6 ) ,
OPT_ANSLOCK = ( 1 < < 7 ) ,
OPT_DONTOUCH = ( 1 < < 8 ) ,
} ;
enum {
@ -80,11 +143,13 @@ enum {
AST_APP_OPTIONS ( forkcdr_exec_options , {
AST_APP_OPTION ( ' a ' , OPT_SETANS ) ,
AST_APP_OPTION ( ' A ' , OPT_ANSLOCK ) ,
AST_APP_OPTION ( ' d ' , OPT_SETDISP ) ,
AST_APP_OPTION ( ' D ' , OPT_RESETDEST ) ,
AST_APP_OPTION ( ' e ' , OPT_ENDCDR ) ,
AST_APP_OPTION ( ' R ' , OPT_NORESET ) ,
AST_APP_OPTION_ARG ( ' s ' , OPT_VARSET , OPT_ARG_VARSET ) ,
AST_APP_OPTION ( ' T ' , OPT_DONTOUCH ) ,
AST_APP_OPTION ( ' v ' , OPT_KEEPVARS ) ,
} ) ;
@ -132,6 +197,12 @@ static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, ch
if ( ast_test_flag ( & optflags , OPT_ENDCDR ) )
ast_cdr_end ( cdr ) ;
if ( ast_test_flag ( & optflags , OPT_ANSLOCK ) )
ast_set_flag ( cdr , AST_CDR_FLAG_ANSLOCKED ) ;
if ( ast_test_flag ( & optflags , OPT_DONTOUCH ) )
ast_set_flag ( cdr , AST_CDR_FLAG_DONT_TOUCH ) ;
ast_set_flag ( cdr , AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED ) ;
}