Fix incorrect duration reporting in CDRs created in batch mode
authorMatthew Jordan <mjordan@digium.com>
Mon, 25 Jun 2012 19:39:03 +0000 (19:39 +0000)
committerMatthew Jordan <mjordan@digium.com>
Mon, 25 Jun 2012 19:39:03 +0000 (19:39 +0000)
Certain places in core/cdr.c would, if the duration value were 0, calculate the
duration as being the delta between the current time and the time at which the
CDR record was started.  While this does not typically cause a problem in
non-batch mode, this can cause an issue in batch mode where CDR records are
gathered and written long after those calls have ended. In particular, this
affects calls that were never answered, as those are expected to have a duration
of 0.  Often, this would result in CDR logs with a significant number of calls
with lengthy durations, but dispositions of "BUSY".

Note that this does not affect cdr_csv, as that backend does not use
ast_cdr_getvar and instead directly reports the duration value.  The affected
core backends include cdr_apative_odbc and cdr_custom; other extended or
deprecated CDR backends may potentially still directly manipulate the duration
values.

(issue ASTERISK-19860)
Reported by: Thomas Arimont

(issue AST-883)
Reported by: Thomas Arimont
Tested by: Matt Jordan

Review: https://reviewboard.asterisk.org/r/1996/
........

Merged revisions 369351 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........

Merged revisions 369369 from http://svn.asterisk.org/svn/asterisk/branches/10

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@369370 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/cdr.c

index 3fc8ef1..7847dc4 100644 (file)
@@ -301,9 +301,9 @@ void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *wor
                cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
        else if (!strcasecmp(name, "end"))
                cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
                cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
        else if (!strcasecmp(name, "end"))
                cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
-       else if (!strcasecmp(name, "duration"))
-               snprintf(workspace, workspacelen, "%ld", cdr->duration ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
-       else if (!strcasecmp(name, "billsec"))
+       else if (!strcasecmp(name, "duration")) {
+               snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
+       } else if (!strcasecmp(name, "billsec"))
                snprintf(workspace, workspacelen, "%ld", cdr->billsec || cdr->answer.tv_sec == 0 ? cdr->billsec : (long)ast_tvdiff_ms(ast_tvnow(), cdr->answer) / 1000);
        else if (!strcasecmp(name, "disposition")) {
                if (raw) {
                snprintf(workspace, workspacelen, "%ld", cdr->billsec || cdr->answer.tv_sec == 0 ? cdr->billsec : (long)ast_tvdiff_ms(ast_tvnow(), cdr->answer) / 1000);
        else if (!strcasecmp(name, "disposition")) {
                if (raw) {