Wed Jan 8 2020 09:49:39

Asterisk developer's documentation


app_forkcdr.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Anthony Minessale anthmct@yahoo.com
5  * Development of this app Sponsered/Funded by TAAN Softworks Corp
6  *
7  * See http://www.asterisk.org for more information about
8  * the Asterisk project. Please do not directly contact
9  * any of the maintainers of this project for assistance;
10  * the project provides a web site, mailing lists and IRC
11  * channels for your use.
12  *
13  * This program is free software, distributed under the terms of
14  * the GNU General Public License Version 2. See the LICENSE file
15  * at the top of the source tree.
16  */
17 
18 /*! \file
19  *
20  * \brief Fork CDR application
21  *
22  * \author Anthony Minessale anthmct@yahoo.com
23  *
24  * \note Development of this app Sponsored/Funded by TAAN Softworks Corp
25  *
26  * \ingroup applications
27  */
28 
29 /*** MODULEINFO
30  <support_level>core</support_level>
31  ***/
32 
33 #include "asterisk.h"
34 
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 408747 $")
36 
37 #include "asterisk/file.h"
38 #include "asterisk/channel.h"
39 #include "asterisk/pbx.h"
40 #include "asterisk/cdr.h"
41 #include "asterisk/app.h"
42 #include "asterisk/module.h"
43 
44 /*** DOCUMENTATION
45  <application name="ForkCDR" language="en_US">
46  <synopsis>
47  Forks the Call Data Record.
48  </synopsis>
49  <syntax>
50  <parameter name="options">
51  <optionlist>
52  <option name="a">
53  <para>Update the answer time on the NEW CDR just after it's been inited.
54  The new CDR may have been answered already. The reset that forkcdr does
55  will erase the answer time. This will bring it back, but the answer time
56  will be a copy of the fork/start time. It will only do this if the initial
57  cdr was indeed already answered.</para>
58  </option>
59  <option name="A">
60  <para>Lock the original CDR against the answer time being updated. This
61  will allow the disposition on the original CDR to remain the same.</para>
62  </option>
63  <option name="d">
64  <para>Copy the disposition forward from the old cdr, after the init.</para>
65  </option>
66  <option name="D">
67  <para>Clear the <literal>dstchannel</literal> on the new CDR after
68  reset.</para>
69  </option>
70  <option name="e">
71  <para>End the original CDR. Do this after all the necessary data is copied
72  from the original CDR to the new forked CDR.</para>
73  </option>
74  <option name="r">
75  <para>Do <emphasis>NOT</emphasis> reset the new cdr.</para>
76  </option>
77  <option name="s(name=val)">
78  <para>Set the CDR var <replaceable>name</replaceable> in the original CDR,
79  with value <replaceable>val</replaceable>.</para>
80  </option>
81  <option name="T">
82  <para>Mark the original CDR with a DONT_TOUCH flag. setvar, answer, and end
83  cdr funcs will obey this flag; normally they don't honor the LOCKED flag
84  set on the original CDR record.</para>
85  <note><para>Using this flag may cause CDR's not to have their end times
86  updated! It is suggested that if you specify this flag, you might wish
87  to use the <literal>e</literal> flag as well!.</para></note>
88  </option>
89  <option name="v">
90  <para>When the new CDR is forked, it gets a copy of the vars attached to
91  the current CDR. The vars attached to the original CDR are removed unless
92  this option is specified.</para>
93  </option>
94  </optionlist>
95  </parameter>
96  </syntax>
97  <description>
98  <para> Causes the Call Data Record to fork an additional cdr record starting from the time
99  of the fork call. This new cdr record will be linked to end of the list of cdr records attached
100  to the channel. The original CDR has a LOCKED flag set, which forces most cdr operations to skip
101  it, except for the functions that set the answer and end times, which ignore the LOCKED flag. This
102  allows all the cdr records in the channel to be 'ended' together when the channel is closed.</para>
103  <para>The CDR() func (when setting CDR values) normally ignores the LOCKED flag also, but has options
104  to vary its behavior. The 'T' option (described below), can override this behavior, but beware
105  the risks.</para>
106  <para>First, this app finds the last cdr record in the list, and makes a copy of it. This new copy
107  will be the newly forked cdr record. Next, this new record is linked to the end of the cdr record list.
108  Next, The new cdr record is RESET (unless you use an option to prevent this)</para>
109  <para>This means that:</para>
110  <para> 1. All flags are unset on the cdr record</para>
111  <para> 2. the start, end, and answer times are all set to zero.</para>
112  <para> 3. the billsec and duration fields are set to zero.</para>
113  <para> 4. the start time is set to the current time.</para>
114  <para> 5. the disposition is set to NULL.</para>
115  <para>Next, unless you specified the <literal>v</literal> option, all variables will be removed from
116  the original cdr record. Thus, the <literal>v</literal> option allows any CDR variables to be replicated
117  to all new forked cdr records. Without the <literal>v</literal> option, the variables on the original
118  are effectively moved to the new forked cdr record.</para>
119  <para>Next, if the <literal>s</literal> option is set, the provided variable and value are set on the
120  original cdr record.</para>
121  <para>Next, if the <literal>a</literal> option is given, and the original cdr record has an answer time
122  set, then the new forked cdr record will have its answer time set to its start time. If the old answer
123  time were carried forward, the answer time would be earlier than the start time, giving strange
124  duration and billsec times.</para>
125  <para>If the <literal>d</literal> option was specified, the disposition is copied from
126  the original cdr record to the new forked cdr. If the <literal>D</literal> option was specified,
127  the destination channel field in the new forked CDR is erased. If the <literal>e</literal> option
128  was specified, the 'end' time for the original cdr record is set to the current time. Future hang-up or
129  ending events will not override this time stamp. If the <literal>A</literal> option is specified,
130  the original cdr record will have it ANS_LOCKED flag set, which prevent future answer events from updating
131  the original cdr record's disposition. Normally, an <literal>ANSWERED</literal> event would mark all cdr
132  records in the chain as <literal>ANSWERED</literal>. If the <literal>T</literal> option is specified,
133  the original cdr record will have its <literal>DONT_TOUCH</literal> flag set, which will force the
134  cdr_answer, cdr_end, and cdr_setvar functions to leave that cdr record alone.</para>
135  <para>And, last but not least, the original cdr record has its LOCKED flag set. Almost all internal
136  CDR functions (except for the funcs that set the end, and answer times, and set a variable) will honor
137  this flag and leave a LOCKED cdr record alone. This means that the newly created forked cdr record
138  will be affected by events transpiring within Asterisk, with the previously noted exceptions.</para>
139  </description>
140  <see-also>
141  <ref type="function">CDR</ref>
142  <ref type="application">NoCDR</ref>
143  <ref type="application">ResetCDR</ref>
144  </see-also>
145  </application>
146  ***/
147 
148 static char *app = "ForkCDR";
149 
150 enum {
151  OPT_SETANS = (1 << 0),
152  OPT_SETDISP = (1 << 1),
153  OPT_RESETDEST = (1 << 2),
154  OPT_ENDCDR = (1 << 3),
155  OPT_NORESET = (1 << 4),
156  OPT_KEEPVARS = (1 << 5),
157  OPT_VARSET = (1 << 6),
158  OPT_ANSLOCK = (1 << 7),
159  OPT_DONTOUCH = (1 << 8),
160 };
161 
162 enum {
164  /* note: this entry _MUST_ be the last one in the enum */
166 };
167 
178 });
179 
180 static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set)
181 {
182  struct ast_cdr *cdr;
183  struct ast_cdr *newcdr;
184  struct ast_flags flags = { AST_CDR_FLAG_KEEP_VARS };
185 
186  cdr = chan->cdr;
187 
188  while (cdr->next)
189  cdr = cdr->next;
190 
191  if (!(newcdr = ast_cdr_dup_unique(cdr)))
192  return;
193 
194  /*
195  * End the original CDR if requested BEFORE appending the new CDR
196  * otherwise we incorrectly end the new CDR also.
197  */
198  if (ast_test_flag(&optflags, OPT_ENDCDR)) {
199  ast_cdr_end(cdr);
200  }
201 
202  ast_cdr_append(cdr, newcdr);
203 
204  if (!ast_test_flag(&optflags, OPT_NORESET))
205  ast_cdr_reset(newcdr, &flags);
206 
208  ast_cdr_free_vars(cdr, 0);
209 
210  if (!ast_strlen_zero(set)) {
211  char *varname = ast_strdupa(set), *varval;
212  varval = strchr(varname,'=');
213  if (varval) {
214  *varval = 0;
215  varval++;
216  ast_cdr_setvar(cdr, varname, varval, 0);
217  }
218  }
219 
220  if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer))
221  newcdr->answer = newcdr->start;
222 
223  if (ast_test_flag(&optflags, OPT_SETDISP))
224  newcdr->disposition = cdr->disposition;
225 
226  if (ast_test_flag(&optflags, OPT_RESETDEST))
227  newcdr->dstchannel[0] = 0;
228 
229  if (ast_test_flag(&optflags, OPT_ANSLOCK))
231 
232  if (ast_test_flag(&optflags, OPT_DONTOUCH))
234 
236 }
237 
238 static int forkcdr_exec(struct ast_channel *chan, const char *data)
239 {
240  int res = 0;
241  char *argcopy = NULL;
242  struct ast_cdr *cdr;
243  struct ast_flags flags = {0};
244  char *opts[OPT_ARG_ARRAY_SIZE];
245  AST_DECLARE_APP_ARGS(arglist,
246  AST_APP_ARG(options);
247  );
248 
249  if (!(cdr = chan->cdr)) {
250  ast_log(LOG_WARNING, "Channel does not have a CDR\n");
251  return 0;
252  }
253 
254  argcopy = ast_strdupa(data);
255 
256  AST_STANDARD_APP_ARGS(arglist, argcopy);
257 
258  opts[OPT_ARG_VARSET] = 0;
259 
260  if (!ast_strlen_zero(arglist.options))
261  ast_app_parse_options(forkcdr_exec_options, &flags, opts, arglist.options);
262 
263  if (!ast_strlen_zero(data)) {
264  int keepvars = ast_test_flag(&flags, OPT_KEEPVARS) ? 1 : 0;
265  while (cdr->next) {
266  cdr = cdr->next;
267  }
268  ast_set2_flag(cdr, keepvars, AST_CDR_FLAG_KEEP_VARS);
269  }
270 
271  ast_cdr_fork(chan, flags, opts[OPT_ARG_VARSET]);
272 
273  return res;
274 }
275 
276 static int unload_module(void)
277 {
278  return ast_unregister_application(app);
279 }
280 
281 static int load_module(void)
282 {
284 }
285 
286 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Fork The CDR into 2 separate entities");
int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur)
Definition: cdr.c:343
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
Definition: app.h:732
Asterisk main include file. File version handling, generic pbx functions.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
Definition: app.h:712
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:94
void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags)
Reset the detail record, optionally posting it first.
Definition: cdr.c:1149
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
void ast_cdr_end(struct ast_cdr *cdr)
End a call.
Definition: cdr.c:933
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
struct ast_cdr * next
Definition: cdr.h:132
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
static char * app
Definition: app_forkcdr.c:148
struct ast_cdr * cdr
Definition: channel.h:766
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
Call Detail Record API.
struct ast_cdr * ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr)
Definition: cdr.c:1216
General Asterisk PBX channel definitions.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Core PBX routines and definitions.
static struct ast_app_option forkcdr_exec_options[128]
Definition: app_forkcdr.c:178
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
struct timeval answer
Definition: cdr.h:102
Responsible for call detail data.
Definition: cdr.h:82
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int unload_module(void)
Definition: app_forkcdr.c:276
static int load_module(void)
Definition: app_forkcdr.c:281
struct timeval start
Definition: cdr.h:100
static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set)
Definition: app_forkcdr.c:180
Structure used to handle boolean flags.
Definition: utils.h:200
struct ast_cdr * ast_cdr_dup_unique(struct ast_cdr *cdr)
Duplicate a record and increment the sequence number.
Definition: cdr.c:190
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static int set(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:208
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
long int disposition
Definition: cdr.h:110
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
void ast_cdr_free_vars(struct ast_cdr *cdr, int recur)
Definition: cdr.c:454
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
Definition: app.h:721
static int forkcdr_exec(struct ast_channel *chan, const char *data)
Definition: app_forkcdr.c:238