Merged revisions 127663 via svnmerge from
authorSteve Murphy <murf@digium.com>
Thu, 3 Jul 2008 17:16:44 +0000 (17:16 +0000)
committerSteve Murphy <murf@digium.com>
Thu, 3 Jul 2008 17:16:44 +0000 (17:16 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r127663 | murf | 2008-07-02 18:16:25 -0600 (Wed, 02 Jul 2008) | 30 lines

The CDRfix4/5/6 omnibus cdr fixes.

(closes issue #10927)
Reported by: murf
Tested by: murf, deeperror

(closes issue #12907)
Reported by: falves11
Tested by: murf, falves11

(closes issue #11849)
Reported by: greyvoip

As to 11849, I think these changes fix the core problems
brought up in that bug, but perhaps not the more global
problems created by the limitations of CDR's themselves
not being oriented around transfers.

Reopen if necc, but bug reports are not the best
medium for enhancement discussions. We need to start
a second-generation CDR standardization effort to cover
transfers.

(closes issue #11093)
Reported by: rossbeer
Tested by: greyvoip, murf

........

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

channels/chan_dahdi.c
channels/chan_sip.c
include/asterisk/cdr.h
main/cdr.c
main/channel.c
main/features.c
main/pbx.c

index af68b7c..b00bd23 100644 (file)
@@ -4080,18 +4080,6 @@ static int attempt_transfer(struct dahdi_pvt *p)
                if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
                        tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, DAHDI_TONE_RINGTONE);
                }
-               if (p->subs[SUB_REAL].owner->cdr) {
-                       /* Move CDR from second channel to current one */
-                       p->subs[SUB_THREEWAY].owner->cdr =
-                               ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->cdr);
-                       p->subs[SUB_REAL].owner->cdr = NULL;
-               }
-               if (ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr) {
-                       /* Move CDR from second channel's bridge to current one */
-                       p->subs[SUB_THREEWAY].owner->cdr =
-                               ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr);
-                       ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr = NULL;
-               }
                 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
                                        ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
@@ -4108,18 +4096,6 @@ static int attempt_transfer(struct dahdi_pvt *p)
                if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
                        tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
                }
-               if (p->subs[SUB_THREEWAY].owner->cdr) {
-                       /* Move CDR from second channel to current one */
-                       p->subs[SUB_REAL].owner->cdr = 
-                               ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->cdr);
-                       p->subs[SUB_THREEWAY].owner->cdr = NULL;
-               }
-               if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr) {
-                       /* Move CDR from second channel's bridge to current one */
-                       p->subs[SUB_REAL].owner->cdr = 
-                               ast_cdr_append(p->subs[SUB_REAL].owner->cdr, ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr);
-                       ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr = NULL;
-               }
                if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
                                        ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
@@ -4855,7 +4831,19 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                                        dahdi_enable_ec(p);
                                                        ast_hangup(chan);
                                                } else {
+                                                       struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
+                                                       int way3bridge = 0, cdr3way = 0;
+                                                       
+                                                       if (!other) {
+                                                               other = ast_bridged_channel(p->subs[SUB_REAL].owner);
+                                                       } else
+                                                               way3bridge = 1;
+                                                       
+                                                       if (p->subs[SUB_THREEWAY].owner->cdr)
+                                                               cdr3way = 1;
+                                                       
                                                        ast_verb(3, "Started three way call on channel %d\n", p->channel);
+
                                                        /* Start music on hold if appropriate */
                                                        if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
                                                                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
@@ -4886,6 +4874,16 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
                                                    (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
                                                        int otherindex = SUB_THREEWAY;
+                                                       struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
+                                                       int way3bridge = 0, cdr3way = 0;
+                                                       
+                                                       if (!other) {
+                                                               other = ast_bridged_channel(p->subs[SUB_REAL].owner);
+                                                       } else
+                                                               way3bridge = 1;
+                                                       
+                                                       if (p->subs[SUB_THREEWAY].owner->cdr)
+                                                               cdr3way = 1;
 
                                                        ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
                                                        /* Put them in the threeway, and flip */
index 1e5b927..8d6adf4 100644 (file)
@@ -17073,19 +17073,6 @@ static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target
                if (peerd)
                        ast_quiet_chan(peerd);
 
-               /* Fix CDRs so they're attached to the remaining channel */
-               if (peera->cdr && peerb->cdr)
-                       peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
-               else if (peera->cdr) 
-                       peerb->cdr = peera->cdr;
-               peera->cdr = NULL;
-
-               if (peerb->cdr && peerc->cdr) 
-                       peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
-               else if (peerc->cdr)
-                       peerb->cdr = peerc->cdr;
-               peerc->cdr = NULL;
-       
                ast_debug(4, "SIP transfer: trying to masquerade %s into %s\n", peerc->name, peerb->name);
                if (ast_channel_masquerade(peerb, peerc)) {
                        ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name);
index addef04..dc14f32 100644 (file)
 #define _ASTERISK_CDR_H
 
 #include <sys/time.h>
+
+/*! \name CDR Flags */
+/*@{ */
 #define AST_CDR_FLAG_KEEP_VARS         (1 << 0)
 #define AST_CDR_FLAG_POSTED                    (1 << 1)
 #define AST_CDR_FLAG_LOCKED                    (1 << 2)
 #define AST_CDR_FLAG_CHILD                     (1 << 3)
 #define AST_CDR_FLAG_POST_DISABLED     (1 << 4)
-#define AST_CDR_FLAG_ANSLOCKED      (1 << 5)
-#define AST_CDR_FLAG_DONT_TOUCH     (1 << 6)
+#define AST_CDR_FLAG_BRIDGED           (1 << 5)
+#define AST_CDR_FLAG_MAIN                      (1 << 6)
+#define AST_CDR_FLAG_ENABLE                    (1 << 7)
+#define AST_CDR_FLAG_ANSLOCKED      (1 << 8)
+#define AST_CDR_FLAG_DONT_TOUCH     (1 << 9)
 #define AST_CDR_FLAG_POST_ENABLE                (1 << 5)
+/*@} */
 
-/*! \name CDR Flags */
+/*! \name CDR Flags - Disposition */
 /*@{ */
 #define AST_CDR_NULL                0
 #define AST_CDR_FAILED                         (1 << 0)
@@ -299,8 +306,16 @@ char *ast_cdr_disp2str(int disposition);
  */
 void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags);
 
-/*! 
- * \brief Flags to a string 
+/*! Reset the detail record times, flags */
+/*!
+ * \param cdr which cdr to act upon
+ * \param flags |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it
+ *              |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's
+ */
+void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *flags);
+
+/*! Flags to a string */
+/*!
  * \param flags binary flag
  * Converts binary flags to string flags
  * Returns string with flag name
index 259328f..1600520 100644 (file)
@@ -781,6 +781,10 @@ void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data)
        for (; cdr; cdr = cdr->next) {
                if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
                        check_post(cdr);
+                       if (!app)
+                               app = "";
+                       if (!data)
+                               data = "";
                        ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp));
                        ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata));
                }
@@ -864,7 +868,13 @@ void ast_cdr_end(struct ast_cdr *cdr)
                        cdr->disposition = AST_CDR_FAILED;
                } else
                        cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
-               cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec;
+               if (ast_tvzero(cdr->answer)) {
+                       if (cdr->disposition == AST_CDR_ANSWERED) {
+                               ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>"));
+                               cdr->disposition = AST_CDR_FAILED;
+                       }
+               } else
+                       cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
        }
 }
 
@@ -1064,6 +1074,27 @@ void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *_flags)
        }
 }
 
+void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *_flags)
+{
+       struct ast_flags flags = { 0 };
+
+       if (_flags)
+               ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
+
+       if (_flags)
+               ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
+       
+       /* Reset to initial state */
+       ast_clear_flag(cdr, AST_FLAGS_ALL);     
+       memset(&cdr->start, 0, sizeof(cdr->start));
+       memset(&cdr->end, 0, sizeof(cdr->end));
+       memset(&cdr->answer, 0, sizeof(cdr->answer));
+       cdr->billsec = 0;
+       cdr->duration = 0;
+       ast_cdr_start(cdr);
+       cdr->disposition = AST_CDR_NULL;
+}
+
 struct ast_cdr *ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr) 
 {
        struct ast_cdr *ret;
index 240d169..cbfe8ff 100644 (file)
@@ -1582,7 +1582,6 @@ static void free_translation(struct ast_channel *clone)
 int ast_hangup(struct ast_channel *chan)
 {
        int res = 0;
-       struct ast_cdr *cdr = NULL;
 
        /* Don't actually hang up a channel that will masquerade as someone else, or
           if someone is going to masquerade as us */
@@ -1633,11 +1632,6 @@ int ast_hangup(struct ast_channel *chan)
                        chan->generator->release(chan, chan->generatordata);
        chan->generatordata = NULL;
        chan->generator = NULL;
-       if (chan->cdr) {                /* End the CDR if it hasn't already */
-               ast_cdr_end(chan->cdr);
-               cdr = chan->cdr;
-               chan->cdr = NULL;
-       }
        if (ast_test_flag(chan, AST_FLAG_BLOCKING)) {
                ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd "
                                        "is blocked by thread %ld in procedure %s!  Expect a failure\n",
@@ -1667,10 +1661,13 @@ int ast_hangup(struct ast_channel *chan)
                        chan->hangupcause,
                        ast_cause2str(chan->hangupcause)
                        );
-       ast_channel_free(chan);
 
-       if (cdr)
-               ast_cdr_detach(cdr);
+       if (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_BRIDGED) && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED) && chan->cdr->disposition != AST_CDR_NULL) {
+               ast_cdr_end(chan->cdr);
+               ast_cdr_detach(chan->cdr);
+       }
+       
+       ast_channel_free(chan);
 
        return res;
 }
@@ -1722,7 +1719,6 @@ int __ast_answer(struct ast_channel *chan, unsigned int delay)
                }
                return res;
        case AST_STATE_UP:
-               ast_cdr_answer(chan->cdr);
                break;
        default:
                break;
@@ -2524,15 +2520,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
                                } else {
                                        /* Answer the CDR */
                                        ast_setstate(chan, AST_STATE_UP);
-                                       if (!chan->cdr) { /* up till now, this insertion hasn't been done. Therefore,
-                                                                                to keep from throwing off the basic order of the universe,
-                                                                                we will try to keep this cdr from getting posted. */
-                                               chan->cdr = ast_cdr_alloc();
-                                               ast_cdr_init(chan->cdr, chan);
-                                               ast_cdr_start(chan->cdr);
-                                       }
-                                       
-                                       ast_cdr_answer(chan->cdr);
+                                       /* removed a call to ast_cdr_answer(chan->cdr) from here. */
                                }
                        }
                        break;
@@ -2755,9 +2743,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
                        chan->hangupcause = cause;
                if (chan->generator)
                        ast_deactivate_generator(chan);
-               /* End the CDR if appropriate */
-               if (chan->cdr)
-                       ast_cdr_end(chan->cdr);
+               /* We no longer End the CDR here */
        }
 
        /* High bit prints debugging */
@@ -3329,15 +3315,6 @@ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *d
        }
        ast_set_callerid(chan, cid_num, cid_name, cid_num);
 
-       
-
-       if (!chan->cdr) { /* up till now, this insertion hasn't been done. Therefore,
-                               to keep from throwing off the basic order of the universe,
-                               we will try to keep this cdr from getting posted. */
-               chan->cdr = ast_cdr_alloc();
-               ast_cdr_init(chan->cdr, chan);
-               ast_cdr_start(chan->cdr);
-       }
        if (ast_call(chan, data, 0)) {  /* ast_call failed... */
                ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
        } else {
@@ -4089,8 +4066,6 @@ void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char
                        ast_free(chan->cid.cid_ani);
                chan->cid.cid_ani = ast_strdup(cid_ani);
        }
-       if (chan->cdr)
-               ast_cdr_setcid(chan->cdr, chan);
        manager_event(EVENT_FLAG_CALL, "NewCallerid",
                                "Channel: %s\r\n"
                                "CallerIDNum: %s\r\n"
index ccd182d..f150f56 100644 (file)
@@ -308,15 +308,6 @@ static void *ast_bridge_call_thread(void *data)
        tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge";
        tobj->peer->data = tobj->chan->name;
 
-       if (tobj->chan->cdr) {
-               ast_cdr_reset(tobj->chan->cdr, NULL);
-               ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name);
-       }
-       if (tobj->peer->cdr) {
-               ast_cdr_reset(tobj->peer->cdr, NULL);
-               ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name);
-       }
-
        ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig);
 
        if (tobj->return_to_pbx) {
@@ -1889,13 +1880,6 @@ static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *call
                ast_string_field_set(chan, language, language);
                ast_channel_inherit_variables(caller, chan);    
                pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
-               if (!chan->cdr) {
-                       chan->cdr=ast_cdr_alloc();
-                       if (chan->cdr) {
-                               ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */
-                               ast_cdr_start(chan->cdr);
-                       }
-               }
                        
                if (!ast_call(chan, data, timeout)) {
                        struct timeval started;
@@ -2042,23 +2026,6 @@ static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *call
        if (outstate)
                *outstate = state;
 
-       if (chan && res <= 0) {
-               if (chan->cdr || (chan->cdr = ast_cdr_alloc())) {
-                       char tmp[256];
-                       ast_cdr_init(chan->cdr, chan);
-                       snprintf(tmp, 256, "%s/%s", type, (char *)data);
-                       ast_cdr_setapp(chan->cdr,"Dial",tmp);
-                       ast_cdr_update(chan);
-                       ast_cdr_start(chan->cdr);
-                       ast_cdr_end(chan->cdr);
-                       /* If the cause wasn't handled properly */
-                       if (ast_cdr_disposition(chan->cdr,chan->hangupcause))
-                               ast_cdr_failed(chan->cdr);
-               } else {
-                       ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
-               }
-       }
-       
        return chan;
 }
 
@@ -2079,13 +2046,15 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
        struct ast_channel *who;
        char chan_featurecode[FEATURE_MAX_LEN + 1]="";
        char peer_featurecode[FEATURE_MAX_LEN + 1]="";
+       char orig_channame[AST_MAX_EXTENSION];
+       char orig_peername[AST_MAX_EXTENSION];
        int res;
        int diff;
        int hasfeatures=0;
        int hadfeatures=0;
        struct ast_option_header *aoh;
        struct ast_bridge_config backup_config;
-       struct ast_cdr *bridge_cdr;
+       struct ast_cdr *bridge_cdr = NULL;
 
        memset(&backup_config, 0, sizeof(backup_config));
 
@@ -2120,25 +2089,49 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
        /* Answer if need be */
        if (ast_answer(chan))
                return -1;
-       peer->appl = "Bridged Call";
-       peer->data = chan->name;
-
-       /* copy the userfield from the B-leg to A-leg if applicable */
-       if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) {
-               char tmp[256];
-               if (!ast_strlen_zero(chan->cdr->userfield)) {
-                       snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield);
-                       ast_cdr_appenduserfield(chan, tmp);
-               } else
-                       ast_cdr_setuserfield(chan, peer->cdr->userfield);
-               /* free the peer's cdr without ast_cdr_free complaining */
-               ast_free(peer->cdr);
-               peer->cdr = NULL;
-       }
 
+       ast_copy_string(orig_channame,chan->name,sizeof(orig_channame));
+       ast_copy_string(orig_peername,peer->name,sizeof(orig_peername));
+       
+       if (!chan->cdr || (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED))) {
+               
+               if (chan->cdr) {
+                       ast_set_flag(chan->cdr, AST_CDR_FLAG_MAIN);
+                       ast_cdr_update(chan);
+                       bridge_cdr = ast_cdr_dup(chan->cdr);
+                       ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
+                       ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
+               } else {
+                       /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */
+                       bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */
+                       ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel));
+                       ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel));
+                       ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid));
+                       ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp));
+                       ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata));
+                       ast_cdr_setcid(bridge_cdr, chan);
+                       bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
+                       bridge_cdr->amaflags = chan->amaflags ? chan->amaflags :  ast_default_amaflags;
+                       ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode));
+                       /* Destination information */
+                       ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst));
+                       ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext));
+                       if (peer->cdr) {
+                               bridge_cdr->start = peer->cdr->start;
+                               ast_copy_string(bridge_cdr->userfield, peer->cdr->userfield, sizeof(bridge_cdr->userfield));
+                       } else {
+                               ast_cdr_start(bridge_cdr);
+                       }
+               }
+               ast_cdr_answer(bridge_cdr);
+               ast_cdr_answer(chan->cdr); /* for the sake of cli status checks */
+               ast_set_flag(chan->cdr, AST_CDR_FLAG_BRIDGED);
+               if (peer->cdr)
+                       ast_set_flag(peer->cdr, AST_CDR_FLAG_BRIDGED);
+       }
        for (;;) {
                struct ast_channel *other;      /* used later */
-
+               
                res = ast_channel_bridge(chan, peer, config, &f, &who);
 
                if (config->feature_timer) {
@@ -2297,67 +2290,18 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                        ast_frfree(f);
 
        }
-       /* arrange the cdrs */
-       bridge_cdr = ast_cdr_alloc();
-       if (bridge_cdr) {
-               if (chan->cdr && peer->cdr) { /* both of them? merge */
-                       ast_channel_lock(chan); /* lock the channel before modifying cdrs */
-                       ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the  destination as a base, but, really, it's random */
-                       ast_cdr_start(bridge_cdr); /* now is the time to start */
-                       
-                       /* absorb the channel cdr */
-                       ast_cdr_merge(bridge_cdr, chan->cdr);
-                       if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
-                               ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
-                       
-                       chan->cdr = NULL;
-                       ast_channel_unlock(chan);
-                       /* absorb the peer cdr */
-                       ast_channel_lock(peer);
-                       ast_cdr_merge(bridge_cdr, peer->cdr);
-                       if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
-                               ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */
-                       
-                       peer->cdr = NULL; /* remove pointer to freed memory before releasing the lock */
-                       ast_channel_unlock(peer);
-
-                       ast_channel_lock(chan);
-                       chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
-                       ast_channel_unlock(chan);
-               } else if (chan->cdr) {
-                       ast_channel_lock(chan); /* Lock before modifying CDR */
-                       /* take the cdr from the channel - literally */
-                       ast_cdr_init(bridge_cdr,chan);
-                       /* absorb this data */
-                       ast_cdr_merge(bridge_cdr, chan->cdr);
-                       if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED))
-                               ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
-                       chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
-                       ast_channel_unlock(chan);
-               } else if (peer->cdr) {
-                       ast_channel_lock(peer); /* Lock before modifying CDR */
-                       /* take the cdr from the peer - literally */
-                       ast_cdr_init(bridge_cdr,peer);
-                       /* absorb this data */
-                       ast_cdr_merge(bridge_cdr, peer->cdr);
-                       if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED))
-                               ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */
-                       peer->cdr = NULL;
-                       peer->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
-                       ast_channel_unlock(peer);
-               } else {
-                       ast_channel_lock(chan); /* Lock before modifying CDR */
-                       /* make up a new cdr */
-                       ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
-                       chan->cdr = bridge_cdr; /*  */
-                       ast_channel_unlock(chan);
-               }
-               if (ast_strlen_zero(bridge_cdr->dstchannel)) {
-                       if (strcmp(bridge_cdr->channel, peer->name) != 0)
-                               ast_cdr_setdestchan(bridge_cdr, peer->name);
-                       else
-                               ast_cdr_setdestchan(bridge_cdr, chan->name);
-               }
+       /* obey the NoCDR() wishes. */
+       if (!chan->cdr || (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED))) {
+               
+               ast_cdr_end(bridge_cdr);
+               
+               ast_cdr_detach(bridge_cdr);
+               
+               /* just in case, these channels get bridged again before hangup */
+               if (chan->cdr)
+                       ast_cdr_specialized_reset(chan->cdr,0);
+               if (peer->cdr)
+                       ast_cdr_specialized_reset(peer->cdr,0);
        }
        return res;
 }
index a0ba3a9..5b7e3bd 100644 (file)
@@ -3475,17 +3475,6 @@ static int __ast_pbx_run(struct ast_channel *c)
        }
        if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
                return -1;
-       if (c->amaflags) {
-               if (!c->cdr) {
-                       c->cdr = ast_cdr_alloc();
-                       if (!c->cdr) {
-                               ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
-                               ast_free(c->pbx);
-                               return -1;
-                       }
-                       ast_cdr_init(c->cdr, c);
-               }
-       }
        /* Set reasonable defaults */
        c->pbx->rtimeoutms = 10000;
        c->pbx->dtimeoutms = 5000;
@@ -3508,8 +3497,6 @@ static int __ast_pbx_run(struct ast_channel *c)
                        ast_copy_string(c->context, "default", sizeof(c->context));
                }
        }
-       if (c->cdr && ast_tvzero(c->cdr->start))
-               ast_cdr_start(c->cdr);
        for (;;) {
                char dst_exten[256];    /* buffer to accumulate digits */
                int pos = 0;            /* XXX should check bounds */
@@ -3691,8 +3678,6 @@ static int __ast_pbx_run(struct ast_channel *c)
        if (res != AST_PBX_KEEPALIVE)
                ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING);
        if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
-               if (c->cdr && ast_opt_end_cdr_before_h_exten)
-                       ast_cdr_end(c->cdr);
                set_ext_pri(c, "h", 1);
                while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) {
                        c->priority++;
@@ -6989,18 +6974,6 @@ int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout,
        if (sync) {
                chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
                if (chan) {
-                       if (!chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
-                               chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
-                               if (!chan->cdr) {
-                                       /* allocation of the cdr failed */
-                                       ast_free(chan->pbx);
-                                       res = -1;
-                                       goto outgoing_app_cleanup;
-                               }
-                               /* allocation of the cdr was successful */
-                               ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
-                               ast_cdr_start(chan->cdr);
-                       }
                        ast_set_variables(chan, vars);
                        if (account)
                                ast_cdr_setaccount(chan, account);
@@ -8375,7 +8348,6 @@ static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string,
        else
                ast_explicit_goto(chan, context, exten, ipri);
        
-       ast_cdr_update(chan);
        return 0;
 
 }