Asterisk - The Open Source Telephony Project GIT-master-d856a3e
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 <example title="Set the userfield">
165 exten => 1,1,Set(CDR(userfield)=test)
166 </example>
167 </description>
168 </function>
169 <function name="CDR_PROP" language="en_US">
170 <synopsis>
171 Set a property on a channel's CDR.
172 </synopsis>
173 <syntax>
174 <parameter name="name" required="true">
175 <para>The property to set on the CDR.</para>
176 <enumlist>
177 <enum name="party_a">
178 <para>Set this channel as the preferred Party A when
179 channels are associated together.</para>
180 <para>Write-Only</para>
181 </enum>
182 <enum name="disable">
183 <para>Setting to 1 will disable CDRs for this channel.
184 Setting to 0 will enable CDRs for this channel.</para>
185 <para>Write-Only</para>
186 </enum>
187 </enumlist>
188 </parameter>
189 </syntax>
190 <description>
191 <para>This function sets a property on a channel's CDR. Properties
192 alter the behavior of how the CDR operates for that channel.</para>
193 </description>
194 </function>
195 ***/
196
198 OPT_UNPARSED = (1 << 1),
199 OPT_FLOAT = (1 << 2),
200};
201
205});
206
209 const char *cmd;
210 const char *arguments;
211 const char *value;
212 void *data;
213};
214
216 char *buf;
217 size_t len;
218};
219
220STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_read_message_type);
221STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_write_message_type);
222STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_prop_write_message_type);
223
224static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name)
225{
226 struct timeval time = { 0 };
227 char *value = NULL;
228 char tempbuf[128];
229 long int tv_sec;
230 long int tv_usec;
231
233 /* Format request on a dummy channel */
234 ast_cdr_format_var(ast_channel_cdr(chan), time_name, &value, tempbuf, sizeof(tempbuf), 1);
235 } else {
236 ast_cdr_getvar(ast_channel_name(chan), time_name, tempbuf, sizeof(tempbuf));
237 }
238
239 /* time.tv_usec is suseconds_t, which could be int or long */
240 if (sscanf(tempbuf, "%ld.%ld", &tv_sec, &tv_usec) == 2) {
241 time.tv_sec = tv_sec;
242 time.tv_usec = tv_usec;
243 } else {
244 ast_log(AST_LOG_WARNING, "Failed to fully extract '%s' from CDR\n", time_name);
245 }
246
247 return time;
248}
249
250static void cdr_read_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
251{
253 struct cdr_func_data *output;
254 char *info;
255 char *value = NULL;
256 struct ast_flags flags = { 0 };
257 char tempbuf[512];
259 AST_APP_ARG(variable);
261 );
262
263 if (cdr_read_message_type() != stasis_message_type(message)) {
264 return;
265 }
266
267 ast_assert(payload != NULL);
268 output = payload->data;
269 ast_assert(output != NULL);
270
271 if (ast_strlen_zero(payload->arguments)) {
272 ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable[,option]))\n)",
273 payload->cmd, payload->cmd);
274 return;
275 }
276 info = ast_strdupa(payload->arguments);
278
279 if (!ast_strlen_zero(args.options)) {
281 }
282
283 if (ast_strlen_zero(ast_channel_name(payload->chan))) {
284 /* Format request on a dummy channel */
285 ast_cdr_format_var(ast_channel_cdr(payload->chan), args.variable, &value, tempbuf, sizeof(tempbuf), ast_test_flag(&flags, OPT_UNPARSED));
286 if (ast_strlen_zero(value)) {
287 return;
288 }
289 ast_copy_string(tempbuf, value, sizeof(tempbuf));
291 } else if (ast_cdr_getvar(ast_channel_name(payload->chan), args.variable, tempbuf, sizeof(tempbuf))) {
292 return;
293 }
294
296 && (!strcasecmp("billsec", args.variable) || !strcasecmp("duration", args.variable))) {
297 struct timeval start = cdr_retrieve_time(payload->chan, !strcasecmp("billsec", args.variable) ? "answer" : "start");
298 struct timeval finish = cdr_retrieve_time(payload->chan, "end");
299 double delta;
300
301 if (ast_tvzero(finish)) {
302 finish = ast_tvnow();
303 }
304
305 if (ast_tvzero(start)) {
306 delta = 0.0;
307 } else {
308 delta = (double)(ast_tvdiff_us(finish, start) / 1000000.0);
309 }
310 snprintf(tempbuf, sizeof(tempbuf), "%lf", delta);
311
312 } else if (!ast_test_flag(&flags, OPT_UNPARSED)) {
313 if (!strcasecmp("start", args.variable)
314 || !strcasecmp("end", args.variable)
315 || !strcasecmp("answer", args.variable)) {
316 struct timeval fmt_time;
317 struct ast_tm tm;
318 /* tv_usec is suseconds_t, which could be int or long */
319 long int tv_sec;
320 long int tv_usec;
321
322 if (sscanf(tempbuf, "%ld.%ld", &tv_sec, &tv_usec) != 2) {
323 ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
324 args.variable, tempbuf, ast_channel_name(payload->chan));
325 return;
326 }
327 if (tv_sec) {
328 fmt_time.tv_sec = tv_sec;
329 fmt_time.tv_usec = tv_usec;
330 ast_localtime(&fmt_time, &tm, NULL);
331 ast_strftime(tempbuf, sizeof(tempbuf), "%Y-%m-%d %T", &tm);
332 } else {
333 tempbuf[0] = '\0';
334 }
335 } else if (!strcasecmp("disposition", args.variable)) {
336 int disposition;
337
338 if (sscanf(tempbuf, "%8d", &disposition) != 1) {
339 ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
340 args.variable, tempbuf, ast_channel_name(payload->chan));
341 return;
342 }
343 snprintf(tempbuf, sizeof(tempbuf), "%s", ast_cdr_disp2str(disposition));
344 } else if (!strcasecmp("amaflags", args.variable)) {
345 int amaflags;
346
347 if (sscanf(tempbuf, "%8d", &amaflags) != 1) {
348 ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
349 args.variable, tempbuf, ast_channel_name(payload->chan));
350 return;
351 }
352 snprintf(tempbuf, sizeof(tempbuf), "%s", ast_channel_amaflags2string(amaflags));
353 }
354 }
355
356 ast_copy_string(output->buf, tempbuf, output->len);
357}
358
359static void cdr_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
360{
361 struct cdr_func_payload *payload;
362 struct ast_flags flags = { 0 };
364 AST_APP_ARG(variable);
366 );
367 char *parse;
368
369 if (cdr_write_message_type() != stasis_message_type(message)) {
370 return;
371 }
372 payload = stasis_message_data(message);
373 if (!payload) {
374 return;
375 }
376 if (ast_strlen_zero(payload->arguments)
377 || !payload->value) {
378 /* Sanity check. cdr_write() could never send these bad messages */
379 ast_assert(0);
380 return;
381 }
382
383 parse = ast_strdupa(payload->arguments);
385
386 if (!ast_strlen_zero(args.options)) {
388 }
389
390 /* These are already handled by cdr_write() */
391 ast_assert(strcasecmp(args.variable, "accountcode")
392 && strcasecmp(args.variable, "peeraccount")
393 && strcasecmp(args.variable, "amaflags"));
394
395 if (!strcasecmp(args.variable, "userfield")) {
396 ast_cdr_setuserfield(ast_channel_name(payload->chan), payload->value);
397 } else {
398 ast_cdr_setvar(ast_channel_name(payload->chan), args.variable, payload->value);
399 }
400}
401
403{
405 enum ast_cdr_options option;
406 char *parse;
408 AST_APP_ARG(variable);
410 );
411
412 if (cdr_prop_write_message_type() != stasis_message_type(message)) {
413 return;
414 }
415
416 if (!payload) {
417 return;
418 }
419
420 if (ast_strlen_zero(payload->arguments)) {
421 ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",
422 payload->cmd, payload->cmd);
423 return;
424 }
425 if (ast_strlen_zero(payload->value)) {
426 ast_log(AST_LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",
427 payload->cmd, payload->cmd);
428 return;
429 }
430 parse = ast_strdupa(payload->arguments);
432
433 if (!strcasecmp("party_a", args.variable)) {
434 option = AST_CDR_FLAG_PARTY_A;
435 } else if (!strcasecmp("disable", args.variable)) {
437 } else {
438 ast_log(AST_LOG_WARNING, "Unknown option %s used with %s\n", args.variable, payload->cmd);
439 return;
440 }
441
442 if (ast_true(payload->value)) {
443 ast_cdr_set_property(ast_channel_name(payload->chan), option);
444 } else {
446 }
447}
448
449
450static int cdr_read(struct ast_channel *chan, const char *cmd, char *parse,
451 char *buf, size_t len)
452{
454 RAII_VAR(struct cdr_func_payload *, payload, NULL, ao2_cleanup);
455 struct cdr_func_data output = { 0, };
456
457 if (!chan) {
458 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
459 return -1;
460 }
461
462 if (!cdr_read_message_type()) {
463 ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",
464 ast_channel_name(chan));
465 return -1;
466 }
467
468 payload = ao2_alloc(sizeof(*payload), NULL);
469 if (!payload) {
470 return -1;
471 }
472 payload->chan = chan;
473 payload->cmd = cmd;
474 payload->arguments = parse;
475 payload->data = &output;
476
477 buf[0] = '\0';/* Ensure the buffer is initialized. */
478 output.buf = buf;
479 output.len = len;
480
481 message = stasis_message_create(cdr_read_message_type(), payload);
482 if (!message) {
483 ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
484 ast_channel_name(chan));
485 return -1;
486 }
487
488 /* If this is a request on a dummy channel, we're doing post-processing on an
489 * already dispatched CDR. Simply call the callback to calculate the value and
490 * return, instead of posting to Stasis as we would for a running channel.
491 */
494 } else {
496
497 if (!router) {
498 ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
499 ast_channel_name(chan));
500 return -1;
501 }
503 }
504
505 return 0;
506}
507
508static int cdr_write(struct ast_channel *chan, const char *cmd, char *arguments,
509 const char *value)
510{
511 struct stasis_message *message;
512 struct cdr_func_payload *payload;
515 AST_APP_ARG(variable);
517 );
518 char *parse;
519
520 if (!chan) {
521 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
522 return -1;
523 }
524 if (ast_strlen_zero(arguments)) {
525 ast_log(LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",
526 cmd, cmd);
527 return -1;
528 }
529 if (!value) {
530 ast_log(LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",
531 cmd, cmd);
532 return -1;
533 }
534
535 parse = ast_strdupa(arguments);
537
538 /* These CDR variables are no longer supported or set directly on the channel */
539 if (!strcasecmp(args.variable, "accountcode")) {
540 ast_log(LOG_WARNING, "Using the %s function to set 'accountcode' is deprecated. Please use the CHANNEL function instead.\n",
541 cmd);
542 ast_channel_lock(chan);
543 ast_channel_accountcode_set(chan, value);
544 ast_channel_unlock(chan);
545 return 0;
546 }
547 if (!strcasecmp(args.variable, "amaflags")) {
548 int amaflags;
549
550 ast_log(LOG_WARNING, "Using the %s function to set 'amaflags' is deprecated. Please use the CHANNEL function instead.\n",
551 cmd);
552 if (isdigit(*value)) {
553 if (sscanf(value, "%30d", &amaflags) != 1) {
555 }
556 } else {
558 }
559 ast_channel_lock(chan);
561 ast_channel_unlock(chan);
562 return 0;
563 }
564 if (!strcasecmp(args.variable, "peeraccount")) {
565 ast_log(LOG_WARNING, "The 'peeraccount' setting is not supported. Please set the 'accountcode' on the appropriate channel using the CHANNEL function.\n");
566 return 0;
567 }
568
569 /* The remaining CDR variables are handled by CDR processing code */
570 if (!cdr_write_message_type()) {
571 ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",
572 ast_channel_name(chan));
573 return -1;
574 }
575
576 payload = ao2_alloc(sizeof(*payload), NULL);
577 if (!payload) {
578 return -1;
579 }
580 payload->chan = chan;
581 payload->cmd = cmd;
582 payload->arguments = arguments;
583 payload->value = value;
584
585 message = stasis_message_create(cdr_write_message_type(), payload);
586 ao2_ref(payload, -1);
587 if (!message) {
588 ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
589 ast_channel_name(chan));
590 return -1;
591 }
593 if (!router) {
594 ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
595 ast_channel_name(chan));
596 ao2_ref(message, -1);
597 return -1;
598 }
600 ao2_ref(router, -1);
601 ao2_ref(message, -1);
602
603 return 0;
604}
605
606static int cdr_prop_write(struct ast_channel *chan, const char *cmd, char *parse,
607 const char *value)
608{
610 RAII_VAR(struct cdr_func_payload *, payload, NULL, ao2_cleanup);
612
613 if (!chan) {
614 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
615 return -1;
616 }
617
618 if (!router) {
619 ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
620 ast_channel_name(chan));
621 return -1;
622 }
623
624 if (!cdr_prop_write_message_type()) {
625 ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",
626 ast_channel_name(chan));
627 return -1;
628 }
629
630 payload = ao2_alloc(sizeof(*payload), NULL);
631 if (!payload) {
632 return -1;
633 }
634 payload->chan = chan;
635 payload->cmd = cmd;
636 payload->arguments = parse;
637 payload->value = value;
638
639 message = stasis_message_create(cdr_prop_write_message_type(), payload);
640 if (!message) {
641 ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
642 ast_channel_name(chan));
643 return -1;
644 }
646
647 return 0;
648}
649
651 .name = "CDR",
652 .read = cdr_read,
653 .write = cdr_write,
654};
655
657 .name = "CDR_PROP",
658 .read = NULL,
659 .write = cdr_prop_write,
660};
661
662static int unload_module(void)
663{
665 int res = 0;
666
667 if (router) {
668 stasis_message_router_remove(router, cdr_prop_write_message_type());
669 stasis_message_router_remove(router, cdr_write_message_type());
670 stasis_message_router_remove(router, cdr_read_message_type());
671 }
672 STASIS_MESSAGE_TYPE_CLEANUP(cdr_read_message_type);
673 STASIS_MESSAGE_TYPE_CLEANUP(cdr_write_message_type);
674 STASIS_MESSAGE_TYPE_CLEANUP(cdr_prop_write_message_type);
677
678 return res;
679}
680
681static int load_module(void)
682{
684 int res = 0;
685
686 if (!router) {
688 }
689
690 res |= STASIS_MESSAGE_TYPE_INIT(cdr_read_message_type);
691 res |= STASIS_MESSAGE_TYPE_INIT(cdr_write_message_type);
692 res |= STASIS_MESSAGE_TYPE_INIT(cdr_prop_write_message_type);
695 res |= stasis_message_router_add(router, cdr_prop_write_message_type(),
697 res |= stasis_message_router_add(router, cdr_write_message_type(),
699 res |= stasis_message_router_add(router, cdr_read_message_type(),
701
702 if (res) {
705 }
707}
708
709AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Call Detail Record (CDR) dialplan functions",
710 .support_level = AST_MODULE_SUPPORT_CORE,
711 .load = load_module,
712 .unload = unload_module,
713 .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:3556
struct stasis_message_router * ast_cdr_message_router(void)
Return the message router for the CDR engine.
Definition: cdr.c:4373
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:3654
int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
Set a variable on a CDR.
Definition: cdr.c:3249
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:3116
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:3403
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3509
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:3627
static int amaflags
Definition: chan_iax2.c:476
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2968
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:4392
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:4379
#define ast_channel_unlock(chan)
Definition: channel.h:2969
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:250
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:450
static const struct ast_app_option cdr_func_options[128]
Definition: func_cdr.c:205
static void cdr_prop_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: func_cdr.c:402
static struct ast_custom_function cdr_prop_function
Definition: func_cdr.c:656
cdr_option_flags
Definition: func_cdr.c:197
@ OPT_FLOAT
Definition: func_cdr.c:199
@ OPT_UNPARSED
Definition: func_cdr.c:198
static int cdr_prop_write(struct ast_channel *chan, const char *cmd, char *parse, const char *value)
Definition: func_cdr.c:606
static void cdr_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: func_cdr.c:359
static int cdr_write(struct ast_channel *chan, const char *cmd, char *arguments, const char *value)
Definition: func_cdr.c:508
static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name)
Definition: func_cdr.c:224
static int load_module(void)
Definition: func_cdr.c:681
static int unload_module(void)
Definition: func_cdr.c:662
static struct ast_custom_function cdr_function
Definition: func_cdr.c:650
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:1558
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:216
size_t len
Definition: func_cdr.c:217
const char * cmd
Definition: func_cdr.c:209
struct ast_channel * chan
Definition: func_cdr.c:208
const char * value
Definition: func_cdr.c:211
const char * arguments
Definition: func_cdr.c:210
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