Asterisk - The Open Source Telephony Project  18.5.0
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 #include "asterisk/module.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/utils.h"
38 #include "asterisk/app.h"
39 #include "asterisk/cdr.h"
40 #include "asterisk/stasis.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>The final state of the CDR.</para>
60  <enumlist>
61  <enum name="0">
62  <para><literal>NO ANSWER</literal></para>
63  </enum>
64  <enum name="1">
65  <para><literal>NO ANSWER</literal> (NULL record)</para>
66  </enum>
67  <enum name="2">
68  <para><literal>FAILED</literal></para>
69  </enum>
70  <enum name="4">
71  <para><literal>BUSY</literal></para>
72  </enum>
73  <enum name="8">
74  <para><literal>ANSWERED</literal></para>
75  </enum>
76  <enum name="16">
77  <para><literal>CONGESTION</literal></para>
78  </enum>
79  </enumlist>
80  </enum>
81  <enum name="src">
82  <para>Source.</para>
83  </enum>
84  <enum name="start">
85  <para>Time the call started.</para>
86  </enum>
87  <enum name="amaflags">
88  <para>R/W the Automatic Message Accounting (AMA) flags on the channel.
89  When read from a channel, the integer value will always be returned.
90  When written to a channel, both the string format or integer value
91  is accepted.</para>
92  <enumlist>
93  <enum name="1"><para><literal>OMIT</literal></para></enum>
94  <enum name="2"><para><literal>BILLING</literal></para></enum>
95  <enum name="3"><para><literal>DOCUMENTATION</literal></para></enum>
96  </enumlist>
97  <warning><para>Accessing this setting is deprecated in CDR. Please use the CHANNEL function instead.</para></warning>
98  </enum>
99  <enum name="dst">
100  <para>Destination.</para>
101  </enum>
102  <enum name="answer">
103  <para>Time the call was answered.</para>
104  </enum>
105  <enum name="accountcode">
106  <para>The channel's account code.</para>
107  <warning><para>Accessing this setting is deprecated in CDR. Please use the CHANNEL function instead.</para></warning>
108  </enum>
109  <enum name="dcontext">
110  <para>Destination context.</para>
111  </enum>
112  <enum name="end">
113  <para>Time the call ended.</para>
114  </enum>
115  <enum name="uniqueid">
116  <para>The channel's unique id.</para>
117  </enum>
118  <enum name="dstchannel">
119  <para>Destination channel.</para>
120  </enum>
121  <enum name="duration">
122  <para>Duration of the call.</para>
123  </enum>
124  <enum name="userfield">
125  <para>The channel's user specified field.</para>
126  </enum>
127  <enum name="lastapp">
128  <para>Last application.</para>
129  </enum>
130  <enum name="billsec">
131  <para>Duration of the call once it was answered.</para>
132  </enum>
133  <enum name="channel">
134  <para>Channel name.</para>
135  </enum>
136  <enum name="sequence">
137  <para>CDR sequence number.</para>
138  </enum>
139  </enumlist>
140  </parameter>
141  <parameter name="options" required="false">
142  <optionlist>
143  <option name="f">
144  <para>Returns billsec or duration fields as floating point values.</para>
145  </option>
146  <option name="u">
147  <para>Retrieves the raw, unprocessed value.</para>
148  <para>For example, 'start', 'answer', and 'end' will be retrieved as epoch
149  values, when the <literal>u</literal> option is passed, but formatted as YYYY-MM-DD HH:MM:SS
150  otherwise. Similarly, disposition and amaflags will return their raw
151  integral values.</para>
152  </option>
153  </optionlist>
154  </parameter>
155  </syntax>
156  <description>
157  <para>All of the CDR field names are read-only, except for <literal>accountcode</literal>,
158  <literal>userfield</literal>, and <literal>amaflags</literal>. You may, however, supply
159  a name not on the above list, and create your own variable, whose value can be changed
160  with this function, and this variable will be stored on the CDR.</para>
161  <note><para>CDRs can only be modified before the bridge between two channels is
162  torn down. For example, CDRs may not be modified after the <literal>Dial</literal>
163  application has returned.</para></note>
164  <para>Example: exten => 1,1,Set(CDR(userfield)=test)</para>
165  </description>
166  </function>
167  <function name="CDR_PROP" language="en_US">
168  <synopsis>
169  Set a property on a channel's CDR.
170  </synopsis>
171  <syntax>
172  <parameter name="name" required="true">
173  <para>The property to set on the CDR.</para>
174  <enumlist>
175  <enum name="party_a">
176  <para>Set this channel as the preferred Party A when
177  channels are associated together.</para>
178  <para>Write-Only</para>
179  </enum>
180  <enum name="disable">
181  <para>Setting to 1 will disable CDRs for this channel.
182  Setting to 0 will enable CDRs for this channel.</para>
183  <para>Write-Only</para>
184  </enum>
185  </enumlist>
186  </parameter>
187  </syntax>
188  <description>
189  <para>This function sets a property on a channel's CDR. Properties
190  alter the behavior of how the CDR operates for that channel.</para>
191  </description>
192  </function>
193  ***/
194 
196  OPT_UNPARSED = (1 << 1),
197  OPT_FLOAT = (1 << 2),
198 };
199 
203 });
204 
206  struct ast_channel *chan;
207  const char *cmd;
208  const char *arguments;
209  const char *value;
210  void *data;
211 };
212 
214  char *buf;
215  size_t len;
216 };
217 
218 STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_read_message_type);
219 STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_write_message_type);
220 STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_prop_write_message_type);
221 
222 static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name)
223 {
224  struct timeval time = { 0 };
225  char *value = NULL;
226  char tempbuf[128];
227  long int tv_sec;
228  long int tv_usec;
229 
230  if (ast_strlen_zero(ast_channel_name(chan))) {
231  /* Format request on a dummy channel */
232  ast_cdr_format_var(ast_channel_cdr(chan), time_name, &value, tempbuf, sizeof(tempbuf), 1);
233  } else {
234  ast_cdr_getvar(ast_channel_name(chan), time_name, tempbuf, sizeof(tempbuf));
235  }
236 
237  /* time.tv_usec is suseconds_t, which could be int or long */
238  if (sscanf(tempbuf, "%ld.%ld", &tv_sec, &tv_usec) == 2) {
239  time.tv_sec = tv_sec;
240  time.tv_usec = tv_usec;
241  } else {
242  ast_log(AST_LOG_WARNING, "Failed to fully extract '%s' from CDR\n", time_name);
243  }
244 
245  return time;
246 }
247 
249 {
250  struct cdr_func_payload *payload = stasis_message_data(message);
251  struct cdr_func_data *output;
252  char *info;
253  char *value = NULL;
254  struct ast_flags flags = { 0 };
255  char tempbuf[512];
257  AST_APP_ARG(variable);
259  );
260 
261  if (cdr_read_message_type() != stasis_message_type(message)) {
262  return;
263  }
264 
265  ast_assert(payload != NULL);
266  output = payload->data;
267  ast_assert(output != NULL);
268 
269  if (ast_strlen_zero(payload->arguments)) {
270  ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable[,option]))\n)",
271  payload->cmd, payload->cmd);
272  return;
273  }
274  info = ast_strdupa(payload->arguments);
276 
277  if (!ast_strlen_zero(args.options)) {
278  ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
279  }
280 
281  if (ast_strlen_zero(ast_channel_name(payload->chan))) {
282  /* Format request on a dummy channel */
283  ast_cdr_format_var(ast_channel_cdr(payload->chan), args.variable, &value, tempbuf, sizeof(tempbuf), ast_test_flag(&flags, OPT_UNPARSED));
284  if (ast_strlen_zero(value)) {
285  return;
286  }
287  ast_copy_string(tempbuf, value, sizeof(tempbuf));
288  ast_set_flag(&flags, OPT_UNPARSED);
289  } else if (ast_cdr_getvar(ast_channel_name(payload->chan), args.variable, tempbuf, sizeof(tempbuf))) {
290  return;
291  }
292 
293  if (ast_test_flag(&flags, OPT_FLOAT)
294  && (!strcasecmp("billsec", args.variable) || !strcasecmp("duration", args.variable))) {
295  struct timeval start = cdr_retrieve_time(payload->chan, !strcasecmp("billsec", args.variable) ? "answer" : "start");
296  struct timeval finish = cdr_retrieve_time(payload->chan, "end");
297  double delta;
298 
299  if (ast_tvzero(finish)) {
300  finish = ast_tvnow();
301  }
302 
303  if (ast_tvzero(start)) {
304  delta = 0.0;
305  } else {
306  delta = (double)(ast_tvdiff_us(finish, start) / 1000000.0);
307  }
308  snprintf(tempbuf, sizeof(tempbuf), "%lf", delta);
309 
310  } else if (!ast_test_flag(&flags, OPT_UNPARSED)) {
311  if (!strcasecmp("start", args.variable)
312  || !strcasecmp("end", args.variable)
313  || !strcasecmp("answer", args.variable)) {
314  struct timeval fmt_time;
315  struct ast_tm tm;
316  /* tv_usec is suseconds_t, which could be int or long */
317  long int tv_sec;
318  long int tv_usec;
319 
320  if (sscanf(tempbuf, "%ld.%ld", &tv_sec, &tv_usec) != 2) {
321  ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
322  args.variable, tempbuf, ast_channel_name(payload->chan));
323  return;
324  }
325  if (tv_sec) {
326  fmt_time.tv_sec = tv_sec;
327  fmt_time.tv_usec = tv_usec;
328  ast_localtime(&fmt_time, &tm, NULL);
329  ast_strftime(tempbuf, sizeof(tempbuf), "%Y-%m-%d %T", &tm);
330  } else {
331  tempbuf[0] = '\0';
332  }
333  } else if (!strcasecmp("disposition", args.variable)) {
334  int disposition;
335 
336  if (sscanf(tempbuf, "%8d", &disposition) != 1) {
337  ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
338  args.variable, tempbuf, ast_channel_name(payload->chan));
339  return;
340  }
341  snprintf(tempbuf, sizeof(tempbuf), "%s", ast_cdr_disp2str(disposition));
342  } else if (!strcasecmp("amaflags", args.variable)) {
343  int amaflags;
344 
345  if (sscanf(tempbuf, "%8d", &amaflags) != 1) {
346  ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
347  args.variable, tempbuf, ast_channel_name(payload->chan));
348  return;
349  }
350  snprintf(tempbuf, sizeof(tempbuf), "%s", ast_channel_amaflags2string(amaflags));
351  }
352  }
353 
354  ast_copy_string(output->buf, tempbuf, output->len);
355 }
356 
358 {
359  struct cdr_func_payload *payload;
360  struct ast_flags flags = { 0 };
362  AST_APP_ARG(variable);
364  );
365  char *parse;
366 
367  if (cdr_write_message_type() != stasis_message_type(message)) {
368  return;
369  }
370  payload = stasis_message_data(message);
371  if (!payload) {
372  return;
373  }
374  if (ast_strlen_zero(payload->arguments)
375  || !payload->value) {
376  /* Sanity check. cdr_write() could never send these bad messages */
377  ast_assert(0);
378  return;
379  }
380 
381  parse = ast_strdupa(payload->arguments);
382  AST_STANDARD_APP_ARGS(args, parse);
383 
384  if (!ast_strlen_zero(args.options)) {
385  ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
386  }
387 
388  /* These are already handled by cdr_write() */
389  ast_assert(strcasecmp(args.variable, "accountcode")
390  && strcasecmp(args.variable, "peeraccount")
391  && strcasecmp(args.variable, "amaflags"));
392 
393  if (!strcasecmp(args.variable, "userfield")) {
394  ast_cdr_setuserfield(ast_channel_name(payload->chan), payload->value);
395  } else {
396  ast_cdr_setvar(ast_channel_name(payload->chan), args.variable, payload->value);
397  }
398 }
399 
401 {
402  struct cdr_func_payload *payload = stasis_message_data(message);
403  enum ast_cdr_options option;
404  char *parse;
406  AST_APP_ARG(variable);
408  );
409 
410  if (cdr_prop_write_message_type() != stasis_message_type(message)) {
411  return;
412  }
413 
414  if (!payload) {
415  return;
416  }
417 
418  if (ast_strlen_zero(payload->arguments)) {
419  ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",
420  payload->cmd, payload->cmd);
421  return;
422  }
423  if (ast_strlen_zero(payload->value)) {
424  ast_log(AST_LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",
425  payload->cmd, payload->cmd);
426  return;
427  }
428  parse = ast_strdupa(payload->arguments);
429  AST_STANDARD_APP_ARGS(args, parse);
430 
431  if (!strcasecmp("party_a", args.variable)) {
432  option = AST_CDR_FLAG_PARTY_A;
433  } else if (!strcasecmp("disable", args.variable)) {
434  option = AST_CDR_FLAG_DISABLE_ALL;
435  } else {
436  ast_log(AST_LOG_WARNING, "Unknown option %s used with %s\n", args.variable, payload->cmd);
437  return;
438  }
439 
440  if (ast_true(payload->value)) {
441  ast_cdr_set_property(ast_channel_name(payload->chan), option);
442  } else {
443  ast_cdr_clear_property(ast_channel_name(payload->chan), option);
444  }
445 }
446 
447 
448 static int cdr_read(struct ast_channel *chan, const char *cmd, char *parse,
449  char *buf, size_t len)
450 {
452  RAII_VAR(struct cdr_func_payload *, payload, NULL, ao2_cleanup);
453  struct cdr_func_data output = { 0, };
454 
455  if (!chan) {
456  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
457  return -1;
458  }
459 
460  if (!cdr_read_message_type()) {
461  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",
462  ast_channel_name(chan));
463  return -1;
464  }
465 
466  payload = ao2_alloc(sizeof(*payload), NULL);
467  if (!payload) {
468  return -1;
469  }
470  payload->chan = chan;
471  payload->cmd = cmd;
472  payload->arguments = parse;
473  payload->data = &output;
474 
475  buf[0] = '\0';/* Ensure the buffer is initialized. */
476  output.buf = buf;
477  output.len = len;
478 
479  message = stasis_message_create(cdr_read_message_type(), payload);
480  if (!message) {
481  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
482  ast_channel_name(chan));
483  return -1;
484  }
485 
486  /* If this is a request on a dummy channel, we're doing post-processing on an
487  * already dispatched CDR. Simply call the callback to calculate the value and
488  * return, instead of posting to Stasis as we would for a running channel.
489  */
490  if (ast_strlen_zero(ast_channel_name(chan))) {
492  } else {
494 
495  if (!router) {
496  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
497  ast_channel_name(chan));
498  return -1;
499  }
501  }
502 
503  return 0;
504 }
505 
506 static int cdr_write(struct ast_channel *chan, const char *cmd, char *arguments,
507  const char *value)
508 {
509  struct stasis_message *message;
510  struct cdr_func_payload *payload;
513  AST_APP_ARG(variable);
515  );
516  char *parse;
517 
518  if (!chan) {
519  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
520  return -1;
521  }
522  if (ast_strlen_zero(arguments)) {
523  ast_log(LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",
524  cmd, cmd);
525  return -1;
526  }
527  if (!value) {
528  ast_log(LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",
529  cmd, cmd);
530  return -1;
531  }
532 
533  parse = ast_strdupa(arguments);
534  AST_STANDARD_APP_ARGS(args, parse);
535 
536  /* These CDR variables are no longer supported or set directly on the channel */
537  if (!strcasecmp(args.variable, "accountcode")) {
538  ast_log(LOG_WARNING, "Using the %s function to set 'accountcode' is deprecated. Please use the CHANNEL function instead.\n",
539  cmd);
540  ast_channel_lock(chan);
541  ast_channel_accountcode_set(chan, value);
542  ast_channel_unlock(chan);
543  return 0;
544  }
545  if (!strcasecmp(args.variable, "amaflags")) {
546  int amaflags;
547 
548  ast_log(LOG_WARNING, "Using the %s function to set 'amaflags' is deprecated. Please use the CHANNEL function instead.\n",
549  cmd);
550  if (isdigit(*value)) {
551  if (sscanf(value, "%30d", &amaflags) != 1) {
552  amaflags = AST_AMA_NONE;
553  }
554  } else {
555  amaflags = ast_channel_string2amaflag(value);
556  }
557  ast_channel_lock(chan);
558  ast_channel_amaflags_set(chan, amaflags);
559  ast_channel_unlock(chan);
560  return 0;
561  }
562  if (!strcasecmp(args.variable, "peeraccount")) {
563  ast_log(LOG_WARNING, "The 'peeraccount' setting is not supported. Please set the 'accountcode' on the appropriate channel using the CHANNEL function.\n");
564  return 0;
565  }
566 
567  /* The remaining CDR variables are handled by CDR processing code */
568  if (!cdr_write_message_type()) {
569  ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",
570  ast_channel_name(chan));
571  return -1;
572  }
573 
574  payload = ao2_alloc(sizeof(*payload), NULL);
575  if (!payload) {
576  return -1;
577  }
578  payload->chan = chan;
579  payload->cmd = cmd;
580  payload->arguments = arguments;
581  payload->value = value;
582 
583  message = stasis_message_create(cdr_write_message_type(), payload);
584  ao2_ref(payload, -1);
585  if (!message) {
586  ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
587  ast_channel_name(chan));
588  return -1;
589  }
590  router = ast_cdr_message_router();
591  if (!router) {
592  ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
593  ast_channel_name(chan));
594  ao2_ref(message, -1);
595  return -1;
596  }
597  stasis_message_router_publish_sync(router, message);
598  ao2_ref(router, -1);
599  ao2_ref(message, -1);
600 
601  return 0;
602 }
603 
604 static int cdr_prop_write(struct ast_channel *chan, const char *cmd, char *parse,
605  const char *value)
606 {
608  RAII_VAR(struct cdr_func_payload *, payload, NULL, ao2_cleanup);
610 
611  if (!chan) {
612  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
613  return -1;
614  }
615 
616  if (!router) {
617  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
618  ast_channel_name(chan));
619  return -1;
620  }
621 
622  if (!cdr_prop_write_message_type()) {
623  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",
624  ast_channel_name(chan));
625  return -1;
626  }
627 
628  payload = ao2_alloc(sizeof(*payload), NULL);
629  if (!payload) {
630  return -1;
631  }
632  payload->chan = chan;
633  payload->cmd = cmd;
634  payload->arguments = parse;
635  payload->value = value;
636 
637  message = stasis_message_create(cdr_prop_write_message_type(), payload);
638  if (!message) {
639  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
640  ast_channel_name(chan));
641  return -1;
642  }
644 
645  return 0;
646 }
647 
649  .name = "CDR",
650  .read = cdr_read,
651  .write = cdr_write,
652 };
653 
655  .name = "CDR_PROP",
656  .read = NULL,
657  .write = cdr_prop_write,
658 };
659 
660 static int unload_module(void)
661 {
663  int res = 0;
664 
665  if (router) {
666  stasis_message_router_remove(router, cdr_prop_write_message_type());
667  stasis_message_router_remove(router, cdr_write_message_type());
668  stasis_message_router_remove(router, cdr_read_message_type());
669  }
670  STASIS_MESSAGE_TYPE_CLEANUP(cdr_read_message_type);
671  STASIS_MESSAGE_TYPE_CLEANUP(cdr_write_message_type);
672  STASIS_MESSAGE_TYPE_CLEANUP(cdr_prop_write_message_type);
673  res |= ast_custom_function_unregister(&cdr_function);
674  res |= ast_custom_function_unregister(&cdr_prop_function);
675 
676  return res;
677 }
678 
679 static int load_module(void)
680 {
682  int res = 0;
683 
684  if (!router) {
686  }
687 
688  res |= STASIS_MESSAGE_TYPE_INIT(cdr_read_message_type);
689  res |= STASIS_MESSAGE_TYPE_INIT(cdr_write_message_type);
690  res |= STASIS_MESSAGE_TYPE_INIT(cdr_prop_write_message_type);
691  res |= ast_custom_function_register(&cdr_function);
692  res |= ast_custom_function_register(&cdr_prop_function);
693  res |= stasis_message_router_add(router, cdr_prop_write_message_type(),
695  res |= stasis_message_router_add(router, cdr_write_message_type(),
697  res |= stasis_message_router_add(router, cdr_read_message_type(),
699 
700  if (res) {
701  unload_module();
703  }
705 }
706 
707 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Call Detail Record (CDR) dialplan functions",
708  .support_level = AST_MODULE_SUPPORT_CORE,
709  .load = load_module,
710  .unload = unload_module,
711  .requires = "cdr",
712 );
const char * name
Definition: pbx.h:119
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
Set a variable on a CDR.
Definition: cdr.c:3178
Asterisk main include file. File version handling, generic pbx functions.
static int amaflags
Definition: chan_iax2.c:431
struct ast_cdr * ast_channel_cdr(const struct ast_channel *chan)
static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name)
Definition: func_cdr.c:222
static int cdr_write(struct ast_channel *chan, const char *cmd, char *arguments, const char *value)
Definition: func_cdr.c:506
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int unload_module(void)
Definition: func_cdr.c:660
static struct stasis_message_router * router
static struct ast_custom_function cdr_prop_function
Definition: func_cdr.c:654
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
Retrieve a CDR variable from a channel&#39;s current CDR.
Definition: cdr.c:3324
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
#define LOG_WARNING
Definition: logger.h:274
static const struct ast_app_option cdr_func_options[128]
Definition: func_cdr.c:203
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
void stasis_message_router_publish_sync(struct stasis_message_router *router, struct stasis_message *message)
Publish a message to a message router&#39;s subscription synchronously.
#define AST_LOG_WARNING
Definition: logger.h:279
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
Definition: channel.c:4418
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_assert(a)
Definition: utils.h:695
const char * args
#define NULL
Definition: resample.c:96
ast_cdr_options
CDR manipulation options. Certain function calls will manipulate the state of a CDR object based on t...
Definition: cdr.h:239
static int cdr_prop_write(struct ast_channel *chan, const char *cmd, char *parse, const char *value)
Definition: func_cdr.c:604
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Utility functions.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4405
static void cdr_prop_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: func_cdr.c:400
Call Detail Record API.
void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
Format a CDR variable from an already posted CDR.
Definition: cdr.c:3050
#define ast_log
Definition: astobj2.c:42
struct stasis_message_router * ast_cdr_message_router(void)
Return the message router for the CDR engine.
Definition: cdr.c:4291
General Asterisk PBX channel definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
char * buf
Definition: func_cdr.c:214
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: main/app.c:2906
Core PBX routines and definitions.
int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
Set a property on a CDR for a channel.
Definition: cdr.c:3548
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3430
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_message_router_remove(struct stasis_message_router *router, struct stasis_message_type *message_type)
Remove a route from a message router.
def info(msg)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_read_message_type)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
const char * arguments
Definition: func_cdr.c:208
struct ast_channel * chan
Definition: func_cdr.c:206
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:3477
Structure used to handle boolean flags.
Definition: utils.h:199
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
static void cdr_read_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: func_cdr.c:248
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
const char * value
Definition: func_cdr.c:209
struct stasis_forward * sub
Definition: res_corosync.c:240
int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
Clear a property on a CDR for a channel.
Definition: cdr.c:3575
static int cdr_read(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_cdr.c:448
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:78
const char * cmd
Definition: func_cdr.c:207
static void cdr_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: func_cdr.c:357
static struct test_options options
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
cdr_option_flags
Definition: func_cdr.c:195
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
size_t len
Definition: func_cdr.c:215
static int load_module(void)
Definition: func_cdr.c:679
static struct ast_custom_function cdr_function
Definition: func_cdr.c:648
#define AST_APP_ARG(name)
Define an application argument.