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
16.8
George Joseph 5 years ago
parent 1b2d305178
commit 1b452ebb51

@ -1465,7 +1465,7 @@ static void cdr_object_finalize(struct cdr_object *cdr)
} }
/* tv_usec is suseconds_t, which could be int or long */ /* 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->name, cdr->party_a.snapshot->name,
(long)cdr->start.tv_sec, (long)cdr->start.tv_sec,
(long)cdr->start.tv_usec, (long)cdr->start.tv_usec,
@ -1473,6 +1473,8 @@ static void cdr_object_finalize(struct cdr_object *cdr)
(long)cdr->answer.tv_usec, (long)cdr->answer.tv_usec,
(long)cdr->end.tv_sec, (long)cdr->end.tv_sec,
(long)cdr->end.tv_usec, (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)); ast_cdr_disp2str(cdr->disposition));
} }
@ -2370,6 +2372,7 @@ static void handle_channel_cache_message(void *data, struct stasis_subscription
struct bridge_leave_data { struct bridge_leave_data {
struct ast_bridge_snapshot *bridge; struct ast_bridge_snapshot *bridge;
struct ast_channel_snapshot *channel; struct ast_channel_snapshot *channel;
const struct timeval *lastevent;
}; };
/*! \brief Callback used to notify CDRs of a Party B leaving the bridge */ /*! \brief Callback used to notify CDRs of a Party B leaving the bridge */
@ -2388,9 +2391,10 @@ static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, void *data, i
ast_assert(cdr->party_b.snapshot ast_assert(cdr->party_b.snapshot
&& !strcasecmp(cdr->party_b.snapshot->name, leave_data->channel->name)); && !strcasecmp(cdr->party_b.snapshot->name, leave_data->channel->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. * transition our CDR appropriately when we leave the bridge.
*/ */
cdr->lastevent = *leave_data->lastevent;
cdr_object_finalize(cdr); cdr_object_finalize(cdr);
} }
return 0; return 0;
@ -2426,6 +2430,7 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription *
struct bridge_leave_data leave_data = { struct bridge_leave_data leave_data = {
.bridge = bridge, .bridge = bridge,
.channel = channel, .channel = channel,
.lastevent = stasis_message_timestamp(message)
}; };
int left_bridge = 0; int left_bridge = 0;
@ -2439,8 +2444,8 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription *
CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n", CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n",
channel->name, channel->name,
(unsigned int)stasis_message_timestamp(message)->tv_sec, (unsigned int)leave_data.lastevent->tv_sec,
(unsigned int)stasis_message_timestamp(message)->tv_usec); (unsigned int)leave_data.lastevent->tv_usec);
cdr = ao2_find(active_cdrs_master, channel->uniqueid, OBJ_SEARCH_KEY); cdr = ao2_find(active_cdrs_master, channel->uniqueid, OBJ_SEARCH_KEY);
if (!cdr) { if (!cdr) {
@ -2452,7 +2457,7 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription *
/* Party A */ /* Party A */
ao2_lock(cdr); ao2_lock(cdr);
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) { 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) { if (!it_cdr->fn_table->process_bridge_leave) {
continue; continue;
} }

Loading…
Cancel
Save