Index: include/asterisk/cdr.h =================================================================== --- include/asterisk/cdr.h (revision 94934) +++ include/asterisk/cdr.h (working copy) @@ -280,6 +280,24 @@ */ char *ast_cdr_disp2str(int disposition); +/*! + * \Brief Disposition mask to string + * \param mask string representation of disposition mask + * \param buf buffer in which to store result + * \param len length of buffer + * Converts the binary form of a disposition mask to string form + * \return string representation of binary form + */ +char *ast_cdr_dispmask2str(int mask, char *buf, int len); + +/*! + * \Brief String to disposition mask + * \param mask string representation of disposition mask + * Converts the string form of a disposition mask to binary form + * \return binary representation of string form + */ +int ast_cdr_str2dispmask(const char *mask); + /*! * \brief Reset the detail record, optionally posting it first * \param cdr which cdr to act upon Index: main/cdr.c =================================================================== --- main/cdr.c (revision 94934) +++ main/cdr.c (working copy) @@ -85,6 +85,7 @@ static int enabled; /*! Is the CDR subsystem enabled ? */ static int unanswered; +static int dispositionmask; static int batchmode; static int batchsize; static int batchtime; @@ -876,6 +877,57 @@ return "UNKNOWN"; } +/*! Converts the binary form of a disposition mask to string representation */ +char *ast_cdr_dispmask2str(int mask, char *buf, int len) { + strncpy(buf, "", len); + + if (mask & AST_CDR_FAILED) + strncat(buf, "FAILED|", len); + if (mask & AST_CDR_BUSY) + strncat(buf, "BUSY|", len); + if (mask & AST_CDR_NOANSWER) + strncat(buf, "NOANSWER|", len); + if (mask & AST_CDR_ANSWERED) + strncat(buf, "ANSWERED|", len); + + if (strlen(buf) > 0) { + *(buf + strlen(buf) - 1) = '\0'; + return buf; + } + + return NULL; +} + +/*! Converts the string form of a disposition mask to binary form */ +int ast_cdr_str2dispmask(const char *mask) { + int dispmask; + char **stringp, *token; + + dispmask = 0; + + stringp = (char **) &mask; + while ((token = strsep(stringp, "|,"))) { + token = ast_strip(token); + if (!strcasecmp(token, "FAILED")) { + dispmask |= AST_CDR_FAILED; + } + else if (!strcasecmp(token, "BUSY")) { + dispmask |= AST_CDR_BUSY; + } + else if (!strcasecmp(token, "NOANSWER")) { + dispmask |= AST_CDR_NOANSWER; + } + else if (!strcasecmp(token, "ANSWERED")) { + dispmask |= AST_CDR_ANSWERED; + } + else { + return -1; + } + } + + return dispmask; +} + /*! Converts AMA flag to printable string */ char *ast_cdr_flags2str(int flag) { @@ -998,6 +1050,8 @@ ast_set_flag(cdr, AST_CDR_FLAG_POSTED); if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) continue; + if ((cdr->disposition ? cdr->disposition : AST_CDR_NOANSWER) & ~dispositionmask) + continue; AST_RWLIST_RDLOCK(&be_list); AST_RWLIST_TRAVERSE(&be_list, i, list) { i->be(cdr); @@ -1234,6 +1288,7 @@ struct ast_cdr_beitem *beitem=NULL; int cnt=0; long nextbatchtime=0; + char tmp[32]; switch (cmd) { case CLI_INIT: @@ -1253,6 +1308,7 @@ ast_cli(a->fd, "CDR mode: %s\n", batchmode ? "batch" : "simple"); if (enabled) { ast_cli(a->fd, "CDR output unanswered calls: %s\n", unanswered ? "yes" : "no"); + ast_cli(a->fd, "CDR disposition mask: %s\n", ast_cdr_dispmask2str(dispositionmask, tmp, sizeof(tmp) - 1)); if (batchmode) { if (batch) cnt = batch->size; @@ -1304,6 +1360,7 @@ struct ast_config *config; const char *enabled_value; const char *unanswered_value; + const char *dispositionmask_value; const char *batched_value; const char *scheduleronly_value; const char *batchsafeshutdown_value; @@ -1342,6 +1399,17 @@ if ((unanswered_value = ast_variable_retrieve(config, "general", "unanswered"))) { unanswered = ast_true(unanswered_value); } + if ((dispositionmask_value = ast_variable_retrieve(config, "general", "dispositions"))) { + if ((dispositionmask = ast_cdr_str2dispmask(dispositionmask_value)) < 0) { + ast_log(LOG_WARNING, "Invalid disposition mask '%s' specified. Using default.\n", dispositionmask_value); + dispositionmask = AST_CDR_FAILED|AST_CDR_BUSY|AST_CDR_NOANSWER|AST_CDR_ANSWERED; + } + else if (dispositionmask == 0) { + ast_log(LOG_WARNING, "Disposition mask of \"\" specified. No CDRs will be posted.\n"); + } + } else { + dispositionmask = AST_CDR_FAILED|AST_CDR_BUSY|AST_CDR_NOANSWER|AST_CDR_ANSWERED; + } if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) { batchmode = ast_true(batched_value); } Index: configs/cdr.conf.sample =================================================================== --- configs/cdr.conf.sample (revision 94934) +++ configs/cdr.conf.sample (working copy) @@ -23,6 +23,11 @@ ; redundant, but cannot be helped. ;unanswered = no +; Define the dispositions to log using the format D1|D2|..|DN where Dx is one +; of FAILED, BUSY, NOANSWER, ANSWERED. Default is to log everything: +; FAILED|BUSY|NOANSWER|ANSWERED. +;dispositions = FAILED|BUSY|NOANSWER|ANSWERED + ; Define the CDR batch mode, where instead of posting the CDR at the end of ; every call, the data will be stored in a buffer to help alleviate load on the ; asterisk server. Default is "no".