app_cdr.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Martin Pycko <martinp@digium.com>
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 Applications connected with CDR engine
00022  *
00023  * \author Martin Pycko <martinp@digium.com>
00024  *
00025  * \ingroup applications
00026  */
00027 
00028 /*** MODULEINFO
00029    <support_level>core</support_level>
00030  ***/
00031 
00032 #include "asterisk.h"
00033 
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 405314 $")
00035 
00036 #include "asterisk/channel.h"
00037 #include "asterisk/module.h"
00038 #include "asterisk/app.h"
00039 #include "asterisk/stasis.h"
00040 #include "asterisk/stasis_message_router.h"
00041 
00042 /*** DOCUMENTATION
00043    <application name="NoCDR" language="en_US">
00044       <synopsis>
00045          Tell Asterisk to not maintain a CDR for this channel.
00046       </synopsis>
00047       <syntax />
00048       <description>
00049          <para>This application will tell Asterisk not to maintain a CDR for
00050          the current channel. This does <emphasis>NOT</emphasis> mean that
00051          information is not tracked; rather, if the channel is hung up no
00052          CDRs will be created for that channel.</para>
00053          <para>If a subsequent call to ResetCDR occurs, all non-finalized
00054          CDRs created for the channel will be enabled.</para>
00055          <note><para>This application is deprecated. Please use the CDR_PROP
00056          function to disable CDRs on a channel.</para></note>
00057       </description>
00058       <see-also>
00059          <ref type="application">ResetCDR</ref>
00060          <ref type="function">CDR_PROP</ref>
00061       </see-also>
00062    </application>
00063    <application name="ResetCDR" language="en_US">
00064       <synopsis>
00065          Resets the Call Data Record.
00066       </synopsis>
00067       <syntax>
00068          <parameter name="options">
00069             <optionlist>
00070                <option name="v">
00071                   <para>Save the CDR variables during the reset.</para>
00072                </option>
00073                <option name="e">
00074                   <para>Enable the CDRs for this channel only (negate
00075                   effects of NoCDR).</para>
00076                </option>
00077             </optionlist>
00078          </parameter>
00079       </syntax>
00080       <description>
00081          <para>This application causes the Call Data Record to be reset.
00082          Depending on the flags passed in, this can have several effects.
00083          With no options, a reset does the following:</para>
00084          <para>1. The <literal>start</literal> time is set to the current time.</para>
00085          <para>2. If the channel is answered, the <literal>answer</literal> time is set to the
00086          current time.</para>
00087          <para>3. All variables are wiped from the CDR. Note that this step
00088          can be prevented with the <literal>v</literal> option.</para>
00089          <para>On the other hand, if the <literal>e</literal> option is
00090          specified, the effects of the NoCDR application will be lifted. CDRs
00091          will be re-enabled for this channel.</para>
00092          <note><para>The <literal>e</literal> option is deprecated. Please
00093          use the CDR_PROP function instead.</para></note>
00094       </description>
00095       <see-also>
00096          <ref type="application">ForkCDR</ref>
00097          <ref type="application">NoCDR</ref>
00098          <ref type="function">CDR_PROP</ref>
00099       </see-also>
00100    </application>
00101  ***/
00102 
00103 static const char nocdr_app[] = "NoCDR";
00104 static const char resetcdr_app[] = "ResetCDR";
00105 
00106 enum reset_cdr_options {
00107    OPT_DISABLE_DISPATCH = (1 << 0),
00108    OPT_KEEP_VARS = (1 << 1),
00109    OPT_ENABLE = (1 << 2),
00110 };
00111 
00112 AST_APP_OPTIONS(resetcdr_opts, {
00113    AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),
00114    AST_APP_OPTION('e', AST_CDR_FLAG_DISABLE_ALL),
00115 });
00116 
00117 STASIS_MESSAGE_TYPE_DEFN_LOCAL(appcdr_message_type);
00118 
00119 /*! \internal \brief Payload for the Stasis message sent to manipulate a CDR */
00120 struct app_cdr_message_payload {
00121    /*! The name of the channel to be manipulated */
00122    const char *channel_name;
00123    /*! Disable the CDR for this channel */
00124    int disable:1;
00125    /*! Re-enable the CDR for this channel */
00126    int reenable:1;
00127    /*! Reset the CDR */
00128    int reset:1;
00129    /*! If reseting the CDR, keep the variables */
00130    int keep_variables:1;
00131 };
00132 
00133 static void appcdr_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
00134 {
00135    struct app_cdr_message_payload *payload;
00136 
00137    if (stasis_message_type(message) != appcdr_message_type()) {
00138       return;
00139    }
00140 
00141    payload = stasis_message_data(message);
00142    if (!payload) {
00143       return;
00144    }
00145 
00146    if (payload->disable) {
00147       if (ast_cdr_set_property(payload->channel_name, AST_CDR_FLAG_DISABLE_ALL)) {
00148          ast_log(AST_LOG_WARNING, "Failed to disable CDRs on channel %s\n",
00149             payload->channel_name);
00150       }
00151    }
00152 
00153    if (payload->reenable) {
00154       if (ast_cdr_clear_property(payload->channel_name, AST_CDR_FLAG_DISABLE_ALL)) {
00155          ast_log(AST_LOG_WARNING, "Failed to enable CDRs on channel %s\n",
00156             payload->channel_name);
00157       }
00158    }
00159 
00160    if (payload->reset) {
00161       if (ast_cdr_reset(payload->channel_name, payload->keep_variables)) {
00162          ast_log(AST_LOG_WARNING, "Failed to reset CDRs on channel %s\n",
00163             payload->channel_name);
00164       }
00165    }
00166 }
00167 
00168 static int publish_app_cdr_message(struct ast_channel *chan, struct app_cdr_message_payload *payload)
00169 {
00170    RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
00171    RAII_VAR(struct stasis_message_router *, router, ast_cdr_message_router(), ao2_cleanup);
00172 
00173    if (!router) {
00174       ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
00175          ast_channel_name(chan));
00176       return -1;
00177    }
00178 
00179    message = stasis_message_create(appcdr_message_type(), payload);
00180    if (!message) {
00181       ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
00182          payload->channel_name);
00183       return -1;
00184    }
00185    stasis_message_router_publish_sync(router, message);
00186 
00187    return 0;
00188 }
00189 
00190 static int resetcdr_exec(struct ast_channel *chan, const char *data)
00191 {
00192    RAII_VAR(struct app_cdr_message_payload *, payload,
00193       ao2_alloc(sizeof(*payload), NULL), ao2_cleanup);
00194    char *args;
00195    struct ast_flags flags = { 0 };
00196 
00197    if (!payload) {
00198       return -1;
00199    }
00200 
00201    if (!ast_strlen_zero(data)) {
00202       args = ast_strdupa(data);
00203       ast_app_parse_options(resetcdr_opts, &flags, NULL, args);
00204    }
00205 
00206    payload->channel_name = ast_channel_name(chan);
00207    payload->reset = 1;
00208 
00209    if (ast_test_flag(&flags, AST_CDR_FLAG_DISABLE_ALL)) {
00210       payload->reenable = 1;
00211    }
00212 
00213    if (ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
00214       payload->keep_variables = 1;
00215    }
00216 
00217    return publish_app_cdr_message(chan, payload);
00218 }
00219 
00220 static int nocdr_exec(struct ast_channel *chan, const char *data)
00221 {
00222    RAII_VAR(struct app_cdr_message_payload *, payload,
00223       ao2_alloc(sizeof(*payload), NULL), ao2_cleanup);
00224 
00225    if (!payload) {
00226       return -1;
00227    }
00228 
00229    payload->channel_name = ast_channel_name(chan);
00230    payload->disable = 1;
00231 
00232    return publish_app_cdr_message(chan, payload);
00233 }
00234 
00235 static int unload_module(void)
00236 {
00237    RAII_VAR(struct stasis_message_router *, router, ast_cdr_message_router(), ao2_cleanup);
00238 
00239    if (router) {
00240       stasis_message_router_remove(router, appcdr_message_type());
00241    }
00242    STASIS_MESSAGE_TYPE_CLEANUP(appcdr_message_type);
00243    ast_unregister_application(nocdr_app);
00244    ast_unregister_application(resetcdr_app);
00245    return 0;
00246 }
00247 
00248 static int load_module(void)
00249 {
00250    RAII_VAR(struct stasis_message_router *, router, ast_cdr_message_router(), ao2_cleanup);
00251    int res = 0;
00252 
00253    if (!router) {
00254       return AST_MODULE_LOAD_FAILURE;
00255    }
00256 
00257    res |= STASIS_MESSAGE_TYPE_INIT(appcdr_message_type);
00258    res |= ast_register_application_xml(nocdr_app, nocdr_exec);
00259    res |= ast_register_application_xml(resetcdr_app, resetcdr_exec);
00260    res |= stasis_message_router_add(router, appcdr_message_type(),
00261                                     appcdr_callback, NULL);
00262 
00263    if (res) {
00264       return AST_MODULE_LOAD_FAILURE;
00265    }
00266    return AST_MODULE_LOAD_SUCCESS;
00267 }
00268 
00269 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Tell Asterisk to not maintain a CDR for the current call");

Generated on Thu Apr 16 06:27:08 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6