--- asterisk-1.4/include/asterisk/cdr.h 2008-11-02 02:24:53.000000000 +0100 +++ asterisk-1.4_new/include/asterisk/cdr.h 2008-11-02 00:51:40.000000000 +0100 @@ -37,6 +37,7 @@ #define AST_CDR_FLAG_ANSLOCKED (1 << 8) #define AST_CDR_FLAG_DONT_TOUCH (1 << 9) #define AST_CDR_FLAG_DIALED (1 << 10) +#define AST_CDR_FLAG_INHERITED (1 << 11) /*! Disposition */ #define AST_CDR_NULL 0 --- asterisk-1.4/main/cdr.c 2008-11-02 02:24:58.000000000 +0100 +++ asterisk-1.4_new/main/cdr.c 2008-11-02 02:24:01.000000000 +0100 @@ -317,6 +317,8 @@ } for (; cdr; cdr = recur ? cdr->next : NULL) { + if (ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) + continue; if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) continue; headp = &cdr->varshead; @@ -506,6 +508,30 @@ AST_LIST_TRAVERSE_SAFE_END; } +void ast_cdr_transfer(struct ast_channel *transferee, struct ast_channel *transferer) +{ + struct ast_cdr *zcdr; + struct ast_cdr *from = transferer->cdr; + struct ast_cdr *to = transferee->cdr; + + /* the 'transferee' CDR list inherits all related CDRs from the 'transferer' */ + while (from) { + /* CDR is inherited only if it contains the 'transferee' as source + or destination channel, otherwise it stays to be posted */ + if((transferee->channel == from->channel) || (transferee->channel == from->dstchannel)) { + /* move from the 'transferer' to the 'transferee' */ + zcdr = from; + from = zcdr->next; + zcdr->next = NULL; + /* set flag to inherited so that only end time and duration can be modified */ + ast_set_flag(zcdr, AST_CDR_FLAG_INHERITED); + ast_cdr_append(to, zcdr); + } + else + from = from->next; + } +} + void ast_cdr_merge(struct ast_cdr *to, struct ast_cdr *from) { struct ast_cdr *zcdr; @@ -517,21 +543,21 @@ return; /* don't merge into locked CDR's -- it's bad business */ - if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { + if (ast_test_flag(to, AST_CDR_FLAG_LOCKED) || ast_test_flag(to, AST_CDR_FLAG_INHERITED)) { zcdr = to; /* safety valve? */ while (to->next) { lto = to; to = to->next; } - if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { + if (ast_test_flag(to, AST_CDR_FLAG_LOCKED) || ast_test_flag(to, AST_CDR_FLAG_INHERITED)) { ast_log(LOG_WARNING, "Merging into locked CDR... no choice."); to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */ lto = NULL; } } - if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) { + if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || ast_test_flag(from, AST_CDR_FLAG_INHERITED)) { discard_from = 1; if (lto) { struct ast_cdr *llfrom = NULL; @@ -649,13 +675,13 @@ to->amaflags = AST_CDR_DOCUMENTATION; if (!from->amaflags) from->amaflags = AST_CDR_DOCUMENTATION; /* make sure both amaflags are set to something (DOC is default) */ - if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) { + if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || ast_test_flag(from, AST_CDR_FLAG_INHERITED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) { to->amaflags = from->amaflags; } - if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) { + if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || ast_test_flag(from, AST_CDR_FLAG_INHERITED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) { ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode)); } - if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) { + if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || ast_test_flag(from, AST_CDR_FLAG_INHERITED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) { ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield)); } /* flags, varsead, ? */ @@ -667,6 +693,8 @@ 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_INHERITED)) + ast_set_flag(to, AST_CDR_FLAG_INHERITED); 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)) @@ -690,7 +718,7 @@ char *chan; for (; cdr; cdr = cdr->next) { - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) { chan = S_OR(cdr->channel, ""); check_post(cdr); cdr->start = ast_tvnow(); @@ -704,6 +732,8 @@ for (; cdr; cdr = cdr->next) { if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) continue; + if (ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) + continue; if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) continue; check_post(cdr); @@ -718,7 +748,7 @@ { for (; cdr; cdr = cdr->next) { - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) { check_post(cdr); if (cdr->disposition < AST_CDR_BUSY) cdr->disposition = AST_CDR_BUSY; @@ -730,7 +760,7 @@ { for (; cdr; cdr = cdr->next) { check_post(cdr); - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) { if (cdr->disposition < AST_CDR_FAILED) cdr->disposition = AST_CDR_FAILED; } @@ -745,7 +775,7 @@ chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : ""; if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) { if (cdr->disposition < AST_CDR_NOANSWER) cdr->disposition = AST_CDR_NOANSWER; } @@ -779,7 +809,7 @@ { for (; cdr; cdr = cdr->next) { check_post(cdr); - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel)); } } @@ -788,7 +818,7 @@ { for (; cdr; cdr = cdr->next) { - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) { check_post(cdr); ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp)); ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata)); @@ -819,7 +849,7 @@ int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c) { for (; cdr; cdr = cdr->next) { - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) set_one_cid(cdr, c); } return 0; @@ -830,7 +860,7 @@ char *chan; for ( ; cdr ; cdr = cdr->next) { - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) { chan = S_OR(cdr->channel, ""); ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); set_one_cid(cdr, c); @@ -920,7 +950,7 @@ ast_string_field_set(chan, accountcode, account); for ( ; cdr ; cdr = cdr->next) { - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) { ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode)); } } @@ -933,7 +963,7 @@ int newflag = ast_cdr_amaflags2int(flag); if (newflag) { for (cdr = chan->cdr; cdr; cdr = cdr->next) { - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) { cdr->amaflags = newflag; } } @@ -947,7 +977,7 @@ struct ast_cdr *cdr = chan->cdr; for ( ; cdr ; cdr = cdr->next) { - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield)); } @@ -961,7 +991,7 @@ for ( ; cdr ; cdr = cdr->next) { int len = strlen(cdr->userfield); - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len); } @@ -973,7 +1003,7 @@ struct ast_cdr *cdr = c->cdr; for ( ; cdr ; cdr = cdr->next) { - if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED)) { set_one_cid(cdr, c); /* Copy account code et-al */ @@ -1040,7 +1070,8 @@ for ( ; cdr ; cdr = cdr->next) { /* Detach if post is requested */ - if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { + if ((ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) && + (ast_test_flag(&flags, AST_CDR_FLAG_INHERITED) || !ast_test_flag(cdr, AST_CDR_FLAG_INHERITED))) { if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) { ast_cdr_end(cdr); if ((dup = ast_cdr_dup(cdr))) {