Index: include/asterisk/cdr.h =================================================================== --- include/asterisk/cdr.h (revision 10254) +++ include/asterisk/cdr.h (working copy) @@ -73,6 +73,8 @@ struct timeval answer; struct timeval end; + + struct timeval flux; /*! Total time in system, in seconds */ int duration; /*! Total time call is up, in seconds */ @@ -169,6 +171,20 @@ */ void ast_cdr_answer(struct ast_cdr *cdr); +/*! Start billable seconds timer for a call */ +/*! + * \param cdr the cdr you wish to associate with the call + * Starts the timer for maintaining the billable seconds of a call + */ +void ast_cdr_start_billing(struct ast_cdr *cdr); + +/*! Stop billable seconds timer for a call */ +/*! + * \param cdr the cdr you wish to associate with the call + * Stops the timer for maintaining the billable seconds of a call + */ +void ast_cdr_stop_billing(struct ast_cdr *cdr); + /*! Busy a call */ /*! * \param cdr the cdr you wish to associate with the call Index: cdr.c =================================================================== --- cdr.c (revision 10254) +++ cdr.c (working copy) @@ -467,10 +467,38 @@ cdr->disposition = AST_CDR_ANSWERED; if (ast_tvzero(cdr->answer)) cdr->answer = ast_tvnow(); + if (ast_tvzero(cdr->flux)) + cdr->flux = ast_tvnow(); cdr = cdr->next; } } +void ast_cdr_start_billing(struct ast_cdr *cdr) +{ + while (cdr) { + /* Add some conditionals first (must be answered, etc...) */ + cdr->flux = ast_tvnow(); + + cdr = cdr->next; + } +} + +void ast_cdr_stop_billing(struct ast_cdr *cdr) +{ + struct timeval cur; + + while (cdr) { + cur = ast_tvnow(); + + if (!ast_tvzero(cdr->flux)) + cdr->billsec += cur.tv_sec - cdr->flux.tv_sec + (cur.tv_usec - cdr->flux.tv_usec) / 1000000; + + memset(&cdr->flux, 0, sizeof(cdr->flux)); + + cdr = cdr->next; + } +} + void ast_cdr_busy(struct ast_cdr *cdr) { char *chan; @@ -785,10 +813,8 @@ if (ast_tvzero(cdr->start)) 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; - if (!ast_tvzero(cdr->answer)) - cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec + (cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000; - else - cdr->billsec = 0; + if (!ast_tvzero(cdr->flux)) + cdr->billsec += cdr->end.tv_sec - cdr->flux.tv_sec + (cdr->end.tv_usec - cdr->flux.tv_usec) / 1000000; ast_set_flag(cdr, AST_CDR_FLAG_POSTED); AST_LIST_LOCK(&be_list); AST_LIST_TRAVERSE(&be_list, i, list) { @@ -828,6 +854,7 @@ memset(&cdr->start, 0, sizeof(cdr->start)); memset(&cdr->end, 0, sizeof(cdr->end)); memset(&cdr->answer, 0, sizeof(cdr->answer)); + memset(&cdr->flux, 0, sizeof(cdr->flux)); cdr->billsec = 0; cdr->duration = 0; ast_cdr_start(cdr); Index: apps/app_cdr.c =================================================================== --- apps/app_cdr.c (revision 10254) +++ apps/app_cdr.c (working copy) @@ -37,7 +37,7 @@ #include "asterisk/pbx.h" -static char *tdesc = "Tell Asterisk to not maintain a CDR for the current call"; +static char *tdesc = "Asterisk CDR control functions"; static char *nocdr_descrip = " NoCDR(): This application will tell Asterisk not to maintain a CDR for the\n" @@ -46,6 +46,26 @@ static char *nocdr_app = "NoCDR"; static char *nocdr_synopsis = "Tell Asterisk to not maintain a CDR for the current call"; +static char *bill_sec_start_descrip = +" StartBillSecCDR(): This application will tell Asterisk to start the billable seconds timer.\n" +"This timer is written in the CDR as the 'billsec' field. By default Asterisk will set the\n" +"billable seconds to be equal to the time from when the call is answered to the time the call\n" +"is hung up. StartBillSecCDR allows the user to control the billable seconds timer.\n"; + +static char *bill_sec_start_app = "StartBillSecCDR"; +static char *bill_sec_start_synopsis = "Tell Asterisk to start billable seconds timer for the current call"; + +static char *bill_sec_stop_descrip = +" StopBillSecCDR(): This application will tell Asterisk to stop the billable seconds time.\n" +"This timer is written in the CDR as the 'billsec' field. By default Asterisk will set the\n" +"billable seconds to be equal to the time from when the call is answered to the time the call\n" +"is hung up. StopBillSecCDR allows the user to control the billable seconds timer.\n"; + +static char *bill_sec_stop_app = "StopBillSecCDR"; +static char *bill_sec_stop_synopsis = "Tell Asterisk to stop billable seconds timer for the current call"; + +STANDARD_LOCAL_USER; + LOCAL_USER_DECL; static int nocdr_exec(struct ast_channel *chan, void *data) @@ -64,11 +84,43 @@ return 0; } +static int bill_sec_start_exec(struct ast_channel *chan, void *data) +{ + struct localuser *u; + + LOCAL_USER_ADD(u); + + if (chan->cdr) { + ast_cdr_start_billing(chan->cdr); + } + + LOCAL_USER_REMOVE(u); + + return 0; +} + +static int bill_sec_stop_exec(struct ast_channel *chan, void *data) +{ + struct localuser *u; + + LOCAL_USER_ADD(u); + + if (chan->cdr) { + ast_cdr_stop_billing(chan->cdr); + } + + LOCAL_USER_REMOVE(u); + + return 0; +} + int unload_module(void) { int res; res = ast_unregister_application(nocdr_app); + res |= ast_unregister_application(bill_sec_start_app); + res |= ast_unregister_application(bill_sec_stop_app); STANDARD_HANGUP_LOCALUSERS; @@ -77,7 +129,13 @@ int load_module(void) { - return ast_register_application(nocdr_app, nocdr_exec, nocdr_synopsis, nocdr_descrip); + int res; + + res = ast_register_application(nocdr_app, nocdr_exec, nocdr_synopsis, nocdr_descrip); + res |= ast_register_application(bill_sec_start_app, bill_sec_start_exec, bill_sec_start_synopsis, bill_sec_start_descrip); + res |= ast_register_application(bill_sec_stop_app, bill_sec_stop_exec, bill_sec_stop_synopsis, bill_sec_stop_descrip); + + return res; } char *description(void)