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 /*** MODULEINFO
00030    <support_level>core</support_level>
00031  ***/
00032 
00033 #include "asterisk.h"
00034 
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 420124 $")
00036 
00037 #include "asterisk/file.h"
00038 #include "asterisk/channel.h"
00039 #include "asterisk/pbx.h"
00040 #include "asterisk/cdr.h"
00041 #include "asterisk/app.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/stasis.h"
00044 #include "asterisk/stasis_message_router.h"
00045 
00046 /*** DOCUMENTATION
00047    <application name="ForkCDR" language="en_US">
00048       <synopsis>
00049          Forks the current Call Data Record for this channel.
00050       </synopsis>
00051       <syntax>
00052          <parameter name="options">
00053             <optionlist>
00054                <option name="a">
00055                   <para>If the channel is answered, set the answer time on
00056                   the forked CDR to the current time. If this option is
00057                   not used, the answer time on the forked CDR will be the
00058                   answer time on the original CDR. If the channel is not
00059                   answered, this option has no effect.</para>
00060                   <para>Note that this option is implicitly assumed if the
00061                   <literal>r</literal> option is used.</para>
00062                </option>
00063                <option name="e">
00064                   <para>End (finalize) the original CDR.</para>
00065                </option>
00066                <option name="r">
00067                   <para>Reset the start and answer times on the forked CDR.
00068                   This will set the start and answer times (if the channel
00069                   is answered) to be set to the current time.</para>
00070                   <para>Note that this option implicitly assumes the
00071                   <literal>a</literal> option.</para>
00072                </option>
00073                <option name="v">
00074                   <para>Do not copy CDR variables and attributes from the
00075                   original CDR to the forked CDR.</para>
00076                   <warning><para>This option has changed. Previously, the
00077                   variables were removed from the original CDR. This no
00078                   longer occurs - this option now controls whether or not
00079                   a forked CDR inherits the variables from the original
00080                   CDR.</para></warning>
00081                </option>
00082             </optionlist>
00083          </parameter>
00084       </syntax>
00085       <description>
00086          <para>Causes the Call Data Record engine to fork a new CDR starting
00087          from the time the application is executed. The forked CDR will be
00088          linked to the end of the CDRs associated with the channel.</para>
00089       </description>
00090       <see-also>
00091          <ref type="function">CDR</ref>
00092          <ref type="application">NoCDR</ref>
00093          <ref type="application">ResetCDR</ref>
00094       </see-also>
00095    </application>
00096  ***/
00097 
00098 static char *app = "ForkCDR";
00099 
00100 AST_APP_OPTIONS(forkcdr_exec_options, {
00101    AST_APP_OPTION('a', AST_CDR_FLAG_SET_ANSWER),
00102    AST_APP_OPTION('e', AST_CDR_FLAG_FINALIZE),
00103    AST_APP_OPTION('r', AST_CDR_FLAG_RESET),
00104    AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),
00105 });
00106 
00107 STASIS_MESSAGE_TYPE_DEFN_LOCAL(forkcdr_message_type);
00108 
00109 /*! \internal \brief Message payload for the Stasis message sent to fork the CDR */
00110 struct fork_cdr_message_payload {
00111    /*! The name of the channel whose CDR will be forked */
00112    const char *channel_name;
00113    /*! Option flags that control how the CDR will be forked */
00114    struct ast_flags *flags;
00115 };
00116 
00117 static void forkcdr_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
00118 {
00119    struct fork_cdr_message_payload *payload;
00120 
00121    if (stasis_message_type(message) != forkcdr_message_type()) {
00122       return;
00123    }
00124 
00125    payload = stasis_message_data(message);
00126    if (!payload) {
00127       return;
00128    }
00129 
00130    if (ast_cdr_fork(payload->channel_name, payload->flags)) {
00131       ast_log(AST_LOG_WARNING, "Failed to fork CDR for channel %s\n",
00132          payload->channel_name);
00133    }
00134 }
00135 
00136 static int forkcdr_exec(struct ast_channel *chan, const char *data)
00137 {
00138    RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
00139    RAII_VAR(struct fork_cdr_message_payload *, payload, NULL, ao2_cleanup);
00140    RAII_VAR(struct stasis_message_router *, router, ast_cdr_message_router(), ao2_cleanup);
00141 
00142    char *parse;
00143    struct ast_flags flags = { 0, };
00144    AST_DECLARE_APP_ARGS(args,
00145       AST_APP_ARG(options);
00146    );
00147 
00148    parse = ast_strdupa(data);
00149 
00150    AST_STANDARD_APP_ARGS(args, parse);
00151 
00152    if (!ast_strlen_zero(args.options)) {
00153       ast_app_parse_options(forkcdr_exec_options, &flags, NULL, args.options);
00154    }
00155 
00156    if (!forkcdr_message_type()) {
00157       ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message type\n",
00158          ast_channel_name(chan));
00159       return -1;
00160    }
00161 
00162    payload = ao2_alloc(sizeof(*payload), NULL);
00163    if (!payload) {
00164       return -1;
00165    }
00166 
00167    if (!router) {
00168       ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
00169          ast_channel_name(chan));
00170       return -1;
00171    }
00172 
00173    payload->channel_name = ast_channel_name(chan);
00174    payload->flags = &flags;
00175    message = stasis_message_create(forkcdr_message_type(), payload);
00176    if (!message) {
00177       ast_log(AST_LOG_WARNING, "Failed to fork CDR for channel %s: unable to create message\n",
00178          ast_channel_name(chan));
00179       return -1;
00180    }
00181    stasis_message_router_publish_sync(router, message);
00182 
00183    return 0;
00184 }
00185 
00186 static int unload_module(void)
00187 {
00188    RAII_VAR(struct stasis_message_router *, router, ast_cdr_message_router(), ao2_cleanup);
00189 
00190    if (router) {
00191       stasis_message_router_remove(router, forkcdr_message_type());
00192    }
00193    STASIS_MESSAGE_TYPE_CLEANUP(forkcdr_message_type);
00194    ast_unregister_application(app);
00195    return 0;
00196 }
00197 
00198 static int load_module(void)
00199 {
00200    RAII_VAR(struct stasis_message_router *, router, ast_cdr_message_router(), ao2_cleanup);
00201    int res = 0;
00202 
00203    if (!router) {
00204       return AST_MODULE_LOAD_FAILURE;
00205    }
00206 
00207    res |= STASIS_MESSAGE_TYPE_INIT(forkcdr_message_type);
00208    res |= ast_register_application_xml(app, forkcdr_exec);
00209    res |= stasis_message_router_add(router, forkcdr_message_type(),
00210                                     forkcdr_callback, NULL);
00211 
00212    if (res) {
00213       return AST_MODULE_LOAD_FAILURE;
00214    }
00215    return AST_MODULE_LOAD_SUCCESS;
00216 }
00217 
00218 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Fork The CDR into 2 separate entities");

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