Wed Oct 28 11:45:25 2009

Asterisk developer's documentation


app_forkcdr.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Anthony Minessale anthmct@yahoo.com
00005  * Development of this app Sponsered/Funded  by TAAN Softworks Corp
00006  *
00007  * See http://www.asterisk.org for more information about
00008  * the Asterisk project. Please do not directly contact
00009  * any of the maintainers of this project for assistance;
00010  * the project provides a web site, mailing lists and IRC
00011  * channels for your use.
00012  *
00013  * This program is free software, distributed under the terms of
00014  * the GNU General Public License Version 2. See the LICENSE file
00015  * at the top of the source tree.
00016  */
00017 
00018 /*! \file
00019  *
00020  * \brief Fork CDR application
00021  *
00022  * \author Anthony Minessale anthmct@yahoo.com
00023  *
00024  * \note Development of this app Sponsored/Funded by TAAN Softworks Corp
00025  * 
00026  * \ingroup applications
00027  */
00028 
00029 #include "asterisk.h"
00030 
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 192095 $")
00032 
00033 #include "asterisk/file.h"
00034 #include "asterisk/channel.h"
00035 #include "asterisk/pbx.h"
00036 #include "asterisk/cdr.h"
00037 #include "asterisk/app.h"
00038 #include "asterisk/module.h"
00039 
00040 static char *app = "ForkCDR";
00041 static char *synopsis = 
00042 "Forks the Call Data Record";
00043 static char *descrip = 
00044 "  ForkCDR([options]):  Causes the Call Data Record to fork an additional\n"
00045 "cdr record starting from the time of the fork call. This new cdr record will\n"
00046 "be linked to end of the list of cdr records attached to the channel. The original CDR\n"
00047 "has a LOCKED flag set, which forces most cdr operations to skip it, except\n"
00048 "for the functions that set the answer and end times, which ignore the LOCKED\n"
00049 "flag. This allows all the cdr records in the channel to be 'ended' together\n"
00050 "when the channel is closed.\n"
00051 "The CDR() func (when setting CDR values) normally ignores the LOCKED flag also,\n"
00052 "but has options to vary its behavior. The 'T' option (described below), can\n"
00053 "override this behavior, but beware the risks.\n"
00054 "\n"
00055 "Detailed Behavior Description:\n"
00056 "First, this app finds the last cdr record in the list, and makes\n"
00057 "a copy of it. This new copy will be the newly forked cdr record.\n"
00058 "Next, this new record is linked to the end of the cdr record list.\n"
00059 "Next, The new cdr record is RESET (unless you use an option to prevent this)\n"
00060 "This means that:\n"
00061 "   1. All flags are unset on the cdr record\n"
00062 "   2. the start, end, and answer times are all set to zero.\n"
00063 "   3. the billsec and duration fields are set to zero.\n"
00064 "   4. the start time is set to the current time.\n"
00065 "   5. the disposition is set to NULL.\n"
00066 "Next, unless you specified the 'v' option, all variables will be\n"
00067 "removed from the original cdr record. Thus, the 'v' option allows\n"
00068 "any CDR variables to be replicated to all new forked cdr records.\n"
00069 "Without the 'v' option, the variables on the original are effectively\n"
00070 "moved to the new forked cdr record.\n"
00071 "Next, if the 's' option is set, the provided variable and value\n"
00072 "are set on the original cdr record.\n"
00073 "Next, if the 'a' option is given, and the original cdr record has an\n"
00074 "answer time set, then the new forked cdr record will have its answer\n"
00075 "time set to its start time. If the old answer time were carried forward,\n"
00076 "the answer time would be earlier than the start time, giving strange\n"
00077 "duration and billsec times.\n"
00078 "Next, if the 'd' option was specified, the disposition is copied from\n"
00079 "the original cdr record to the new forked cdr.\n"
00080 "Next, if the 'D' option was specified, the destination channel field\n"
00081 "in the new forked CDR is erased.\n"
00082 "Next, if the 'e' option was specified, the 'end' time for the original\n"
00083 "cdr record is set to the current time. Future hang-up or ending events\n"
00084 "will not override this time stamp.\n"
00085 "Next, If the 'A' option is specified, the original cdr record will have\n"
00086 "it ANS_LOCKED flag set, which prevent future answer events\n"
00087 "from updating the original cdr record's disposition. Normally, an\n"
00088 "'ANSWERED' event would mark all cdr records in the chain as 'ANSWERED'.\n"
00089 "Next, if the 'T' option is specified, the original cdr record will have\n"
00090 "its 'DONT_TOUCH' flag set, which will force the cdr_answer, cdr_end, and\n"
00091 "cdr_setvar functions to leave that cdr record alone.\n"
00092 "And, last but not least, the original cdr record has its LOCKED flag\n"
00093 "set. Almost all internal CDR functions (except for the funcs that set\n"
00094 "the end, and answer times, and set a variable) will honor this flag\n"
00095 "and leave a LOCKED cdr record alone.\n"
00096 "This means that the newly created forked cdr record will be affected\n"
00097 "by events transpiring within Asterisk, with the previously noted\n"
00098 "exceptions.\n"
00099 "  Options:\n"
00100 "    a - update the answer time on the NEW CDR just after it's been inited.\n"
00101 "         The new CDR may have been answered already. The reset that forkcdr\n"
00102 "         does will erase the answer time. This will bring it back, but\n"
00103 "         the answer time will be a copy of the fork/start time. It will\n"
00104 "         only do this if the initial cdr was indeed already answered.\n"
00105 "    A - Lock the original CDR against the answer time being updated.\n"
00106 "         This will allow the disposition on the original CDR to remain the same.\n"
00107 "    d - Copy the disposition forward from the old cdr, after the \n"
00108 "         init.\n"
00109 "    D - Clear the dstchannel on the new CDR after reset.\n"
00110 "    e - end the original CDR. Do this after all the neccessary data\n"
00111 "         is copied from the original CDR to the new forked CDR.\n"
00112 "    R -  do NOT reset the new cdr.\n"
00113 "    s(name=val) - Set the CDR var 'name' in the original CDR, with value\n"
00114 "                  'val'.\n"
00115 "    T -  Mark the original CDR with a DONT_TOUCH flag. setvar, answer, and end\n"
00116 "          cdr funcs will obey this flag; normally they don't honor the LOCKED\n"
00117 "          flag set on the original CDR record.\n"
00118 "          Beware-- using this flag may cause CDR's not to have their end times\n"
00119 "          updated! It is suggested that if you specify this flag, you might\n"
00120 "          wish to use the 'e' flag as well!\n"
00121 "    v  - When the new CDR is forked, it gets a copy of the vars attached\n"
00122 "         to the current CDR. The vars attached to the original CDR are removed\n"
00123 "         unless this option is specified.\n";
00124 
00125 
00126 enum {
00127    OPT_SETANS =            (1 << 0),
00128    OPT_SETDISP =           (1 << 1),
00129    OPT_RESETDEST =         (1 << 2),
00130    OPT_ENDCDR =            (1 << 3),
00131    OPT_NORESET =           (1 << 4),
00132    OPT_KEEPVARS =          (1 << 5),
00133    OPT_VARSET =            (1 << 6),
00134    OPT_ANSLOCK =           (1 << 7),
00135    OPT_DONTOUCH =          (1 << 8),
00136 };
00137 
00138 enum {
00139    OPT_ARG_VARSET = 0,
00140    /* note: this entry _MUST_ be the last one in the enum */
00141    OPT_ARG_ARRAY_SIZE,
00142 };
00143 
00144 AST_APP_OPTIONS(forkcdr_exec_options, {
00145    AST_APP_OPTION('a', OPT_SETANS),
00146    AST_APP_OPTION('A', OPT_ANSLOCK),
00147    AST_APP_OPTION('d', OPT_SETDISP),
00148    AST_APP_OPTION('D', OPT_RESETDEST),
00149    AST_APP_OPTION('e', OPT_ENDCDR),
00150    AST_APP_OPTION('R', OPT_NORESET),
00151    AST_APP_OPTION_ARG('s', OPT_VARSET, OPT_ARG_VARSET),
00152    AST_APP_OPTION('T', OPT_DONTOUCH),
00153    AST_APP_OPTION('v', OPT_KEEPVARS),
00154 });
00155 
00156 static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set) 
00157 {
00158    struct ast_cdr *cdr;
00159    struct ast_cdr *newcdr;
00160    struct ast_flags flags = { AST_CDR_FLAG_KEEP_VARS };
00161 
00162    cdr = chan->cdr;
00163 
00164    while (cdr->next)
00165       cdr = cdr->next;
00166    
00167    if (!(newcdr = ast_cdr_dup(cdr)))
00168       return;
00169    
00170    ast_cdr_append(cdr, newcdr);
00171 
00172    if (!ast_test_flag(&optflags, OPT_NORESET))
00173       ast_cdr_reset(newcdr, &flags);
00174       
00175    if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
00176       ast_cdr_free_vars(cdr, 0);
00177    
00178    if (!ast_strlen_zero(set)) {
00179       char *varname = ast_strdupa(set), *varval;
00180       varval = strchr(varname,'=');
00181       if (varval) {
00182          *varval = 0;
00183          varval++;
00184          ast_cdr_setvar(cdr, varname, varval, 0);
00185       }
00186    }
00187    
00188    if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer))
00189       newcdr->answer = newcdr->start;
00190 
00191    if (ast_test_flag(&optflags, OPT_SETDISP))
00192       newcdr->disposition = cdr->disposition;
00193    
00194    if (ast_test_flag(&optflags, OPT_RESETDEST))
00195       newcdr->dstchannel[0] = 0;
00196    
00197    if (ast_test_flag(&optflags, OPT_ENDCDR))
00198       ast_cdr_end(cdr);
00199 
00200    if (ast_test_flag(&optflags, OPT_ANSLOCK))
00201       ast_set_flag(cdr, AST_CDR_FLAG_ANSLOCKED);
00202    
00203    if (ast_test_flag(&optflags, OPT_DONTOUCH))
00204       ast_set_flag(cdr, AST_CDR_FLAG_DONT_TOUCH);
00205       
00206    ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
00207 }
00208 
00209 static int forkcdr_exec(struct ast_channel *chan, void *data)
00210 {
00211    int res = 0;
00212    char *argcopy = NULL;
00213    struct ast_flags flags = {0};
00214    char *opts[OPT_ARG_ARRAY_SIZE];
00215    AST_DECLARE_APP_ARGS(arglist,
00216       AST_APP_ARG(options);
00217    );
00218 
00219    if (!chan->cdr) {
00220       ast_log(LOG_WARNING, "Channel does not have a CDR\n");
00221       return 0;
00222    }
00223 
00224    argcopy = ast_strdupa(data);
00225 
00226    AST_STANDARD_APP_ARGS(arglist, argcopy);
00227 
00228    opts[OPT_ARG_VARSET] = 0;
00229 
00230    if (!ast_strlen_zero(arglist.options))
00231       ast_app_parse_options(forkcdr_exec_options, &flags, opts, arglist.options);
00232    
00233    if (!ast_strlen_zero(data))
00234       ast_set2_flag(chan->cdr, ast_test_flag(&flags, OPT_KEEPVARS), AST_CDR_FLAG_KEEP_VARS);
00235    
00236    ast_cdr_fork(chan, flags, opts[OPT_ARG_VARSET]);
00237 
00238    return res;
00239 }
00240 
00241 static int unload_module(void)
00242 {
00243    return ast_unregister_application(app);
00244 }
00245 
00246 static int load_module(void)
00247 {
00248    return ast_register_application(app, forkcdr_exec, synopsis, descrip);
00249 }
00250 
00251 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Fork The CDR into 2 separate entities");

Generated on Wed Oct 28 11:45:25 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6