diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/cdr.c | 84 | ||||
-rw-r--r-- | main/channel.c | 32 | ||||
-rw-r--r-- | main/pbx.c | 6 |
3 files changed, 94 insertions, 28 deletions
diff --git a/main/cdr.c b/main/cdr.c index be2385212..7703e35a5 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -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) diff --git a/main/channel.c b/main/channel.c index 998843d7e..87be422a7 100644 --- a/main/channel.c +++ b/main/channel.c @@ -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; diff --git a/main/pbx.c b/main/pbx.c index 2ce76054d..ef9567850 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -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)); |