diff options
author | murf <murf@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-04-09 18:32:07 +0000 |
---|---|---|
committer | murf <murf@f38db490-d61c-443f-a65b-d21fe96a405b> | 2007-04-09 18:32:07 +0000 |
commit | 06afe72ddde29a01ab01380a6136c35913c8b619 (patch) | |
tree | e5d6613b436e3aa37ac46a65ae4b15e4393f1464 /main | |
parent | e712a2adf2cccce5cd6d454617e3f7d125004451 (diff) |
This is a big improvement over the current CDR fixes. It may still need refinement, but this won't have as many folks bothered.
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@60989 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r-- | main/cdr.c | 71 | ||||
-rw-r--r-- | main/channel.c | 32 | ||||
-rw-r--r-- | main/pbx.c | 6 |
3 files changed, 82 insertions, 27 deletions
diff --git a/main/cdr.c b/main/cdr.c index e10f8fafe..f6a90c035 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -469,31 +469,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 */ @@ -501,19 +550,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; @@ -559,6 +595,7 @@ void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from) from->userfield[0] = 0; /* theft */ } /* flags, varsead, ? */ + cdr_merge_vars(from, to); } void ast_cdr_start(struct ast_cdr *cdr) diff --git a/main/channel.c b/main/channel.c index bb7f556c5..4f0b58536 100644 --- a/main/channel.c +++ b/main/channel.c @@ -711,7 +711,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; @@ -824,6 +824,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); @@ -835,13 +859,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; diff --git a/main/pbx.c b/main/pbx.c index beb69081f..257728df4 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -4558,7 +4558,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); } @@ -4919,7 +4919,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 */ @@ -5030,7 +5030,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)); |