Merged revisions 60989 via svnmerge from
authorSteve Murphy <murf@digium.com>
Tue, 10 Apr 2007 05:41:34 +0000 (05:41 +0000)
committerSteve Murphy <murf@digium.com>
Tue, 10 Apr 2007 05:41:34 +0000 (05:41 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r60989 | murf | 2007-04-09 12:32:07 -0600 (Mon, 09 Apr 2007) | 1 line

This is a big improvement over the current CDR fixes. It may still need refinement, but this won't have as many folks bothered.
This also adds the mods from 1.4/r.61136;
........

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

23 files changed:
apps/app_cdr.c
apps/app_voicemail.c
channels/chan_agent.c
channels/chan_alsa.c
channels/chan_features.c
channels/chan_gtalk.c
channels/chan_h323.c
channels/chan_iax2.c
channels/chan_local.c
channels/chan_mgcp.c
channels/chan_misdn.c
channels/chan_nbs.c
channels/chan_oss.c
channels/chan_phone.c
channels/chan_sip.c
channels/chan_skinny.c
channels/chan_vpb.cc
channels/chan_zap.c
include/asterisk/channel.h
main/cdr.c
main/channel.c
main/pbx.c
res/res_features.c

index 60e48d7..c0d88fb 100644 (file)
@@ -51,8 +51,7 @@ static int nocdr_exec(struct ast_channel *chan, void *data)
        u = ast_module_user_add(chan);
 
        if (chan->cdr) {
-               ast_cdr_free(chan->cdr);
-               chan->cdr = NULL;
+               ast_set_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED);
        }
 
        ast_module_user_remove(u);
index b603f36..668915e 100644 (file)
@@ -1914,7 +1914,7 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
 
        if (!ast_strlen_zero(fromstring)) {
                struct ast_channel *ast;
-               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
                        char *passdata;
                        int vmlen = strlen(fromstring)*3 + 200;
                        if ((passdata = alloca(vmlen))) {
@@ -1936,7 +1936,7 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
        fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata), vmu->email);
        if (!ast_strlen_zero(emailsubject)) {
                struct ast_channel *ast;
-               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
                        char *passdata;
                        int vmlen = strlen(emailsubject) * 3 + 200;
                        if ((passdata = alloca(vmlen))) {
@@ -1990,7 +1990,7 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
        fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
        if (emailbody) {
                struct ast_channel *ast;
-               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
                        char *passdata;
                        int vmlen = strlen(emailbody)*3 + 200;
                        if ((passdata = alloca(vmlen))) {
@@ -2109,7 +2109,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
 
        if (*pagerfromstring) {
                struct ast_channel *ast;
-               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
                        char *passdata;
                        int vmlen = strlen(fromstring)*3 + 200;
                        if ((passdata = alloca(vmlen))) {
@@ -2127,7 +2127,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
        fprintf(p, "To: %s\n", pager);
        if (pagersubject) {
                struct ast_channel *ast;
-               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
                        char *passdata;
                        int vmlen = strlen(pagersubject) * 3 + 200;
                        if ((passdata = alloca(vmlen))) {
@@ -2146,7 +2146,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
        strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
        if (pagerbody) {
                struct ast_channel *ast;
-               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0))) {
+               if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
                        char *passdata;
                        int vmlen = strlen(pagerbody)*3 + 200;
                        if ((passdata = alloca(vmlen))) {
index 26f8ca5..50b3666 100644 (file)
@@ -918,9 +918,9 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state)
        }
 #endif 
        if (p->pending)
-               tmp = ast_channel_alloc(0, state, 0, 0, "Agent/P%s-%d", p->agent, ast_random() & 0xffff);
+               tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? p->chan->exten:"", p->chan ? p->chan->context:"", 0, "Agent/P%s-%d", p->agent, ast_random() & 0xffff);
        else
-               tmp = ast_channel_alloc(0, state, 0, 0, "Agent/%s", p->agent);
+               tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? p->chan->exten:"", p->chan ? p->chan->context:"", 0, "Agent/%s", p->agent);
        if (!tmp) {
                ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n");
                return NULL;
index 2be93ef..aa444c5 100644 (file)
@@ -790,7 +790,7 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state)
 {
        struct ast_channel *tmp = NULL;
 
-       if (!(tmp = ast_channel_alloc(1, state, 0, 0, "ALSA/%s", indevname)))
+       if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "ALSA/%s", indevname)))
                return NULL;
 
        tmp->tech = &alsa_tech;
index 2fb7207..0979270 100644 (file)
@@ -472,7 +472,7 @@ static struct ast_channel *features_new(struct feature_pvt *p, int state, int in
                if (y >= 3)
                        break;
        }
-       tmp = ast_channel_alloc(0, state, 0,0, b2);
+       tmp = ast_channel_alloc(0, state, 0,0, "", "", "", 0, b2);
        /* free up the name, it was copied into the channel name */
        if (b2)
                free(b2);
index bab6f92..8c4a27b 100644 (file)
@@ -904,7 +904,7 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
                n2 = title;
        else
                n2 = i->us;
-       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "Gtalk/%s-%04lx", n2, ast_random() & 0xffff);
+       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, client->accountcode, i->exten, client->context, client->amaflags, "Gtalk/%s-%04lx", n2, ast_random() & 0xffff);
        if (!tmp) {
                ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n");
                return NULL;
index 6ab4ab5..70725ac 100644 (file)
@@ -1024,7 +1024,7 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c
        
        /* Don't hold a oh323_pvt lock while we allocate a chanel */
        ast_mutex_unlock(&pvt->lock);
-       ch = ast_channel_alloc(1, state, cid_num, cid_name, "H323/%s", host);
+       ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, pvt->amaflags, "H323/%s", host);
        /* Update usage counter */
        ast_module_ref(ast_module_info->self);
        ast_mutex_lock(&pvt->lock);
index 2fa322f..88e1ae5 100644 (file)
@@ -3377,7 +3377,7 @@ static struct ast_channel *ast_iax2_new(int callno, int state, int capability)
 
        /* Don't hold call lock */
        ast_mutex_unlock(&iaxsl[callno]);
-       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "IAX2/%s-%d", i->host, i->callno);
+       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "IAX2/%s-%d", i->host, i->callno);
        ast_mutex_lock(&iaxsl[callno]);
        if (!tmp)
                return NULL;
@@ -6220,8 +6220,8 @@ static int iax_park(struct ast_channel *chan1, struct ast_channel *chan2)
        struct iax_dual *d;
        struct ast_channel *chan1m, *chan2m;
        pthread_t th;
-       chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "Parking/%s", chan1->name);
-       chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "IAXPeer/%s",chan2->name);
+       chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
+       chan2m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "IAXPeer/%s",chan2->name);
        if (chan2m && chan1m) {
                /* Make formats okay */
                chan1m->readformat = chan1->readformat;
index 265d685..15a38a6 100644 (file)
@@ -584,8 +584,8 @@ static struct ast_channel *local_new(struct local_pvt *p, int state)
        int randnum = ast_random() & 0xffff, fmt = 0;
 
        /* Allocate two new Asterisk channels */
-       if (!(tmp = ast_channel_alloc(1, state, 0, 0, "Local/%s@%s-%04x,1", p->exten, p->context, randnum)) 
-                       || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, "Local/%s@%s-%04x,2", p->exten, p->context, randnum))) {
+       if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "Local/%s@%s-%04x,1", p->exten, p->context, randnum)) 
+                       || !(tmp2 = ast_channel_alloc(1, AST_STATE_RING, 0, 0, "", p->exten, p->context, 0, "Local/%s@%s-%04x,2", p->exten, p->context, randnum))) {
                if (tmp)
                        ast_channel_free(tmp);
                if (tmp2)
index acabdc7..27ca268 100644 (file)
@@ -1433,7 +1433,7 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
        struct mgcp_endpoint *i = sub->parent;
        int fmt;
 
-       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
+       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
        if (tmp) {
                tmp->tech = &mgcp_tech;
                tmp->nativeformats = i->capability;
index fa13d03..37aec62 100644 (file)
@@ -3167,7 +3167,7 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char
        if (callerid) 
                ast_callerid_parse(callerid, &cid_name, &cid_num);
 
-       tmp = ast_channel_alloc(1, state, cid_num, cid_name, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
+       tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
        
        if (tmp) {
                chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
index 0e9a329..2cb912e 100644 (file)
@@ -233,7 +233,7 @@ static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame)
 static struct ast_channel *nbs_new(struct nbs_pvt *i, int state)
 {
        struct ast_channel *tmp;
-       tmp = ast_channel_alloc(1, state, 0, 0, "NBS/%s", i->stream);
+       tmp = ast_channel_alloc(1, state, 0, 0, "", "s", context, 0, "NBS/%s", i->stream);
        if (tmp) {
                tmp->tech = &nbs_tech;
                tmp->fds[0] = nbs_fd(i->nbs);
index d6757a6..d734496 100644 (file)
@@ -1021,7 +1021,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
 {
        struct ast_channel *c;
 
-       c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "OSS/%s", o->device + 5);
+       c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", o->ext, o->ctx, 0, "OSS/%s", o->device + 5);
        if (c == NULL)
                return NULL;
        c->tech = &oss_tech;
@@ -1033,10 +1033,6 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
        c->writeformat = AST_FORMAT_SLINEAR;
        c->tech_pvt = o;
 
-       if (!ast_strlen_zero(ctx))
-               ast_copy_string(c->context, ctx, sizeof(c->context));
-       if (!ast_strlen_zero(ext))
-               ast_copy_string(c->exten, ext, sizeof(c->exten));
        if (!ast_strlen_zero(o->language))
                ast_string_field_set(c, language, o->language);
        /* Don't use ast_set_callerid() here because it will
index 8312fab..76311fc 100644 (file)
@@ -865,7 +865,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
 {
        struct ast_channel *tmp;
        struct phone_codec_data codec;
-       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "Phone/%s", i->dev + 5);
+       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, 0, "Phone/%s", i->dev + 5);
        if (tmp) {
                tmp->tech = cur_tech;
                tmp->fds[0] = i->fd;
index 5c3cac5..dd36327 100644 (file)
@@ -4091,8 +4091,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
 
                sip_pvt_unlock(i);
                /* Don't hold a sip pvt lock while we allocate a channel */
-
-               tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "SIP/%s-%08x", my_name, (int)(long) i);
+               tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "SIP/%s-%08x", my_name, (int)(long) i);
 
        }
        if (!tmp) {
@@ -4207,6 +4206,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
        ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
        ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
 
+
        /* Don't use ast_set_callerid() here because it will
         * generate an unnecessary NewCallerID event  */
        tmp->cid.cid_num = ast_strdup(i->cid_num);
@@ -13302,8 +13302,8 @@ static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct
                /* Chan2m: The transferer, chan1m: The transferee */
        pthread_t th;
 
-       transferee = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "Parking/%s", chan1->name);
-       transferer = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "SIPPeer/%s", chan2->name);
+       transferee = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan1->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name);
+       transferer = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "SIPPeer/%s", chan2->name);
        if ((!transferer) || (!transferee)) {
                if (transferee) {
                        transferee->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
@@ -14116,7 +14116,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                        /* Initialize our tag */        
 
                        make_our_tag(p->tag, sizeof(p->tag));
-
                        /* First invitation - create the channel */
                        c = sip_new(p, AST_STATE_DOWN, S_OR(p->username, NULL));
                        *recount = 1;
index 8d88f85..f06db4d 100644 (file)
@@ -2810,7 +2810,7 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state)
        struct skinny_device *d = l->parent;
        int fmt;
 
-       tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, "Skinny/%s@%s-%d", l->name, d->name, callnums);
+       tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums);
        if (!tmp) {
                ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
                return NULL;
index e85500b..ddee75d 100644 (file)
@@ -2626,7 +2626,7 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
        if (option_verbose > 3)
                ast_verbose("%s: New call for context [%s]\n",me->dev,context);
            
-       tmp = ast_channel_alloc(1, state, 0, 0, me->dev);
+       tmp = ast_channel_alloc(1, state, 0, 0, "", me->exten, me->context, 0, me->dev);
        if (tmp) {
                if (use_ast_ind == 1){
                        tmp->tech = &vpb_tech_indicate;
index 6479311..0aa37a8 100644 (file)
@@ -5520,7 +5520,7 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
                }
                y++;
        } while (x < 3);
-       tmp = ast_channel_alloc(0, state, 0, 0, b2);
+       tmp = ast_channel_alloc(0, state, 0, 0, i->accountcode, i->exten, i->context, i->amaflags, b2);
        if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
                free(b2);
        if (!tmp)
index 1f7f393..6fa71ad 100644 (file)
@@ -633,7 +633,7 @@ int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
        by default set to the "default" context and
        extension "s"
  */
-struct ast_channel *ast_channel_alloc(int needalertpipe, int state, const char *cid_num, const char *cid_name, const char *name_fmt, ...);
+struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt, ...);
 
 /*! \brief Queue an outgoing frame */
 int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f);
index be23852..7703e35 100644 (file)
@@ -77,7 +77,7 @@ static struct ast_cdr_batch {
        int size;
        struct ast_cdr_batch_item *head;
        struct ast_cdr_batch_item *tail;
-} *batch;
+} *batch = NULL;
 
 static struct sched_context *sched;
 static int cdr_sched = -1;
@@ -474,31 +474,80 @@ struct ast_cdr *ast_cdr_alloc(void)
        return x;
 }
 
+static void cdr_merge_vars(struct ast_cdr *to, struct ast_cdr *from)
+{
+       struct ast_var_t *variablesfrom,*variablesto;
+       struct varshead *headpfrom = &to->varshead;
+       struct varshead *headpto = &from->varshead;
+       AST_LIST_TRAVERSE_SAFE_BEGIN(headpfrom, variablesfrom, entries) {
+               /* for every var in from, stick it in to */
+               const char *fromvarname, *fromvarval;
+               const char *tovarname, *tovarval;
+               fromvarname = ast_var_name(variablesfrom);
+               fromvarval = ast_var_value(variablesfrom);
+               tovarname = 0;
+
+               /* now, quick see if that var is in the 'to' cdr already */
+               AST_LIST_TRAVERSE(headpto, variablesto, entries) {
+
+                       /* now, quick see if that var is in the 'to' cdr already */
+                       if ( strcasecmp(fromvarname, ast_var_name(variablesto)) == 0 ) {
+                               tovarname = ast_var_name(variablesto);
+                               tovarval = ast_var_value(variablesto);
+                               break;
+                       }
+               }
+               if (tovarname && strcasecmp(fromvarval,tovarval) != 0) {  /* this message here to see how irritating the userbase finds it */
+                       ast_log(LOG_NOTICE, "Merging CDR's: variable %s value %s dropped in favor of value %s\n", tovarname, fromvarval, tovarval);
+                       continue;
+               } else if (tovarname && strcasecmp(fromvarval,tovarval) == 0) /* if they are the same, the job is done */
+                       continue;
+
+               /*rip this var out of the from cdr, and stick it in the to cdr */
+               AST_LIST_REMOVE_CURRENT(headpfrom, entries);
+               AST_LIST_INSERT_HEAD(headpto, variablesfrom, entries);
+       }
+       AST_LIST_TRAVERSE_SAFE_END;
+}
+
 void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from)
 {
        if (!to || !from)
                return;
+       
        if (!ast_tvzero(from->start)) {
                if (!ast_tvzero(to->start)) {
                        if (ast_tvcmp(to->start, from->start) > 0 ) {
                                to->start = from->start; /* use the earliest time */
                                from->start = ast_tv(0,0); /* we actively "steal" these values */
-                       } else {
-                               ast_log(LOG_WARNING,"CDR start disagreement for %s\n", to->channel);
                        }
+                       /* else nothing to do */
                } else {
                        to->start = from->start;
                        from->start = ast_tv(0,0); /* we actively "steal" these values */
                }
        }
+       if (!ast_tvzero(from->answer)) {
+               if (!ast_tvzero(to->answer)) {
+                       if (ast_tvcmp(to->answer, from->answer) > 0 ) {
+                               to->answer = from->answer; /* use the earliest time */
+                               from->answer = ast_tv(0,0); /* we actively "steal" these values */
+                       }
+                       /* we got the earliest answer time, so we'll settle for that? */
+               } else {
+                       to->answer = from->answer;
+                       from->answer = ast_tv(0,0); /* we actively "steal" these values */
+               }
+       }
        if (!ast_tvzero(from->end)) {
                if (!ast_tvzero(to->end)) {
                        if (ast_tvcmp(to->end, from->end) < 0 ) {
                                to->end = from->end; /* use the latest time */
                                from->end = ast_tv(0,0); /* we actively "steal" these values */
-                       } else {
-                               ast_log(LOG_WARNING,"CDR end disagreement for %s\n", to->channel);
+                               to->duration = to->end.tv_sec - to->start.tv_sec;  /* don't forget to update the duration, billsec, when we set end */
+                               to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec;
                        }
+                       /* else, nothing to do */
                } else {
                        to->end = from->end;
                        from->end = ast_tv(0,0); /* we actively "steal" these values */
@@ -506,19 +555,6 @@ void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from)
                        to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec;
                }
        }
-       if (!ast_tvzero(from->answer)) {
-               if (!ast_tvzero(to->answer)) {
-                       if (ast_tvcmp(to->answer, from->answer) > 0 ) {
-                               to->answer = from->answer; /* use the earliest time */
-                               from->answer = ast_tv(0,0); /* we actively "steal" these values */
-                       } else {
-                               ast_log(LOG_WARNING,"CDR answer disagreement for %s\n", to->channel);
-                       }
-               } else {
-                       to->answer = from->answer;
-                       from->answer = ast_tv(0,0); /* we actively "steal" these values */
-               }
-       }
        if (to->disposition < from->disposition) {
                to->disposition = from->disposition;
                from->disposition = AST_CDR_NOANSWER;
@@ -564,6 +600,18 @@ void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from)
                from->userfield[0] = 0; /* theft */
        }
        /* flags, varsead, ? */
+       cdr_merge_vars(from, to);
+
+       if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS))
+               ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS);
+       if (ast_test_flag(from, AST_CDR_FLAG_POSTED))
+               ast_set_flag(to, AST_CDR_FLAG_POSTED);
+       if (ast_test_flag(from, AST_CDR_FLAG_LOCKED))
+               ast_set_flag(to, AST_CDR_FLAG_LOCKED);
+       if (ast_test_flag(from, AST_CDR_FLAG_CHILD))
+               ast_set_flag(to, AST_CDR_FLAG_CHILD);
+       if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED))
+               ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED);
 }
 
 void ast_cdr_start(struct ast_cdr *cdr)
index 998843d..87be422 100644 (file)
@@ -620,7 +620,7 @@ static const struct ast_channel_tech null_tech = {
 };
 
 /*! \brief Create a new channel structure */
-struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *name_fmt, ...)
+struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const int amaflag, const char *name_fmt, ...)
 {
        struct ast_channel *tmp;
        int x;
@@ -733,6 +733,30 @@ struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_
        }
 
        /* Reminder for the future: under what conditions do we NOT want to track cdrs on channels? */
+
+       /* These 4 variables need to be set up for the cdr_init() to work right */
+       if (amaflag)
+               tmp->amaflags = amaflag;
+       else
+               tmp->amaflags = ast_default_amaflags;
+       
+       if (!ast_strlen_zero(acctcode))
+               ast_string_field_set(tmp, accountcode, acctcode);
+       else
+               ast_string_field_set(tmp, accountcode, ast_default_accountcode);
+               
+       if (!ast_strlen_zero(context))
+               ast_copy_string(tmp->context, context, sizeof(tmp->context));
+       else
+               strcpy(tmp->context, "default");
+
+       if (!ast_strlen_zero(exten))
+               ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
+       else
+               strcpy(tmp->exten, "s");
+
+       tmp->priority = 1;
+               
        tmp->cdr = ast_cdr_alloc();
        ast_cdr_init(tmp->cdr, tmp);
        ast_cdr_start(tmp->cdr);
@@ -744,13 +768,7 @@ struct ast_channel *ast_channel_alloc(int needqueue, int state, const char *cid_
        
        AST_LIST_HEAD_INIT_NOLOCK(&tmp->datastores);
        
-       strcpy(tmp->context, "default");
-       strcpy(tmp->exten, "s");
-       tmp->priority = 1;
-       
        ast_string_field_set(tmp, language, defaultlanguage);
-       tmp->amaflags = ast_default_amaflags;
-       ast_string_field_set(tmp, accountcode, ast_default_accountcode);
 
        tmp->tech = &null_tech;
 
index 2ce7605..ef95678 100644 (file)
@@ -4573,7 +4573,7 @@ int ast_async_goto(struct ast_channel *chan, const char *context, const char *ex
                /* In order to do it when the channel doesn't really exist within
                   the PBX, we have to make a new channel, masquerade, and start the PBX
                   at the new location */
-               struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, "AsyncGoto/%s", chan->name);
+               struct ast_channel *tmpchan = ast_channel_alloc(0, chan->_state, 0, 0, chan->accountcode, chan->exten, chan->context, chan->amaflags, "AsyncGoto/%s", chan->name);
                if (chan->cdr) {
                        tmpchan->cdr = ast_cdr_dup(chan->cdr);
                }
@@ -4934,7 +4934,7 @@ static void *async_wait(void *data)
 static int ast_pbx_outgoing_cdr_failed(void)
 {
        /* allocate a channel */
-       struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, 0);
+       struct ast_channel *chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0);
 
        if (!chan)
                return -1;  /* failure */
@@ -5053,7 +5053,7 @@ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout
                        /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
                        /* check if "failed" exists */
                        if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
-                               chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "OutgoingSpoolFailed");
+                               chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "OutgoingSpoolFailed");
                                if (chan) {
                                        if (!ast_strlen_zero(context))
                                                ast_copy_string(chan->context, context, sizeof(chan->context));
index 60b2f03..18e2218 100644 (file)
@@ -194,7 +194,7 @@ static void check_goto_on_transfer(struct ast_channel *chan)
 
        goto_on_transfer = ast_strdupa(val);
 
-       if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan->name)))
+       if (!(xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, chan->name)))
                return;
 
        for (x = goto_on_transfer; x && *x; x++) {
@@ -445,7 +445,7 @@ int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int
        struct ast_frame *f;
 
        /* Make a new, fake channel that we'll use to masquerade in the real one */
-       if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "Parked/%s",rchan->name))) {
+       if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
                ast_log(LOG_WARNING, "Unable to create parked channel\n");
                return -1;
        }
@@ -840,7 +840,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
                return -1;
        }
 
-       xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "Transfered/%s", transferee->name);
+       xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
        if (!xferchan) {
                ast_hangup(newchan);
                return -1;
@@ -1373,81 +1373,6 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                peer->cdr = NULL;
        }
 
-       /* arrange the cdrs */
-       bridge_cdr = ast_cdr_alloc();
-       if (bridge_cdr) {
-               if (chan->cdr && peer->cdr) { /* both of them? merge */
-                       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);
-                       ast_cdr_discard(chan->cdr); /* no posting these guys */
-                       chan->cdr = NULL;
-                       
-                       /* absorb the peer cdr */
-                       ast_cdr_merge(bridge_cdr, peer->cdr);
-                       ast_cdr_discard(peer->cdr); /* no posting these guys */
-                       peer->cdr = NULL;
-               } else if (chan->cdr) {
-                       /* take the cdr from the channel - literally */
-                       ast_cdr_init(bridge_cdr,chan);
-                       if (chan->cdr->disposition!=AST_CDR_ANSWERED) {
-                               ast_cdr_end(chan->cdr);
-                               ast_cdr_detach(chan->cdr); /* post the existing cdr, we will be starting a fresh new cdr presently */
-                               chan->cdr = ast_cdr_alloc();
-                               if (chan->cdr) {
-                                       ast_cdr_init(chan->cdr,chan); /* a fresh new one its place */
-                                       ast_cdr_start(chan->cdr); /* now is the time to start */
-                               }
-                       } else {
-                               /* absorb this data */
-                               ast_cdr_merge(bridge_cdr, chan->cdr);
-                               ast_cdr_discard(chan->cdr); /* no posting these guys */
-                               chan->cdr = NULL;
-                       }
-                       peer->cdr = ast_cdr_alloc();
-                       if (peer->cdr)
-                               ast_cdr_init(peer->cdr, peer);
-               } else if (peer->cdr) {
-                       /* take the cdr from the peer - literally */
-                       ast_cdr_init(bridge_cdr,peer);
-                       if (peer->cdr->disposition != AST_CDR_ANSWERED) {
-                               ast_cdr_end(peer->cdr);
-                               ast_cdr_detach(peer->cdr); /* post the existing cdr, we will be starting a fresh new cdr presently */
-                               peer->cdr = ast_cdr_alloc();
-                               if (peer->cdr) {
-                                       ast_cdr_init(peer->cdr,peer); /* a fresh new one its place */
-                                       ast_cdr_start(peer->cdr); /* now is the time to start */
-                               }
-                       } else {
-                               /* absorb this data */
-                               ast_cdr_merge(bridge_cdr, chan->cdr);
-                               ast_cdr_discard(chan->cdr); /* no posting these guys */
-                               chan->cdr = NULL;
-                       }
-                       chan->cdr = ast_cdr_alloc();
-                       if (chan->cdr)
-                               ast_cdr_init(chan->cdr, chan);
-               } else {
-                       /* make up a new cdr */
-                       ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
-                       chan->cdr = ast_cdr_alloc();
-                       if (chan->cdr) {
-                               ast_cdr_init(chan->cdr, chan);
-                       }
-                       peer->cdr = ast_cdr_alloc();
-                       if (chan->cdr) {
-                               ast_cdr_init(peer->cdr, peer);
-                               ast_cdr_start(peer->cdr); /* now is the time to start */
-                       }
-               }
-               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);
-               }
-       }
        for (;;) {
                struct ast_channel *other;      /* used later */
 
@@ -1514,19 +1439,6 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                }
                if (res < 0) {
                        ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
-                       /* whoa!! don't go running off without cleaning up your mess! */
-                       if (bridge_cdr) {
-                               ast_cdr_merge(bridge_cdr,chan->cdr);
-                               ast_cdr_merge(bridge_cdr,peer->cdr);
-                               ast_cdr_failed(bridge_cdr);
-                               ast_cdr_end(bridge_cdr);
-                               ast_cdr_detach(bridge_cdr);
-                               bridge_cdr = NULL;
-                       }
-                       ast_cdr_free(chan->cdr); /* no posting these guys */
-                       ast_cdr_free(peer->cdr);
-                       chan->cdr = NULL;
-                       peer->cdr = NULL;
                        return -1;
                }
                
@@ -1615,20 +1527,51 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                }
                if (f)
                        ast_frfree(f);
+
        }
-       /* before leaving, post the cdr we accumulated */
-       /* whoa!! don't go running off without cleaning up your mess! */
+       /* arrange the cdrs */
+       bridge_cdr = ast_cdr_alloc();
        if (bridge_cdr) {
-               ast_cdr_merge(bridge_cdr,chan->cdr);
-               ast_cdr_merge(bridge_cdr,peer->cdr);
-               ast_cdr_end(bridge_cdr);
-               ast_cdr_detach(bridge_cdr);
-               bridge_cdr = NULL;
-       }
-       ast_cdr_discard(chan->cdr); /* no posting these guys */
-       ast_cdr_discard(peer->cdr);
-       chan->cdr = NULL;
-       peer->cdr = NULL;
+               if (chan->cdr && peer->cdr) { /* both of them? merge */
+                       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);
+                       ast_cdr_discard(chan->cdr); /* no posting these guys */
+                       
+                       /* absorb the peer cdr */
+                       ast_cdr_merge(bridge_cdr, peer->cdr);
+                       ast_cdr_discard(peer->cdr); /* no posting these guys */
+                       peer->cdr = NULL;
+                       chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
+               } else if (chan->cdr) {
+                       /* take the cdr from the channel - literally */
+                       ast_cdr_init(bridge_cdr,chan);
+                       /* absorb this data */
+                       ast_cdr_merge(bridge_cdr, chan->cdr);
+                       ast_cdr_discard(chan->cdr); /* no posting these guys */
+                       chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */
+               } else if (peer->cdr) {
+                       /* take the cdr from the peer - literally */
+                       ast_cdr_init(bridge_cdr,peer);
+                       /* absorb this data */
+                       ast_cdr_merge(bridge_cdr, peer->cdr);
+                       ast_cdr_discard(peer->cdr); /* no posting these guys */
+                       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 */
+               } else {
+                       /* make up a new cdr */
+                       ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */
+                       chan->cdr = bridge_cdr; /*  */
+               }
+               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);
+               }
+       }
        return res;
 }