Merged revisions 134883 via svnmerge from
authorSteve Murphy <>
Thu, 31 Jul 2008 19:48:08 +0000 (19:48 +0000)
committerSteve Murphy <>
Thu, 31 Jul 2008 19:48:08 +0000 (19:48 +0000)

r134883 | murf | 2008-07-31 13:23:42 -0600 (Thu, 31 Jul 2008) | 51 lines

(closes issue #11849)
Reported by: greyvoip
Tested by: murf

OK, a few days of debugging, a bunch of instrumentation
in chan_sip, main/channel.c, main/pbx.c, etc. and 5 solid
notebook pages of notes later, I  have made the small
tweek necc. to get the start time right on the second
CDR when:

  A Calls B
  B answ.
  A hits Xfer button on sip phone,
  A dials C and hits the OK button,
  A hangs up
  C answers ringing phone
  B and C converse
  B and/or C hangs up

But does not harm the scenario where:

  A Calls B
  B answ.
  B hits xfer button on sip phone,
  B dials C and hits the OK button,
  B hangs up
  C answers ringing phone
  A and C converse
  A and/or C hangs up

The difference in start times on the second CDR is because
of a Masquerade on the B channel when the xfer number is
sent. It ends up replacing the CDR on the B channel with
a duplicate, which ends up getting tossed out. We keep
a pointer to the first CDR, and update *that* after the
bridge closes. But, only if the CDR has changed.

I hope this change is specific enough not to muck
up any current CDR-based apps. In my defence, I
assert that the previous information was wrong,
and this change fixes it, and possibly other
similar scenarios.

I wonder if I should be doing the same thing
for the channel, as I did for the peer, but
I can't think of a scenario this might affect.
I leave it, then, as an exersize for the users,
to find the scenario where the chan's CDR
changes and loses the proper start time.


and as to 1.4 to trunk; have I expressed my
feelings about code shifting from one file
to another? Good.

git-svn-id: 65c4cc65-6c06-0410-ace0-fbb531ad65f3


index a7eeedb..9724cc8 100644 (file)
@@ -2070,6 +2070,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
        struct ast_option_header *aoh;
        struct ast_bridge_config backup_config;
        struct ast_cdr *bridge_cdr = NULL;
+       struct ast_cdr *orig_peer_cdr = NULL;
        memset(&backup_config, 0, sizeof(backup_config));
@@ -2107,6 +2108,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
+       orig_peer_cdr = peer->cdr;
        if (!chan->cdr || (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED))) {
@@ -2141,8 +2143,9 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                ast_cdr_answer(chan->cdr); /* for the sake of cli status checks */
                ast_set_flag(chan->cdr, AST_CDR_FLAG_BRIDGED);
-               if (peer->cdr)
+               if (peer->cdr) {
                        ast_set_flag(peer->cdr, AST_CDR_FLAG_BRIDGED);
+               }
        for (;;) {
                struct ast_channel *other;      /* used later */
@@ -2313,10 +2316,17 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                /* just in case, these channels get bridged again before hangup */
-               if (chan->cdr)
+               if (chan->cdr) {
-               if (peer->cdr)
-                       ast_cdr_specialized_reset(peer->cdr,0);
+               }
+               if (peer->cdr) {
+                       if (orig_peer_cdr && peer->cdr != orig_peer_cdr) {
+                               /* this can only happen if there was a transfer, methinks */
+                               ast_cdr_specialized_reset(orig_peer_cdr,0);
+                       } else {
+                               ast_cdr_specialized_reset(peer->cdr,0);
+                       }
+               }
        return res;