aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authormurf <murf@f38db490-d61c-443f-a65b-d21fe96a405b>2007-04-09 18:32:07 +0000
committermurf <murf@f38db490-d61c-443f-a65b-d21fe96a405b>2007-04-09 18:32:07 +0000
commit06afe72ddde29a01ab01380a6136c35913c8b619 (patch)
treee5d6613b436e3aa37ac46a65ae4b15e4393f1464 /main
parente712a2adf2cccce5cd6d454617e3f7d125004451 (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.c71
-rw-r--r--main/channel.c32
-rw-r--r--main/pbx.c6
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));