a2367c07f8
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r118858 | murf | 2008-05-28 18:25:28 -0600 (Wed, 28 May 2008) | 46 lines (closes issue #10668) (closes issue #11721) (closes issue #12726) Reported by: arkadia Tested by: murf These changes: 1. revert the changes made via bug 10668; I should have known that such changes, even tho they made sense at the time, seemed like an omission, etc, were actually integral to the CDR system via forkCDR. It makes sense to me now that forkCDR didn't natively end any CDR's, but rather depended on natively closing them all at hangup time via traversing and closing them all, whether locked or not. I still don't completely understand the benefits of setvar and answer operating on locked cdrs, but I've seen enough to revert those changes also, and stop messing up users who depended on that behavior. bug 12726 found reverting the changes fixed his changes, and after a long review and working on forkCDR, I can see why. 2. Apply the suggested enhancements proposed in 10668, but in a completely compatible way. ForkCDR will behave exactly as before, but now has new options that will allow some actions to be taken that will slightly modify the outcome and side-effects of forkCDR. Based on conversations I've had with various people, these small tweaks will allow some users to get the behavior they need. For instance, users executing forkCDR in an AGI script will find the answer time set, and DISPOSITION set, a situation not covered when the routines were first written. 3. A small problem in the cdr serializer would output answer and end times even when they were not set. This is now fixed. ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@118880 65c4cc65-6c06-0410-ace0-fbb531ad65f3
181 lines
5 KiB
C
181 lines
5 KiB
C
/*
|
|
* Asterisk -- An open source telephony toolkit.
|
|
*
|
|
* Copyright (C) 1999 - 2005, Anthony Minessale anthmct@yahoo.com
|
|
* Development of this app Sponsered/Funded by TAAN Softworks Corp
|
|
*
|
|
* See http://www.asterisk.org for more information about
|
|
* the Asterisk project. Please do not directly contact
|
|
* any of the maintainers of this project for assistance;
|
|
* the project provides a web site, mailing lists and IRC
|
|
* channels for your use.
|
|
*
|
|
* This program is free software, distributed under the terms of
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
* at the top of the source tree.
|
|
*/
|
|
|
|
/*! \file
|
|
*
|
|
* \brief Fork CDR application
|
|
*
|
|
* \author Anthony Minessale anthmct@yahoo.com
|
|
*
|
|
* \note Development of this app Sponsored/Funded by TAAN Softworks Corp
|
|
*
|
|
* \ingroup applications
|
|
*/
|
|
|
|
#include "asterisk.h"
|
|
|
|
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|
|
|
#include "asterisk/file.h"
|
|
#include "asterisk/channel.h"
|
|
#include "asterisk/pbx.h"
|
|
#include "asterisk/cdr.h"
|
|
#include "asterisk/app.h"
|
|
#include "asterisk/module.h"
|
|
|
|
static char *app = "ForkCDR";
|
|
static char *synopsis =
|
|
"Forks the Call Data Record";
|
|
static char *descrip =
|
|
" ForkCDR([options]): Causes the Call Data Record to fork an additional\n"
|
|
"cdr record starting from the time of the fork call\n"
|
|
" Options:\n"
|
|
" a - update the answer time on the NEW CDR just after it's been inited..\n"
|
|
" The new CDR may have been answered already, the reset that forkcdr.\n"
|
|
" does will erase the answer time. This will bring it back, but.\n"
|
|
" the answer time will be a copy of the fork/start time. It will.\n"
|
|
" only do this if the initial cdr was indeed already answered..\n"
|
|
" D - Copy the disposition forward from the old cdr, after the .\n"
|
|
" init..\n"
|
|
" d - Clear the dstchannel on the new CDR after reset..\n"
|
|
" e - end the original CDR. Do this after all the necc. data.\n"
|
|
" is copied from the original CDR to the new forked CDR..\n"
|
|
" R - do NOT reset the new cdr..\n"
|
|
" s(name=val) - Set the CDR var 'name' in the original CDR, with value.\n"
|
|
" 'val'.\n"
|
|
" v - When the new CDR is forked, it gets a copy of the vars attached\n"
|
|
" to the current CDR. The vars attached to the original CDR are removed\n"
|
|
" unless this option is specified.\n";
|
|
|
|
|
|
enum {
|
|
OPT_SETANS = (1 << 0),
|
|
OPT_SETDISP = (1 << 1),
|
|
OPT_RESETDEST = (1 << 2),
|
|
OPT_ENDCDR = (1 << 3),
|
|
OPT_NORESET = (1 << 4),
|
|
OPT_KEEPVARS = (1 << 5),
|
|
OPT_VARSET = (1 << 6),
|
|
};
|
|
|
|
enum {
|
|
OPT_ARG_VARSET = 0,
|
|
/* note: this entry _MUST_ be the last one in the enum */
|
|
OPT_ARG_ARRAY_SIZE,
|
|
};
|
|
|
|
AST_APP_OPTIONS(forkcdr_exec_options, {
|
|
AST_APP_OPTION('a', OPT_SETANS),
|
|
AST_APP_OPTION('d', OPT_SETDISP),
|
|
AST_APP_OPTION('D', OPT_RESETDEST),
|
|
AST_APP_OPTION('e', OPT_ENDCDR),
|
|
AST_APP_OPTION('R', OPT_NORESET),
|
|
AST_APP_OPTION_ARG('s', OPT_VARSET, OPT_ARG_VARSET),
|
|
AST_APP_OPTION('v', OPT_KEEPVARS),
|
|
});
|
|
|
|
static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set)
|
|
{
|
|
struct ast_cdr *cdr;
|
|
struct ast_cdr *newcdr;
|
|
struct ast_flags flags = { AST_CDR_FLAG_KEEP_VARS };
|
|
|
|
cdr = chan->cdr;
|
|
|
|
while (cdr->next)
|
|
cdr = cdr->next;
|
|
|
|
if (!(newcdr = ast_cdr_dup(cdr)))
|
|
return;
|
|
|
|
ast_cdr_append(cdr, newcdr);
|
|
|
|
if (!ast_test_flag(&optflags, OPT_NORESET))
|
|
ast_cdr_reset(newcdr, &flags);
|
|
|
|
if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
|
|
ast_cdr_free_vars(cdr, 0);
|
|
|
|
if (!ast_strlen_zero(set)) {
|
|
char *varname = ast_strdupa(set), *varval;
|
|
varval = strchr(varname,'=');
|
|
if (varval) {
|
|
*varval = 0;
|
|
varval++;
|
|
ast_cdr_setvar(cdr, varname, varval, 0);
|
|
}
|
|
}
|
|
|
|
if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer))
|
|
newcdr->answer = newcdr->start;
|
|
|
|
if (ast_test_flag(&optflags, OPT_SETDISP))
|
|
newcdr->disposition = cdr->disposition;
|
|
|
|
if (ast_test_flag(&optflags, OPT_RESETDEST))
|
|
newcdr->dstchannel[0] = 0;
|
|
|
|
if (ast_test_flag(&optflags, OPT_ENDCDR))
|
|
ast_cdr_end(cdr);
|
|
|
|
ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
|
|
}
|
|
|
|
static int forkcdr_exec(struct ast_channel *chan, void *data)
|
|
{
|
|
int res = 0;
|
|
char *argcopy = NULL;
|
|
struct ast_flags flags = {0};
|
|
char *opts[OPT_ARG_ARRAY_SIZE];
|
|
AST_DECLARE_APP_ARGS(arglist,
|
|
AST_APP_ARG(options);
|
|
);
|
|
|
|
if (!chan->cdr) {
|
|
ast_log(LOG_WARNING, "Channel does not have a CDR\n");
|
|
return 0;
|
|
}
|
|
|
|
argcopy = ast_strdupa(data);
|
|
|
|
AST_STANDARD_APP_ARGS(arglist, argcopy);
|
|
|
|
if (!ast_strlen_zero(arglist.options)) {
|
|
ast_app_parse_options(forkcdr_exec_options, &flags, opts, arglist.options);
|
|
} else
|
|
opts[OPT_ARG_VARSET] = 0;
|
|
|
|
if (!ast_strlen_zero(data))
|
|
ast_set2_flag(chan->cdr, ast_test_flag(&flags, OPT_KEEPVARS), AST_CDR_FLAG_KEEP_VARS);
|
|
|
|
ast_cdr_fork(chan, flags, opts[OPT_ARG_VARSET]);
|
|
|
|
return res;
|
|
}
|
|
|
|
static int unload_module(void)
|
|
{
|
|
return ast_unregister_application(app);
|
|
}
|
|
|
|
static int load_module(void)
|
|
{
|
|
return ast_register_application(app, forkcdr_exec, synopsis, descrip);
|
|
}
|
|
|
|
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Fork The CDR into 2 separate entities");
|