Sat Aug 6 00:39:20 2011

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

Generated on Sat Aug 6 00:39:20 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7