diff --git a/funcs/func_cdr.c b/funcs/func_cdr.c index 8d98479d151c0294614e8f28c20d6b18491253af..ae15f6aa9459cea42cd20406b6b7fe6caa467ddd 100644 --- a/funcs/func_cdr.c +++ b/funcs/func_cdr.c @@ -221,6 +221,26 @@ STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_read_message_type); STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_write_message_type); STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_prop_write_message_type); +static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name) +{ + struct timeval time; + char *value = NULL; + char tempbuf[128]; + + if (ast_strlen_zero(ast_channel_name(chan))) { + /* Format request on a dummy channel */ + ast_cdr_format_var(ast_channel_cdr(chan), time_name, &value, tempbuf, sizeof(tempbuf), 1); + } else { + ast_cdr_getvar(ast_channel_name(chan), time_name, tempbuf, sizeof(tempbuf)); + } + + if (sscanf(tempbuf, "%ld.%ld", &time.tv_sec, &time.tv_usec) != 2) { + ast_log(AST_LOG_WARNING, "Failed to fully extract '%s' from CDR\n", time_name); + } + + return time; +} + static void cdr_read_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message) { struct cdr_func_payload *payload = stasis_message_data(message); @@ -268,16 +288,21 @@ static void cdr_read_callback(void *data, struct stasis_subscription *sub, struc if (ast_test_flag(&flags, OPT_FLOAT) && (!strcasecmp("billsec", args.variable) || !strcasecmp("duration", args.variable))) { - long ms; - double dtime; + struct timeval start = cdr_retrieve_time(payload->chan, !strcasecmp("billsec", args.variable) ? "answer" : "start"); + struct timeval finish = cdr_retrieve_time(payload->chan, "end"); + double delta; - if (sscanf(tempbuf, "%30ld", &ms) != 1) { - ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n", - args.variable, tempbuf, ast_channel_name(payload->chan)); - return; + if (ast_tvzero(finish)) { + finish = ast_tvnow(); } - dtime = (double)(ms / 1000.0); - snprintf(tempbuf, sizeof(tempbuf), "%lf", dtime); + + if (ast_tvzero(start)) { + delta = 0.0; + } else { + delta = (double)(ast_tvdiff_us(finish, start) / 1000000.0); + } + snprintf(tempbuf, sizeof(tempbuf), "%lf", delta); + } else if (!ast_test_flag(&flags, OPT_UNPARSED)) { if (!strcasecmp("start", args.variable) || !strcasecmp("end", args.variable)