From: George Joseph Date: Wed, 22 Jan 2020 18:56:38 +0000 (-0700) Subject: cdr.c: Set event time on party b when leaving a parking bridge X-Git-Tag: 17.2.0-rc1~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f34a4d5a775e2dd3feba11102c9b23fbff12eb72;p=thirdparty%2Fasterisk.git cdr.c: Set event time on party b when leaving a parking bridge When Alice calls Bob and Bob does a blind transfer to Charlie, Bob's bridge leave event generates a finalize on both the party_a and party_b CDRs but while the party_a CDR has the correct end time set from the event time, party_b's leg did not. This caused that CDR's end time to be equal to the answered time and resulted in a billsec of 0. * We now pass the bridge leave message event time to cdr_object_party_b_left_bridge_cb() and set it on that CDR before calling cdr_object_finalize() on it. NOTE: This issue affected transfers using chan_sip most of the time but also occasionally affected chan_pjsip probably due to message timing. ASTERISK-28677 Reported by: Maciej Michno Change-Id: I790720f1e7326f9b8ce8293028743b0ef0fb2cca --- diff --git a/main/cdr.c b/main/cdr.c index 2c3ca9762e..e862caffe2 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -1457,7 +1457,7 @@ static void cdr_object_finalize(struct cdr_object *cdr) } /* tv_usec is suseconds_t, which could be int or long */ - ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dispo %s\n", + ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dur %.3f bill %.3f dispo %s\n", cdr->party_a.snapshot->base->name, (long)cdr->start.tv_sec, (long)cdr->start.tv_usec, @@ -1465,6 +1465,8 @@ static void cdr_object_finalize(struct cdr_object *cdr) (long)cdr->answer.tv_usec, (long)cdr->end.tv_sec, (long)cdr->end.tv_usec, + (double)ast_tvdiff_ms(cdr->end, cdr->start) / 1000.0, + (double)ast_tvdiff_ms(cdr->end, cdr->answer) / 1000.0, ast_cdr_disp2str(cdr->disposition)); } @@ -2352,6 +2354,7 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub struct bridge_leave_data { struct ast_bridge_snapshot *bridge; struct ast_channel_snapshot *channel; + const struct timeval *lastevent; }; /*! \brief Callback used to notify CDRs of a Party B leaving the bridge */ @@ -2370,9 +2373,10 @@ static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, void *data, i ast_assert(cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->base->name, leave_data->channel->base->name)); - /* It is our Party B, in our bridge. Set the end time and let the handler + /* It is our Party B, in our bridge. Set the last event and let the handler * transition our CDR appropriately when we leave the bridge. */ + cdr->lastevent = *leave_data->lastevent; cdr_object_finalize(cdr); } return 0; @@ -2408,6 +2412,7 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription * struct bridge_leave_data leave_data = { .bridge = bridge, .channel = channel, + .lastevent = stasis_message_timestamp(message) }; int left_bridge = 0; @@ -2421,8 +2426,8 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription * CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n", channel->base->name, - (unsigned int)stasis_message_timestamp(message)->tv_sec, - (unsigned int)stasis_message_timestamp(message)->tv_usec); + (unsigned int)leave_data.lastevent->tv_sec, + (unsigned int)leave_data.lastevent->tv_usec); cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY); if (!cdr) { @@ -2434,7 +2439,7 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription * /* Party A */ ao2_lock(cdr); for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) { - it_cdr->lastevent = *stasis_message_timestamp(message); + it_cdr->lastevent = *leave_data.lastevent; if (!it_cdr->fn_table->process_bridge_leave) { continue; }