Wed Jan 8 2020 09:49:47

Asterisk developer's documentation


func_cdr.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999-2006, Digium, Inc.
5  *
6  * Portions Copyright (C) 2005, Anthony Minessale II
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Call Detail Record related dialplan functions
22  *
23  * \author Anthony Minessale II
24  *
25  * \ingroup functions
26  */
27 
28 /*** MODULEINFO
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 366048 $")
35 
36 #include "asterisk/module.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/pbx.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/app.h"
41 #include "asterisk/cdr.h"
42 
43 /*** DOCUMENTATION
44  <function name="CDR" language="en_US">
45  <synopsis>
46  Gets or sets a CDR variable.
47  </synopsis>
48  <syntax>
49  <parameter name="name" required="true">
50  <para>CDR field name:</para>
51  <enumlist>
52  <enum name="clid">
53  <para>Caller ID.</para>
54  </enum>
55  <enum name="lastdata">
56  <para>Last application arguments.</para>
57  </enum>
58  <enum name="disposition">
59  <para>ANSWERED, NO ANSWER, BUSY, FAILED.</para>
60  </enum>
61  <enum name="src">
62  <para>Source.</para>
63  </enum>
64  <enum name="start">
65  <para>Time the call started.</para>
66  </enum>
67  <enum name="amaflags">
68  <para>DOCUMENTATION, BILL, IGNORE, etc.</para>
69  </enum>
70  <enum name="dst">
71  <para>Destination.</para>
72  </enum>
73  <enum name="answer">
74  <para>Time the call was answered.</para>
75  </enum>
76  <enum name="accountcode">
77  <para>The channel's account code.</para>
78  </enum>
79  <enum name="dcontext">
80  <para>Destination context.</para>
81  </enum>
82  <enum name="end">
83  <para>Time the call ended.</para>
84  </enum>
85  <enum name="uniqueid">
86  <para>The channel's unique id.</para>
87  </enum>
88  <enum name="dstchannel">
89  <para>Destination channel.</para>
90  </enum>
91  <enum name="duration">
92  <para>Duration of the call.</para>
93  </enum>
94  <enum name="userfield">
95  <para>The channel's user specified field.</para>
96  </enum>
97  <enum name="lastapp">
98  <para>Last application.</para>
99  </enum>
100  <enum name="billsec">
101  <para>Duration of the call once it was answered.</para>
102  </enum>
103  <enum name="channel">
104  <para>Channel name.</para>
105  </enum>
106  <enum name="sequence">
107  <para>CDR sequence number.</para>
108  </enum>
109  </enumlist>
110  </parameter>
111  <parameter name="options" required="false">
112  <optionlist>
113  <option name="f">
114  <para>Returns billsec or duration fields as floating point values.</para>
115  </option>
116  <option name="l">
117  <para>Uses the most recent CDR on a channel with multiple records</para>
118  </option>
119  <option name="r">
120  <para>Searches the entire stack of CDRs on the channel.</para>
121  </option>
122  <option name="s">
123  <para>Skips any CDR's that are marked 'LOCKED' due to forkCDR() calls.
124  (on setting/writing CDR vars only)</para>
125  </option>
126  <option name="u">
127  <para>Retrieves the raw, unprocessed value.</para>
128  <para>For example, 'start', 'answer', and 'end' will be retrieved as epoch
129  values, when the <literal>u</literal> option is passed, but formatted as YYYY-MM-DD HH:MM:SS
130  otherwise. Similarly, disposition and amaflags will return their raw
131  integral values.</para>
132  </option>
133  </optionlist>
134  </parameter>
135  </syntax>
136  <description>
137  <para>All of the CDR field names are read-only, except for <literal>accountcode</literal>,
138  <literal>userfield</literal>, and <literal>amaflags</literal>. You may, however, supply
139  a name not on the above list, and create your own variable, whose value can be changed
140  with this function, and this variable will be stored on the cdr.</para>
141  <note><para>For setting CDR values, the <literal>l</literal> flag does not apply to
142  setting the <literal>accountcode</literal>, <literal>userfield</literal>, or
143  <literal>amaflags</literal>.</para><para>CDRs can only be modified before the bridge
144  between two channels is torn down. For example, CDRs may not be modified after the
145  <literal>Dial</literal> application has returned.</para></note>
146  <para>Raw values for <literal>disposition</literal>:</para>
147  <enumlist>
148  <enum name="0">
149  <para>NO ANSWER</para>
150  </enum>
151  <enum name="1">
152  <para>NO ANSWER (NULL record)</para>
153  </enum>
154  <enum name="2">
155  <para>FAILED</para>
156  </enum>
157  <enum name="4">
158  <para>BUSY</para>
159  </enum>
160  <enum name="8">
161  <para>ANSWERED</para>
162  </enum>
163  </enumlist>
164  <para>Raw values for <literal>amaflags</literal>:</para>
165  <enumlist>
166  <enum name="1">
167  <para>OMIT</para>
168  </enum>
169  <enum name="2">
170  <para>BILLING</para>
171  </enum>
172  <enum name="3">
173  <para>DOCUMENTATION</para>
174  </enum>
175  </enumlist>
176  <para>Example: exten => 1,1,Set(CDR(userfield)=test)</para>
177  </description>
178  </function>
179  ***/
180 
182  OPT_RECURSIVE = (1 << 0),
183  OPT_UNPARSED = (1 << 1),
184  OPT_LAST = (1 << 2),
185  OPT_SKIPLOCKED = (1 << 3),
186  OPT_FLOAT = (1 << 4),
187 };
188 
191  AST_APP_OPTION('l', OPT_LAST),
195 });
196 
197 static int cdr_read(struct ast_channel *chan, const char *cmd, char *parse,
198  char *buf, size_t len)
199 {
200  char *ret = NULL;
201  struct ast_flags flags = { 0 };
202  struct ast_cdr *cdr;
204  AST_APP_ARG(variable);
205  AST_APP_ARG(options);
206  );
207 
208  if (ast_strlen_zero(parse) || !chan)
209  return -1;
210 
211  ast_channel_lock(chan);
212  cdr = chan->cdr;
213  if (!cdr) {
214  ast_channel_unlock(chan);
215  return -1;
216  }
217 
218  AST_STANDARD_APP_ARGS(args, parse);
219 
220  if (!ast_strlen_zero(args.options))
221  ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
222 
223  if (ast_test_flag(&flags, OPT_LAST))
224  while (cdr->next)
225  cdr = cdr->next;
226 
227  if (ast_test_flag(&flags, OPT_SKIPLOCKED))
228  while (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && cdr->next)
229  cdr = cdr->next;
230 
231  if (!strcasecmp("billsec", args.variable) && ast_test_flag(&flags, OPT_FLOAT)) {
232  if (!ast_tvzero(cdr->answer)) {
233  double hrtime;
234 
235  if(!ast_tvzero(cdr->end))
236  hrtime = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0);
237  else
238  hrtime = (double)(ast_tvdiff_us(ast_tvnow(), cdr->answer) / 1000000.0);
239 
240  snprintf(buf, len, "%lf", hrtime);
241  } else {
242  snprintf(buf, len, "%lf", 0.0);
243  }
244  ret = buf;
245  } else if (!strcasecmp("duration", args.variable) && ast_test_flag(&flags, OPT_FLOAT)) {
246  double hrtime;
247 
248  if(!ast_tvzero(cdr->end))
249  hrtime = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0);
250  else
251  hrtime = (double)(ast_tvdiff_us(ast_tvnow(), cdr->start) / 1000000.0);
252 
253  snprintf(buf, len, "%lf", hrtime);
254 
255  if (!ast_strlen_zero(buf)) {
256  ret = buf;
257  }
258  } else {
259  ast_cdr_getvar(cdr, args.variable, &ret, buf, len,
260  ast_test_flag(&flags, OPT_RECURSIVE),
261  ast_test_flag(&flags, OPT_UNPARSED));
262  }
263 
264  ast_channel_unlock(chan);
265  return ret ? 0 : -1;
266 }
267 
268 static int cdr_write(struct ast_channel *chan, const char *cmd, char *parse,
269  const char *value)
270 {
271  struct ast_cdr *cdr;
272  struct ast_flags flags = { 0 };
274  AST_APP_ARG(variable);
275  AST_APP_ARG(options);
276  );
277 
278  if (ast_strlen_zero(parse) || !value || !chan)
279  return -1;
280 
281  ast_channel_lock(chan);
282  cdr = chan->cdr;
283  if (!cdr) {
284  ast_channel_unlock(chan);
285  return -1;
286  }
287 
288  AST_STANDARD_APP_ARGS(args, parse);
289 
290  if (!ast_strlen_zero(args.options))
291  ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
292 
293  if (ast_test_flag(&flags, OPT_LAST))
294  while (cdr->next)
295  cdr = cdr->next;
296 
297  if (!strcasecmp(args.variable, "accountcode")) /* the 'l' flag doesn't apply to setting the accountcode, userfield, or amaflags */
298  ast_cdr_setaccount(chan, value);
299  else if (!strcasecmp(args.variable, "peeraccount"))
300  ast_cdr_setpeeraccount(chan, value);
301  else if (!strcasecmp(args.variable, "userfield"))
302  ast_cdr_setuserfield(chan, value);
303  else if (!strcasecmp(args.variable, "amaflags"))
304  ast_cdr_setamaflags(chan, value);
305  else
306  ast_cdr_setvar(cdr, args.variable, value, ast_test_flag(&flags, OPT_RECURSIVE));
307  /* No need to worry about the u flag, as all fields for which setting
308  * 'u' would do anything are marked as readonly. */
309 
310  ast_channel_unlock(chan);
311  return 0;
312 }
313 
315  .name = "CDR",
316  .read = cdr_read,
317  .write = cdr_write,
318 };
319 
320 static int unload_module(void)
321 {
322  return ast_custom_function_unregister(&cdr_function);
323 }
324 
325 static int load_module(void)
326 {
327  return ast_custom_function_register(&cdr_function);
328 }
329 
330 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call Detail Record (CDR) dialplan function");
int ast_cdr_setamaflags(struct ast_channel *chan, const char *amaflags)
Set AMA flags for channel.
Definition: cdr.c:1042
static struct ast_app_option cdr_func_options[128]
Definition: func_cdr.c:195
int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur)
Definition: cdr.c:343
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
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
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int unload_module(void)
Definition: func_cdr.c:320
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
int ast_cdr_setaccount(struct ast_channel *chan, const char *account)
Set account code, will generate AMI event.
Definition: cdr.c:990
#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
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
struct ast_cdr * cdr
Definition: channel.h:766
int value
Definition: syslog.c:39
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
Utility functions.
int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:1057
void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw)
Definition: cdr.c:264
Call Detail Record API.
General Asterisk PBX channel definitions.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Data structure associated with a custom dialplan function.
Definition: pbx.h:95
Core PBX routines and definitions.
struct timeval answer
Definition: cdr.h:102
Responsible for call detail data.
Definition: cdr.h:82
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_channel_unlock(chan)
Definition: channel.h:2467
struct timeval start
Definition: cdr.h:100
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
int ast_cdr_setpeeraccount(struct ast_channel *chan, const char *account)
Set the peer account.
Definition: cdr.c:1016
Structure used to handle boolean flags.
Definition: utils.h:200
struct timeval end
Definition: cdr.h:104
static int cdr_write(struct ast_channel *chan, const char *cmd, char *parse, const char *value)
Definition: func_cdr.c:268
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static int cdr_read(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_cdr.c:197
const char * name
Definition: pbx.h:96
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:70
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
cdr_option_flags
Definition: func_cdr.c:181
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
#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 load_module(void)
Definition: func_cdr.c:325
static struct ast_custom_function cdr_function
Definition: func_cdr.c:314