Wed Apr 6 11:29:45 2011

Asterisk developer's documentation


func_cdr.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999-2006, Digium, Inc.
00005  *
00006  * Portions Copyright (C) 2005, Anthony Minessale II
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief  Call Detail Record related dialplan functions
00022  *
00023  * \author Anthony Minessale II 
00024  *
00025  * \ingroup functions
00026  */
00027 
00028 #include "asterisk.h"
00029 
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 269153 $")
00031 
00032 #include "asterisk/module.h"
00033 #include "asterisk/channel.h"
00034 #include "asterisk/pbx.h"
00035 #include "asterisk/utils.h"
00036 #include "asterisk/app.h"
00037 #include "asterisk/cdr.h"
00038 
00039 /*** DOCUMENTATION
00040    <function name="CDR" language="en_US">
00041       <synopsis>
00042          Gets or sets a CDR variable.
00043       </synopsis> 
00044       <syntax>
00045          <parameter name="name" required="true">
00046             <para>CDR field name:</para>
00047             <enumlist>
00048                <enum name="clid">
00049                   <para>Caller ID.</para>
00050                </enum>
00051                <enum name="lastdata">
00052                   <para>Last application arguments.</para>
00053                </enum>
00054                <enum name="disposition">
00055                   <para>ANSWERED, NO ANSWER, BUSY, FAILED.</para>
00056                </enum>
00057                <enum name="src">
00058                   <para>Source.</para>
00059                </enum>
00060                <enum name="start">
00061                   <para>Time the call started.</para>
00062                </enum>
00063                <enum name="amaflags">
00064                   <para>DOCUMENTATION, BILL, IGNORE, etc.</para>
00065                </enum>
00066                <enum name="dst">
00067                   <para>Destination.</para>
00068                </enum>
00069                <enum name="answer">
00070                   <para>Time the call was answered.</para>
00071                </enum>
00072                <enum name="accountcode">
00073                   <para>The channel's account code.</para>
00074                </enum>
00075                <enum name="dcontext">
00076                   <para>Destination context.</para>
00077                </enum>
00078                <enum name="end">
00079                   <para>Time the call ended.</para>
00080                </enum>
00081                <enum name="uniqueid">
00082                   <para>The channel's unique id.</para>
00083                </enum>
00084                <enum name="dstchannel">
00085                   <para>Destination channel.</para>
00086                </enum>
00087                <enum name="duration">
00088                   <para>Duration of the call.</para>
00089                </enum>
00090                <enum name="userfield">
00091                   <para>The channel's user specified field.</para>
00092                </enum>
00093                <enum name="lastapp">
00094                   <para>Last application.</para>
00095                </enum>
00096                <enum name="billsec">
00097                   <para>Duration of the call once it was answered.</para>
00098                </enum>
00099                <enum name="channel">
00100                   <para>Channel name.</para>
00101                </enum>
00102                <enum name="sequence">
00103                   <para>CDR sequence number.</para>
00104                </enum>
00105             </enumlist>
00106          </parameter>
00107          <parameter name="options" required="false">
00108             <optionlist>
00109                <option name="f">
00110                   <para>Returns billsec or duration fields as floating point values.</para>
00111                </option>
00112                <option name="l">
00113                   <para>Uses the most recent CDR on a channel with multiple records</para>
00114                </option>
00115                <option name="r">
00116                   <para>Searches the entire stack of CDRs on the channel.</para>
00117                </option>
00118                <option name="s">
00119                   <para>Skips any CDR's that are marked 'LOCKED' due to forkCDR() calls.
00120                   (on setting/writing CDR vars only)</para>
00121                </option>
00122                <option name="u">
00123                   <para>Retrieves the raw, unprocessed value.</para>
00124                   <para>For example, 'start', 'answer', and 'end' will be retrieved as epoch
00125                   values, when the <literal>u</literal> option is passed, but formatted as YYYY-MM-DD HH:MM:SS
00126                   otherwise.  Similarly, disposition and amaflags will return their raw
00127                   integral values.</para>
00128                </option>
00129             </optionlist>
00130          </parameter>
00131       </syntax>
00132       <description>
00133          <para>All of the CDR field names are read-only, except for <literal>accountcode</literal>,
00134          <literal>userfield</literal>, and <literal>amaflags</literal>. You may, however, supply
00135          a name not on the above list, and create your own variable, whose value can be changed
00136          with this function, and this variable will be stored on the cdr.</para>
00137          <note><para>For setting CDR values, the <literal>l</literal> flag does not apply to
00138          setting the <literal>accountcode</literal>, <literal>userfield</literal>, or
00139          <literal>amaflags</literal>.</para></note>
00140          <para>Raw values for <literal>disposition</literal>:</para>
00141          <enumlist>
00142             <enum name="0">
00143                <para>NO ANSWER</para>
00144             </enum>
00145             <enum name="1">
00146                <para>NO ANSWER (NULL record)</para>
00147             </enum>
00148             <enum name="2">
00149                <para>FAILED</para>
00150             </enum>
00151             <enum name="4">
00152                <para>BUSY</para>
00153             </enum>
00154             <enum name="8">
00155                <para>ANSWERED</para>
00156             </enum>
00157          </enumlist>
00158          <para>Raw values for <literal>amaflags</literal>:</para>
00159          <enumlist>
00160             <enum name="1">
00161                <para>OMIT</para>
00162             </enum>
00163             <enum name="2">
00164                <para>BILLING</para>
00165             </enum>
00166             <enum name="3">
00167                <para>DOCUMENTATION</para>
00168             </enum>
00169          </enumlist>
00170          <para>Example: exten => 1,1,Set(CDR(userfield)=test)</para>
00171       </description>
00172    </function>
00173  ***/
00174 
00175 enum cdr_option_flags {
00176    OPT_RECURSIVE = (1 << 0),
00177    OPT_UNPARSED = (1 << 1),
00178    OPT_LAST = (1 << 2),
00179    OPT_SKIPLOCKED = (1 << 3),
00180    OPT_FLOAT = (1 << 4),
00181 };
00182 
00183 AST_APP_OPTIONS(cdr_func_options, {
00184    AST_APP_OPTION('f', OPT_FLOAT),
00185    AST_APP_OPTION('l', OPT_LAST),
00186    AST_APP_OPTION('r', OPT_RECURSIVE),
00187    AST_APP_OPTION('s', OPT_SKIPLOCKED),
00188    AST_APP_OPTION('u', OPT_UNPARSED),
00189 });
00190 
00191 static int cdr_read(struct ast_channel *chan, const char *cmd, char *parse,
00192           char *buf, size_t len)
00193 {
00194    char *ret;
00195    struct ast_flags flags = { 0 };
00196    struct ast_cdr *cdr = chan ? chan->cdr : NULL;
00197    AST_DECLARE_APP_ARGS(args,
00198               AST_APP_ARG(variable);
00199               AST_APP_ARG(options);
00200    );
00201 
00202    if (ast_strlen_zero(parse))
00203       return -1;
00204 
00205    if (!cdr)
00206       return -1;
00207 
00208    AST_STANDARD_APP_ARGS(args, parse);
00209 
00210    if (!ast_strlen_zero(args.options))
00211       ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
00212 
00213    if (ast_test_flag(&flags, OPT_LAST))
00214       while (cdr->next)
00215          cdr = cdr->next;
00216 
00217    if (ast_test_flag(&flags, OPT_SKIPLOCKED))
00218       while (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && cdr->next)
00219          cdr = cdr->next;
00220 
00221    if (!strcasecmp("billsec", args.variable) && ast_test_flag(&flags, OPT_FLOAT)) {
00222       if (!ast_tvzero(cdr->answer)) {
00223          double hrtime;
00224 
00225          if(!ast_tvzero(cdr->end))
00226             hrtime = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0);
00227          else
00228             hrtime = (double)(ast_tvdiff_us(ast_tvnow(), cdr->answer) / 1000000.0);
00229 
00230          snprintf(buf, len, "%lf", hrtime);
00231       } else {
00232          snprintf(buf, len, "%lf", 0.0);
00233       }
00234       ret = buf;
00235    } else if (!strcasecmp("duration", args.variable) && ast_test_flag(&flags, OPT_FLOAT)) {
00236          double hrtime;
00237 
00238          if(!ast_tvzero(cdr->end))
00239             hrtime = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0);
00240          else
00241             hrtime = (double)(ast_tvdiff_us(ast_tvnow(), cdr->start) / 1000000.0);
00242 
00243          snprintf(buf, len, "%lf", hrtime);
00244 
00245       if (!ast_strlen_zero(buf)) {
00246          ret = buf;
00247       }
00248    } else {
00249       ast_cdr_getvar(cdr, args.variable, &ret, buf, len,
00250                 ast_test_flag(&flags, OPT_RECURSIVE),
00251                ast_test_flag(&flags, OPT_UNPARSED));
00252    }
00253 
00254    return ret ? 0 : -1;
00255 }
00256 
00257 static int cdr_write(struct ast_channel *chan, const char *cmd, char *parse,
00258            const char *value)
00259 {
00260    struct ast_cdr *cdr = chan ? chan->cdr : NULL;
00261    struct ast_flags flags = { 0 };
00262    AST_DECLARE_APP_ARGS(args,
00263               AST_APP_ARG(variable);
00264               AST_APP_ARG(options);
00265    );
00266 
00267    if (ast_strlen_zero(parse) || !value || !chan)
00268       return -1;
00269 
00270    if (!cdr)
00271       return -1;
00272 
00273    AST_STANDARD_APP_ARGS(args, parse);
00274 
00275    if (!ast_strlen_zero(args.options))
00276       ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
00277 
00278    if (ast_test_flag(&flags, OPT_LAST))
00279       while (cdr->next)
00280          cdr = cdr->next;
00281 
00282    if (!strcasecmp(args.variable, "accountcode"))  /* the 'l' flag doesn't apply to setting the accountcode, userfield, or amaflags */
00283       ast_cdr_setaccount(chan, value);
00284    else if (!strcasecmp(args.variable, "peeraccount"))
00285       ast_cdr_setpeeraccount(chan, value);
00286    else if (!strcasecmp(args.variable, "userfield"))
00287       ast_cdr_setuserfield(chan, value);
00288    else if (!strcasecmp(args.variable, "amaflags"))
00289       ast_cdr_setamaflags(chan, value);
00290    else
00291       ast_cdr_setvar(cdr, args.variable, value, ast_test_flag(&flags, OPT_RECURSIVE));
00292       /* No need to worry about the u flag, as all fields for which setting
00293        * 'u' would do anything are marked as readonly. */
00294 
00295    return 0;
00296 }
00297 
00298 static struct ast_custom_function cdr_function = {
00299    .name = "CDR",
00300    .read = cdr_read,
00301    .write = cdr_write,
00302 };
00303 
00304 static int unload_module(void)
00305 {
00306    return ast_custom_function_unregister(&cdr_function);
00307 }
00308 
00309 static int load_module(void)
00310 {
00311    return ast_custom_function_register(&cdr_function);
00312 }
00313 
00314 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call Detail Record (CDR) dialplan function");

Generated on Wed Apr 6 11:29:45 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7