diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index af68b7c1e53881511d566abce11b7d6669d969c5..b00bd239e7aa222ac839d4c8e16680d1644678f7 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -4079,18 +4079,6 @@ static int attempt_transfer(struct dahdi_pvt *p) } if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, DAHDI_TONE_RINGTONE); - } - if (p->subs[SUB_REAL].owner->cdr) { - /* Move CDR from second channel to current one */ - p->subs[SUB_THREEWAY].owner->cdr = - ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->cdr); - p->subs[SUB_REAL].owner->cdr = NULL; - } - if (ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr) { - /* Move CDR from second channel's bridge to current one */ - p->subs[SUB_THREEWAY].owner->cdr = - ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr); - ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr = NULL; } if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", @@ -4108,18 +4096,6 @@ static int attempt_transfer(struct dahdi_pvt *p) if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE); } - if (p->subs[SUB_THREEWAY].owner->cdr) { - /* Move CDR from second channel to current one */ - p->subs[SUB_REAL].owner->cdr = - ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->cdr); - p->subs[SUB_THREEWAY].owner->cdr = NULL; - } - if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr) { - /* Move CDR from second channel's bridge to current one */ - p->subs[SUB_REAL].owner->cdr = - ast_cdr_append(p->subs[SUB_REAL].owner->cdr, ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr); - ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr = NULL; - } if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); @@ -4855,7 +4831,19 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) dahdi_enable_ec(p); ast_hangup(chan); } else { + struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); + int way3bridge = 0, cdr3way = 0; + + if (!other) { + other = ast_bridged_channel(p->subs[SUB_REAL].owner); + } else + way3bridge = 1; + + if (p->subs[SUB_THREEWAY].owner->cdr) + cdr3way = 1; + ast_verb(3, "Started three way call on channel %d\n", p->channel); + /* Start music on hold if appropriate */ if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, @@ -4886,6 +4874,16 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { int otherindex = SUB_THREEWAY; + struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); + int way3bridge = 0, cdr3way = 0; + + if (!other) { + other = ast_bridged_channel(p->subs[SUB_REAL].owner); + } else + way3bridge = 1; + + if (p->subs[SUB_THREEWAY].owner->cdr) + cdr3way = 1; ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); /* Put them in the threeway, and flip */ diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 1e5b927cf0e264044f9f4420b9c8df3bb2380471..8d6adf4f3ed7aae96806d2f16bc18e055251bb67 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -17073,19 +17073,6 @@ static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target if (peerd) ast_quiet_chan(peerd); - /* Fix CDRs so they're attached to the remaining channel */ - if (peera->cdr && peerb->cdr) - peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr); - else if (peera->cdr) - peerb->cdr = peera->cdr; - peera->cdr = NULL; - - if (peerb->cdr && peerc->cdr) - peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr); - else if (peerc->cdr) - peerb->cdr = peerc->cdr; - peerc->cdr = NULL; - ast_debug(4, "SIP transfer: trying to masquerade %s into %s\n", peerc->name, peerb->name); if (ast_channel_masquerade(peerb, peerc)) { ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name); diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h index addef04eaacd675c512977661ad109dde718ec04..dc14f326e979c9d97a71f0024d2cd2b7cd0fbb21 100644 --- a/include/asterisk/cdr.h +++ b/include/asterisk/cdr.h @@ -24,16 +24,23 @@ #define _ASTERISK_CDR_H #include <sys/time.h> + +/*! \name CDR Flags */ +/*@{ */ #define AST_CDR_FLAG_KEEP_VARS (1 << 0) #define AST_CDR_FLAG_POSTED (1 << 1) #define AST_CDR_FLAG_LOCKED (1 << 2) #define AST_CDR_FLAG_CHILD (1 << 3) #define AST_CDR_FLAG_POST_DISABLED (1 << 4) -#define AST_CDR_FLAG_ANSLOCKED (1 << 5) -#define AST_CDR_FLAG_DONT_TOUCH (1 << 6) +#define AST_CDR_FLAG_BRIDGED (1 << 5) +#define AST_CDR_FLAG_MAIN (1 << 6) +#define AST_CDR_FLAG_ENABLE (1 << 7) +#define AST_CDR_FLAG_ANSLOCKED (1 << 8) +#define AST_CDR_FLAG_DONT_TOUCH (1 << 9) #define AST_CDR_FLAG_POST_ENABLE (1 << 5) +/*@} */ -/*! \name CDR Flags */ +/*! \name CDR Flags - Disposition */ /*@{ */ #define AST_CDR_NULL 0 #define AST_CDR_FAILED (1 << 0) @@ -299,8 +306,16 @@ char *ast_cdr_disp2str(int disposition); */ void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags); -/*! - * \brief Flags to a string +/*! Reset the detail record times, flags */ +/*! + * \param cdr which cdr to act upon + * \param flags |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it + * |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's + */ +void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *flags); + +/*! Flags to a string */ +/*! * \param flags binary flag * Converts binary flags to string flags * Returns string with flag name diff --git a/main/cdr.c b/main/cdr.c index 259328fe16e449d78cb0063b96d4d672ce989b80..1600520007492d3ce59aa79a2853c24d8f91b281 100644 --- a/main/cdr.c +++ b/main/cdr.c @@ -781,6 +781,10 @@ void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data) for (; cdr; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { check_post(cdr); + if (!app) + app = ""; + if (!data) + data = ""; ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp)); ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata)); } @@ -864,7 +868,13 @@ void ast_cdr_end(struct ast_cdr *cdr) cdr->disposition = AST_CDR_FAILED; } else cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec; - cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec; + if (ast_tvzero(cdr->answer)) { + if (cdr->disposition == AST_CDR_ANSWERED) { + ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>")); + cdr->disposition = AST_CDR_FAILED; + } + } else + cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec; } } @@ -1064,6 +1074,27 @@ void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *_flags) } } +void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *_flags) +{ + struct ast_flags flags = { 0 }; + + if (_flags) + ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); + + if (_flags) + ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); + + /* Reset to initial state */ + ast_clear_flag(cdr, AST_FLAGS_ALL); + memset(&cdr->start, 0, sizeof(cdr->start)); + memset(&cdr->end, 0, sizeof(cdr->end)); + memset(&cdr->answer, 0, sizeof(cdr->answer)); + cdr->billsec = 0; + cdr->duration = 0; + ast_cdr_start(cdr); + cdr->disposition = AST_CDR_NULL; +} + struct ast_cdr *ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr) { struct ast_cdr *ret; diff --git a/main/channel.c b/main/channel.c index 240d1699a9d5eeeb9f6b02df0299ebe41802fe36..cbfe8ffcae877f4a02fb4fb50f9e55a0a9beeabe 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1582,7 +1582,6 @@ static void free_translation(struct ast_channel *clone) int ast_hangup(struct ast_channel *chan) { int res = 0; - struct ast_cdr *cdr = NULL; /* Don't actually hang up a channel that will masquerade as someone else, or if someone is going to masquerade as us */ @@ -1633,11 +1632,6 @@ int ast_hangup(struct ast_channel *chan) chan->generator->release(chan, chan->generatordata); chan->generatordata = NULL; chan->generator = NULL; - if (chan->cdr) { /* End the CDR if it hasn't already */ - ast_cdr_end(chan->cdr); - cdr = chan->cdr; - chan->cdr = NULL; - } if (ast_test_flag(chan, AST_FLAG_BLOCKING)) { ast_log(LOG_WARNING, "Hard hangup called by thread %ld on %s, while fd " "is blocked by thread %ld in procedure %s! Expect a failure\n", @@ -1667,10 +1661,13 @@ int ast_hangup(struct ast_channel *chan) chan->hangupcause, ast_cause2str(chan->hangupcause) ); - ast_channel_free(chan); - if (cdr) - ast_cdr_detach(cdr); + if (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_BRIDGED) && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED) && chan->cdr->disposition != AST_CDR_NULL) { + ast_cdr_end(chan->cdr); + ast_cdr_detach(chan->cdr); + } + + ast_channel_free(chan); return res; } @@ -1722,7 +1719,6 @@ int __ast_answer(struct ast_channel *chan, unsigned int delay) } return res; case AST_STATE_UP: - ast_cdr_answer(chan->cdr); break; default: break; @@ -2524,15 +2520,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) } else { /* Answer the CDR */ ast_setstate(chan, AST_STATE_UP); - if (!chan->cdr) { /* up till now, this insertion hasn't been done. Therefore, - to keep from throwing off the basic order of the universe, - we will try to keep this cdr from getting posted. */ - chan->cdr = ast_cdr_alloc(); - ast_cdr_init(chan->cdr, chan); - ast_cdr_start(chan->cdr); - } - - ast_cdr_answer(chan->cdr); + /* removed a call to ast_cdr_answer(chan->cdr) from here. */ } } break; @@ -2755,9 +2743,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) chan->hangupcause = cause; if (chan->generator) ast_deactivate_generator(chan); - /* End the CDR if appropriate */ - if (chan->cdr) - ast_cdr_end(chan->cdr); + /* We no longer End the CDR here */ } /* High bit prints debugging */ @@ -3329,15 +3315,6 @@ struct ast_channel *__ast_request_and_dial(const char *type, int format, void *d } ast_set_callerid(chan, cid_num, cid_name, cid_num); - - - if (!chan->cdr) { /* up till now, this insertion hasn't been done. Therefore, - to keep from throwing off the basic order of the universe, - we will try to keep this cdr from getting posted. */ - chan->cdr = ast_cdr_alloc(); - ast_cdr_init(chan->cdr, chan); - ast_cdr_start(chan->cdr); - } if (ast_call(chan, data, 0)) { /* ast_call failed... */ ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data); } else { @@ -4089,8 +4066,6 @@ void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char ast_free(chan->cid.cid_ani); chan->cid.cid_ani = ast_strdup(cid_ani); } - if (chan->cdr) - ast_cdr_setcid(chan->cdr, chan); manager_event(EVENT_FLAG_CALL, "NewCallerid", "Channel: %s\r\n" "CallerIDNum: %s\r\n" diff --git a/main/features.c b/main/features.c index ccd182d2157797c36bb49d76f2f4361c3ef1b434..f150f560fea19b62c46c551de3cd828a2afaa627 100644 --- a/main/features.c +++ b/main/features.c @@ -308,15 +308,6 @@ static void *ast_bridge_call_thread(void *data) tobj->peer->appl = !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge"; tobj->peer->data = tobj->chan->name; - if (tobj->chan->cdr) { - ast_cdr_reset(tobj->chan->cdr, NULL); - ast_cdr_setdestchan(tobj->chan->cdr, tobj->peer->name); - } - if (tobj->peer->cdr) { - ast_cdr_reset(tobj->peer->cdr, NULL); - ast_cdr_setdestchan(tobj->peer->cdr, tobj->chan->name); - } - ast_bridge_call(tobj->peer, tobj->chan, &tobj->bconfig); if (tobj->return_to_pbx) { @@ -1889,13 +1880,6 @@ static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *call ast_string_field_set(chan, language, language); ast_channel_inherit_variables(caller, chan); pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name); - if (!chan->cdr) { - chan->cdr=ast_cdr_alloc(); - if (chan->cdr) { - ast_cdr_init(chan->cdr, chan); /* initilize our channel's cdr */ - ast_cdr_start(chan->cdr); - } - } if (!ast_call(chan, data, timeout)) { struct timeval started; @@ -2042,23 +2026,6 @@ static struct ast_channel *ast_feature_request_and_dial(struct ast_channel *call if (outstate) *outstate = state; - if (chan && res <= 0) { - if (chan->cdr || (chan->cdr = ast_cdr_alloc())) { - char tmp[256]; - ast_cdr_init(chan->cdr, chan); - snprintf(tmp, 256, "%s/%s", type, (char *)data); - ast_cdr_setapp(chan->cdr,"Dial",tmp); - ast_cdr_update(chan); - ast_cdr_start(chan->cdr); - ast_cdr_end(chan->cdr); - /* If the cause wasn't handled properly */ - if (ast_cdr_disposition(chan->cdr,chan->hangupcause)) - ast_cdr_failed(chan->cdr); - } else { - ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); - } - } - return chan; } @@ -2079,13 +2046,15 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast struct ast_channel *who; char chan_featurecode[FEATURE_MAX_LEN + 1]=""; char peer_featurecode[FEATURE_MAX_LEN + 1]=""; + char orig_channame[AST_MAX_EXTENSION]; + char orig_peername[AST_MAX_EXTENSION]; int res; int diff; int hasfeatures=0; int hadfeatures=0; struct ast_option_header *aoh; struct ast_bridge_config backup_config; - struct ast_cdr *bridge_cdr; + struct ast_cdr *bridge_cdr = NULL; memset(&backup_config, 0, sizeof(backup_config)); @@ -2120,25 +2089,49 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast /* Answer if need be */ if (ast_answer(chan)) return -1; - peer->appl = "Bridged Call"; - peer->data = chan->name; - - /* copy the userfield from the B-leg to A-leg if applicable */ - if (chan->cdr && peer->cdr && !ast_strlen_zero(peer->cdr->userfield)) { - char tmp[256]; - if (!ast_strlen_zero(chan->cdr->userfield)) { - snprintf(tmp, sizeof(tmp), "%s;%s", chan->cdr->userfield, peer->cdr->userfield); - ast_cdr_appenduserfield(chan, tmp); - } else - ast_cdr_setuserfield(chan, peer->cdr->userfield); - /* free the peer's cdr without ast_cdr_free complaining */ - ast_free(peer->cdr); - peer->cdr = NULL; - } + ast_copy_string(orig_channame,chan->name,sizeof(orig_channame)); + ast_copy_string(orig_peername,peer->name,sizeof(orig_peername)); + + if (!chan->cdr || (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED))) { + + if (chan->cdr) { + ast_set_flag(chan->cdr, AST_CDR_FLAG_MAIN); + ast_cdr_update(chan); + bridge_cdr = ast_cdr_dup(chan->cdr); + ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp)); + ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata)); + } else { + /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */ + bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */ + ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel)); + ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel)); + ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid)); + ast_copy_string(bridge_cdr->lastapp, chan->appl, sizeof(bridge_cdr->lastapp)); + ast_copy_string(bridge_cdr->lastdata, chan->data, sizeof(bridge_cdr->lastdata)); + ast_cdr_setcid(bridge_cdr, chan); + bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL; + bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags; + ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode)); + /* Destination information */ + ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst)); + ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext)); + if (peer->cdr) { + bridge_cdr->start = peer->cdr->start; + ast_copy_string(bridge_cdr->userfield, peer->cdr->userfield, sizeof(bridge_cdr->userfield)); + } else { + ast_cdr_start(bridge_cdr); + } + } + ast_cdr_answer(bridge_cdr); + ast_cdr_answer(chan->cdr); /* for the sake of cli status checks */ + ast_set_flag(chan->cdr, AST_CDR_FLAG_BRIDGED); + if (peer->cdr) + ast_set_flag(peer->cdr, AST_CDR_FLAG_BRIDGED); + } for (;;) { struct ast_channel *other; /* used later */ - + res = ast_channel_bridge(chan, peer, config, &f, &who); if (config->feature_timer) { @@ -2297,67 +2290,18 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast ast_frfree(f); } - /* arrange the cdrs */ - bridge_cdr = ast_cdr_alloc(); - if (bridge_cdr) { - if (chan->cdr && peer->cdr) { /* both of them? merge */ - ast_channel_lock(chan); /* lock the channel before modifying cdrs */ - 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); - if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) - ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ - - chan->cdr = NULL; - ast_channel_unlock(chan); - /* absorb the peer cdr */ - ast_channel_lock(peer); - ast_cdr_merge(bridge_cdr, peer->cdr); - if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) - ast_cdr_discard(peer->cdr); /* if locked cdrs are in peer, they are taken over in the merge */ - - peer->cdr = NULL; /* remove pointer to freed memory before releasing the lock */ - ast_channel_unlock(peer); - - ast_channel_lock(chan); - chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ - ast_channel_unlock(chan); - } else if (chan->cdr) { - ast_channel_lock(chan); /* Lock before modifying CDR */ - /* take the cdr from the channel - literally */ - ast_cdr_init(bridge_cdr,chan); - /* absorb this data */ - ast_cdr_merge(bridge_cdr, chan->cdr); - if (!ast_test_flag(chan->cdr, AST_CDR_FLAG_LOCKED)) - ast_cdr_discard(chan->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ - chan->cdr = bridge_cdr; /* make this available to the rest of the world via the chan while the call is in progress */ - ast_channel_unlock(chan); - } else if (peer->cdr) { - ast_channel_lock(peer); /* Lock before modifying CDR */ - /* take the cdr from the peer - literally */ - ast_cdr_init(bridge_cdr,peer); - /* absorb this data */ - ast_cdr_merge(bridge_cdr, peer->cdr); - if (!ast_test_flag(peer->cdr, AST_CDR_FLAG_LOCKED)) - ast_cdr_discard(peer->cdr); /* if locked cdrs are in chan, they are taken over in the merge */ - 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 */ - ast_channel_unlock(peer); - } else { - ast_channel_lock(chan); /* Lock before modifying CDR */ - /* make up a new cdr */ - ast_cdr_init(bridge_cdr,chan); /* eh, just pick one of them */ - chan->cdr = bridge_cdr; /* */ - ast_channel_unlock(chan); - } - 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); - } + /* obey the NoCDR() wishes. */ + if (!chan->cdr || (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED))) { + + ast_cdr_end(bridge_cdr); + + ast_cdr_detach(bridge_cdr); + + /* just in case, these channels get bridged again before hangup */ + if (chan->cdr) + ast_cdr_specialized_reset(chan->cdr,0); + if (peer->cdr) + ast_cdr_specialized_reset(peer->cdr,0); } return res; } diff --git a/main/pbx.c b/main/pbx.c index a0ba3a901478147fd8258a1ae1d2bd54204c3237..5b7e3bdee3f0d6b14fbe9f4a603e4dcc5a54c71b 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -3475,17 +3475,6 @@ static int __ast_pbx_run(struct ast_channel *c) } if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx)))) return -1; - if (c->amaflags) { - if (!c->cdr) { - c->cdr = ast_cdr_alloc(); - if (!c->cdr) { - ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); - ast_free(c->pbx); - return -1; - } - ast_cdr_init(c->cdr, c); - } - } /* Set reasonable defaults */ c->pbx->rtimeoutms = 10000; c->pbx->dtimeoutms = 5000; @@ -3508,8 +3497,6 @@ static int __ast_pbx_run(struct ast_channel *c) ast_copy_string(c->context, "default", sizeof(c->context)); } } - if (c->cdr && ast_tvzero(c->cdr->start)) - ast_cdr_start(c->cdr); for (;;) { char dst_exten[256]; /* buffer to accumulate digits */ int pos = 0; /* XXX should check bounds */ @@ -3691,8 +3678,6 @@ static int __ast_pbx_run(struct ast_channel *c) if (res != AST_PBX_KEEPALIVE) ast_softhangup(c, c->hangupcause ? c->hangupcause : AST_CAUSE_NORMAL_CLEARING); if ((res != AST_PBX_KEEPALIVE) && ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) { - if (c->cdr && ast_opt_end_cdr_before_h_exten) - ast_cdr_end(c->cdr); set_ext_pri(c, "h", 1); while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) { c->priority++; @@ -6989,18 +6974,6 @@ int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, if (sync) { chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh); if (chan) { - if (!chan->cdr) { /* check if the channel already has a cdr record, if not give it one */ - chan->cdr = ast_cdr_alloc(); /* allocate a cdr for the channel */ - if (!chan->cdr) { - /* allocation of the cdr failed */ - ast_free(chan->pbx); - res = -1; - goto outgoing_app_cleanup; - } - /* allocation of the cdr was successful */ - ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */ - ast_cdr_start(chan->cdr); - } ast_set_variables(chan, vars); if (account) ast_cdr_setaccount(chan, account); @@ -8375,7 +8348,6 @@ static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, else ast_explicit_goto(chan, context, exten, ipri); - ast_cdr_update(chan); return 0; }