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: https://origsvn.digium.com/svn/asterisk/branches/1.4@60989 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Steve Murphy 19 years ago
parent a1bdbc0289
commit 7d5a79a0b9

@ -1863,7 +1863,7 @@ static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, in
if (*fromstring) { if (*fromstring) {
struct ast_channel *ast; 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; char *passdata;
int vmlen = strlen(fromstring)*3 + 200; int vmlen = strlen(fromstring)*3 + 200;
if ((passdata = alloca(vmlen))) { if ((passdata = alloca(vmlen))) {
@ -1885,7 +1885,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); fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata), vmu->email);
if (emailsubject) { if (emailsubject) {
struct ast_channel *ast; 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; char *passdata;
int vmlen = strlen(emailsubject)*3 + 200; int vmlen = strlen(emailsubject)*3 + 200;
if ((passdata = alloca(vmlen))) { if ((passdata = alloca(vmlen))) {
@ -1939,7 +1939,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); fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
if (emailbody) { if (emailbody) {
struct ast_channel *ast; 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; char *passdata;
int vmlen = strlen(emailbody)*3 + 200; int vmlen = strlen(emailbody)*3 + 200;
if ((passdata = alloca(vmlen))) { if ((passdata = alloca(vmlen))) {
@ -2058,7 +2058,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
if (*pagerfromstring) { if (*pagerfromstring) {
struct ast_channel *ast; 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; char *passdata;
int vmlen = strlen(fromstring)*3 + 200; int vmlen = strlen(fromstring)*3 + 200;
if ((passdata = alloca(vmlen))) { if ((passdata = alloca(vmlen))) {
@ -2075,7 +2075,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
fprintf(p, "To: %s\n", pager); fprintf(p, "To: %s\n", pager);
if (pagersubject) { if (pagersubject) {
struct ast_channel *ast; 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; char *passdata;
int vmlen = strlen(pagersubject) * 3 + 200; int vmlen = strlen(pagersubject) * 3 + 200;
if ((passdata = alloca(vmlen))) { if ((passdata = alloca(vmlen))) {
@ -2091,7 +2091,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm); strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
if (pagerbody) { if (pagerbody) {
struct ast_channel *ast; 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; char *passdata;
int vmlen = strlen(pagerbody)*3 + 200; int vmlen = strlen(pagerbody)*3 + 200;
if ((passdata = alloca(vmlen))) { if ((passdata = alloca(vmlen))) {

@ -923,9 +923,9 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state)
} }
#endif #endif
if (p->pending) 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 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) { if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n"); ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n");
return NULL; return NULL;

@ -780,7 +780,7 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state)
{ {
struct ast_channel *tmp = NULL; 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; return NULL;
tmp->tech = &alsa_tech; tmp->tech = &alsa_tech;

@ -471,7 +471,7 @@ static struct ast_channel *features_new(struct feature_pvt *p, int state, int in
if (y >= 3) if (y >= 3)
break; 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 */ /* free up the name, it was copied into the channel name */
if (b2) if (b2)
free(b2); free(b2);

@ -899,7 +899,7 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
n2 = title; n2 = title;
else else
n2 = i->us; 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) { if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n"); ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n");
return NULL; return NULL;

@ -1014,7 +1014,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 */ /* Don't hold a oh323_pvt lock while we allocate a chanel */
ast_mutex_unlock(&pvt->lock); 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 */ /* Update usage counter */
ast_module_ref(ast_module_info->self); ast_module_ref(ast_module_info->self);
ast_mutex_lock(&pvt->lock); ast_mutex_lock(&pvt->lock);

@ -3270,7 +3270,7 @@ static struct ast_channel *ast_iax2_new(int callno, int state, int capability)
/* Don't hold call lock */ /* Don't hold call lock */
ast_mutex_unlock(&iaxsl[callno]); 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]); ast_mutex_lock(&iaxsl[callno]);
if (!tmp) if (!tmp)
return NULL; return NULL;
@ -6113,8 +6113,8 @@ static int iax_park(struct ast_channel *chan1, struct ast_channel *chan2)
struct iax_dual *d; struct iax_dual *d;
struct ast_channel *chan1m, *chan2m; struct ast_channel *chan1m, *chan2m;
pthread_t th; pthread_t th;
chan1m = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "Parking/%s", chan1->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, "IAXPeer/%s",chan2->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) { if (chan2m && chan1m) {
/* Make formats okay */ /* Make formats okay */
chan1m->readformat = chan1->readformat; chan1m->readformat = chan1->readformat;

@ -584,8 +584,8 @@ static struct ast_channel *local_new(struct local_pvt *p, int state)
int randnum = ast_random() & 0xffff, fmt = 0; int randnum = ast_random() & 0xffff, fmt = 0;
/* Allocate two new Asterisk channels */ /* Allocate two new Asterisk channels */
if (!(tmp = ast_channel_alloc(1, state, 0, 0, "Local/%s@%s-%04x,1", 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, "Local/%s@%s-%04x,2", 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) if (tmp)
ast_channel_free(tmp); ast_channel_free(tmp);
if (tmp2) if (tmp2)

@ -1427,7 +1427,7 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
struct mgcp_endpoint *i = sub->parent; struct mgcp_endpoint *i = sub->parent;
int fmt; 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) { if (tmp) {
tmp->tech = &mgcp_tech; tmp->tech = &mgcp_tech;
tmp->nativeformats = i->capability; tmp->nativeformats = i->capability;

@ -3188,7 +3188,7 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char
if (callerid) if (callerid)
ast_callerid_parse(callerid, &cid_name, &cid_num); 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) { if (tmp) {
chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid); chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);

@ -232,7 +232,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) static struct ast_channel *nbs_new(struct nbs_pvt *i, int state)
{ {
struct ast_channel *tmp; 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) { if (tmp) {
tmp->tech = &nbs_tech; tmp->tech = &nbs_tech;
tmp->fds[0] = nbs_fd(i->nbs); tmp->fds[0] = nbs_fd(i->nbs);

@ -992,7 +992,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
{ {
struct ast_channel *c; 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) if (c == NULL)
return NULL; return NULL;
c->tech = &oss_tech; c->tech = &oss_tech;
@ -1004,10 +1004,6 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
c->writeformat = AST_FORMAT_SLINEAR; c->writeformat = AST_FORMAT_SLINEAR;
c->tech_pvt = o; 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)) if (!ast_strlen_zero(o->language))
ast_string_field_set(c, language, o->language); ast_string_field_set(c, language, o->language);
/* Don't use ast_set_callerid() here because it will /* Don't use ast_set_callerid() here because it will

@ -826,7 +826,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
{ {
struct ast_channel *tmp; struct ast_channel *tmp;
struct phone_codec_data codec; 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) { if (tmp) {
tmp->tech = cur_tech; tmp->tech = cur_tech;
tmp->fds[0] = i->fd; tmp->fds[0] = i->fd;

@ -3777,7 +3777,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
ast_mutex_unlock(&i->lock); ast_mutex_unlock(&i->lock);
/* Don't hold a sip pvt lock while we allocate a channel */ /* 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) { if (!tmp) {
@ -3875,6 +3875,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->context, i->context, sizeof(tmp->context));
ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
/* Don't use ast_set_callerid() here because it will /* Don't use ast_set_callerid() here because it will
* generate an unnecessary NewCallerID event */ * generate an unnecessary NewCallerID event */
tmp->cid.cid_num = ast_strdup(i->cid_num); tmp->cid.cid_num = ast_strdup(i->cid_num);
@ -12629,8 +12630,8 @@ static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct
/* Chan2m: The transferer, chan1m: The transferee */ /* Chan2m: The transferer, chan1m: The transferee */
pthread_t th; pthread_t th;
transferee = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "Parking/%s", chan1->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, "SIPPeer/%s", chan2->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 ((!transferer) || (!transferee)) {
if (transferee) { if (transferee) {
transferee->hangupcause = AST_CAUSE_SWITCH_CONGESTION; transferee->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
@ -13441,7 +13442,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
/* Initialize our tag */ /* Initialize our tag */
make_our_tag(p->tag, sizeof(p->tag)); make_our_tag(p->tag, sizeof(p->tag));
/* First invitation - create the channel */ /* First invitation - create the channel */
c = sip_new(p, AST_STATE_DOWN, S_OR(p->username, NULL)); c = sip_new(p, AST_STATE_DOWN, S_OR(p->username, NULL));
*recount = 1; *recount = 1;

@ -2719,7 +2719,7 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state)
struct skinny_device *d = l->parent; struct skinny_device *d = l->parent;
int fmt; 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) { if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
return NULL; return NULL;

@ -2634,7 +2634,7 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
if (option_verbose > 3) if (option_verbose > 3)
ast_verbose("%s: New call for context [%s]\n",me->dev,context); 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 (tmp) {
if (use_ast_ind == 1){ if (use_ast_ind == 1){
tmp->tech = &vpb_tech_indicate; tmp->tech = &vpb_tech_indicate;

@ -5181,7 +5181,7 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
} }
y++; y++;
} while (x < 3); } 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 */ if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
free(b2); free(b2);
if (!tmp) if (!tmp)

@ -581,7 +581,7 @@ int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
by default set to the "default" context and by default set to the "default" context and
extension "s" 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 */ /*! \brief Queue an outgoing frame */
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f); int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f);

@ -469,31 +469,80 @@ struct ast_cdr *ast_cdr_alloc(void)
return x; 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) void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from)
{ {
if (!to || !from) if (!to || !from)
return; return;
if (!ast_tvzero(from->start)) { if (!ast_tvzero(from->start)) {
if (!ast_tvzero(to->start)) { if (!ast_tvzero(to->start)) {
if (ast_tvcmp(to->start, from->start) > 0 ) { if (ast_tvcmp(to->start, from->start) > 0 ) {
to->start = from->start; /* use the earliest time */ to->start = from->start; /* use the earliest time */
from->start = ast_tv(0,0); /* we actively "steal" these values */ 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 { } else {
to->start = from->start; to->start = from->start;
from->start = ast_tv(0,0); /* we actively "steal" these values */ 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(from->end)) {
if (!ast_tvzero(to->end)) { if (!ast_tvzero(to->end)) {
if (ast_tvcmp(to->end, from->end) < 0 ) { if (ast_tvcmp(to->end, from->end) < 0 ) {
to->end = from->end; /* use the latest time */ to->end = from->end; /* use the latest time */
from->end = ast_tv(0,0); /* we actively "steal" these values */ from->end = ast_tv(0,0); /* we actively "steal" these values */
} else { to->duration = to->end.tv_sec - to->start.tv_sec; /* don't forget to update the duration, billsec, when we set end */
ast_log(LOG_WARNING,"CDR end disagreement for %s\n", to->channel); to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec;
} }
/* else, nothing to do */
} else { } else {
to->end = from->end; to->end = from->end;
from->end = ast_tv(0,0); /* we actively "steal" these values */ 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; 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) { if (to->disposition < from->disposition) {
to->disposition = from->disposition; to->disposition = from->disposition;
from->disposition = AST_CDR_NOANSWER; 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 */ from->userfield[0] = 0; /* theft */
} }
/* flags, varsead, ? */ /* flags, varsead, ? */
cdr_merge_vars(from, to);
} }
void ast_cdr_start(struct ast_cdr *cdr) void ast_cdr_start(struct ast_cdr *cdr)

@ -711,7 +711,7 @@ static const struct ast_channel_tech null_tech = {
}; };
/*! \brief Create a new channel structure */ /*! \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; struct ast_channel *tmp;
int x; 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? */ /* 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(); tmp->cdr = ast_cdr_alloc();
ast_cdr_init(tmp->cdr, tmp); ast_cdr_init(tmp->cdr, tmp);
ast_cdr_start(tmp->cdr); 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); 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); 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; tmp->tech = &null_tech;

@ -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 /* 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 the PBX, we have to make a new channel, masquerade, and start the PBX
at the new location */ 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) { if (chan->cdr) {
tmpchan->cdr = ast_cdr_dup(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) static int ast_pbx_outgoing_cdr_failed(void)
{ {
/* allocate a channel */ /* 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) if (!chan)
return -1; /* failure */ 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 */ /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
/* check if "failed" exists */ /* check if "failed" exists */
if (ast_exists_extension(chan, context, "failed", 1, NULL)) { 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 (chan) {
if (!ast_strlen_zero(context)) if (!ast_strlen_zero(context))
ast_copy_string(chan->context, context, sizeof(chan->context)); ast_copy_string(chan->context, context, sizeof(chan->context));

@ -191,7 +191,7 @@ static void check_goto_on_transfer(struct ast_channel *chan)
goto_on_transfer = ast_strdupa(val); 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; return;
for (x = goto_on_transfer; x && *x; x++) { for (x = goto_on_transfer; x && *x; x++) {
@ -442,7 +442,7 @@ int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int
struct ast_frame *f; struct ast_frame *f;
/* Make a new, fake channel that we'll use to masquerade in the real one */ /* 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"); ast_log(LOG_WARNING, "Unable to create parked channel\n");
return -1; return -1;
} }
@ -837,7 +837,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
return -1; 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) { if (!xferchan) {
ast_hangup(newchan); ast_hangup(newchan);
return -1; return -1;
@ -1370,81 +1370,6 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
peer->cdr = NULL; 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 (;;) { for (;;) {
struct ast_channel *other; /* used later */ struct ast_channel *other; /* used later */
@ -1513,15 +1438,11 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 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! */ /* whoa!! don't go running off without cleaning up your mess! */
if (bridge_cdr) { if (bridge_cdr) {
ast_cdr_merge(bridge_cdr,chan->cdr);
ast_cdr_merge(bridge_cdr,peer->cdr);
ast_cdr_failed(bridge_cdr); ast_cdr_failed(bridge_cdr);
ast_cdr_end(bridge_cdr); ast_cdr_end(bridge_cdr);
ast_cdr_detach(bridge_cdr); ast_cdr_detach(bridge_cdr);
bridge_cdr = NULL; bridge_cdr = NULL;
} }
ast_cdr_free(chan->cdr); /* no posting these guys */
ast_cdr_free(peer->cdr);
chan->cdr = NULL; chan->cdr = NULL;
peer->cdr = NULL; peer->cdr = NULL;
return -1; return -1;
@ -1612,20 +1533,61 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
} }
if (f) if (f)
ast_frfree(f); ast_frfree(f);
} }
/* before leaving, post the cdr we accumulated */ /* arrange the cdrs */
/* whoa!! don't go running off without cleaning up your mess! */ bridge_cdr = ast_cdr_alloc();
if (bridge_cdr) { if (bridge_cdr) {
ast_cdr_merge(bridge_cdr,chan->cdr); ast_log(LOG_NOTICE,"merging the bridged CDRs\n");
ast_cdr_merge(bridge_cdr,peer->cdr); ast_cdr_init(bridge_cdr,chan); /* seems more logicaller to use the destination as a base, but, really, it's random */
ast_cdr_end(bridge_cdr); if (chan->cdr && peer->cdr) { /* both of them? merge */
ast_cdr_detach(bridge_cdr); ast_cdr_start(bridge_cdr); /* now is the time to start */
bridge_cdr = NULL; /* absorb the channel cdr */
} ast_cdr_merge(bridge_cdr, chan->cdr);
ast_cdr_discard(chan->cdr); /* no posting these guys */ ast_cdr_discard(chan->cdr); /* no posting these guys */
ast_cdr_discard(peer->cdr);
chan->cdr = NULL; /* absorb the peer cdr */
peer->cdr = NULL; 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);
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 */
} else {
/* 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);
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 */
} else {
/* 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; return res;
} }

Loading…
Cancel
Save