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