mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-03 04:16:43 +00:00
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
This commit is contained in:
15
main/cdr.c
15
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 */
|
/* 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,
|
cdr->party_a.snapshot->base->name,
|
||||||
(long)cdr->start.tv_sec,
|
(long)cdr->start.tv_sec,
|
||||||
(long)cdr->start.tv_usec,
|
(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->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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2352,6 +2354,7 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub
|
|||||||
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 */
|
||||||
@@ -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
|
ast_assert(cdr->party_b.snapshot
|
||||||
&& !strcasecmp(cdr->party_b.snapshot->base->name, leave_data->channel->base->name));
|
&& !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.
|
* 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;
|
||||||
@@ -2408,6 +2412,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;
|
||||||
|
|
||||||
@@ -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",
|
CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n",
|
||||||
channel->base->name,
|
channel->base->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->base->uniqueid, OBJ_SEARCH_KEY);
|
cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);
|
||||||
if (!cdr) {
|
if (!cdr) {
|
||||||
@@ -2434,7 +2439,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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user