Asterisk - The Open Source Telephony Project GIT-master-0deac78
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 * Mark Spencer <markster@digium.com>
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 API
22 *
23 * \author Mark Spencer <markster@digium.com>
24 *
25 * \note Includes code and algorithms from the Zapata library.
26 *
27 * \note We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip
28 * through our fingers somehow. If someone allocates a CDR, it must be completely handled normally
29 * or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR
30 * isn't properly generated and posted.
31 */
32
33/*! \li \ref cdr.c uses the configuration file \ref cdr.conf
34 * \addtogroup configuration_file Configuration Files
35 */
36
37/*!
38 * \page cdr.conf cdr.conf
39 * \verbinclude cdr.conf.sample
40 */
41
42/*** MODULEINFO
43 <support_level>core</support_level>
44 ***/
45
46#include "asterisk.h"
47
48#include <signal.h>
49#include <inttypes.h>
50
51#include "asterisk/lock.h"
52#include "asterisk/channel.h"
53#include "asterisk/cdr.h"
54#include "asterisk/callerid.h"
55#include "asterisk/manager.h"
56#include "asterisk/module.h"
57#include "asterisk/causes.h"
59#include "asterisk/utils.h"
60#include "asterisk/sched.h"
61#include "asterisk/config.h"
62#include "asterisk/cli.h"
65#include "asterisk/json.h"
66#include "asterisk/parking.h"
67#include "asterisk/stasis.h"
71#include "asterisk/astobj2.h"
73
74/*** DOCUMENTATION
75 <configInfo name="cdr" language="en_US">
76 <synopsis>Call Detail Record configuration</synopsis>
77 <description>
78 <para>CDR is Call Detail Record, which provides logging services via a variety of
79 pluggable backend modules. Detailed call information can be recorded to
80 databases, files, etc. Useful for billing, fraud prevention, compliance with
81 Sarbanes-Oxley aka The Enron Act, QOS evaluations, and more.</para>
82 </description>
83 <configFile name="cdr.conf">
84 <configObject name="general">
85 <since>
86 <version>12.0.0</version>
87 </since>
88 <synopsis>Global settings applied to the CDR engine.</synopsis>
89 <configOption name="debug">
90 <since>
91 <version>12.0.0</version>
92 </since>
93 <synopsis>Enable/disable verbose CDR debugging.</synopsis>
94 <description><para>When set to <literal>True</literal>, verbose updates
95 of changes in CDR information will be logged. Note that this is only
96 of use when debugging CDR behavior.</para>
97 </description>
98 </configOption>
99 <configOption name="enable" default="yes">
100 <since>
101 <version>12.0.0</version>
102 </since>
103 <synopsis>Enable/disable CDR logging.</synopsis>
104 <description><para>Define whether or not to use CDR logging. Setting this to "no" will override
105 any loading of backend CDR modules.</para>
106 </description>
107 </configOption>
108 <configOption name="channeldefaultenabled" default="yes">
109 <since>
110 <version>16.24.0</version>
111 <version>18.10.0</version>
112 <version>19.2.0</version>
113 </since>
114 <synopsis>Whether CDR is enabled on a channel by default</synopsis>
115 <description><para>Define whether or not CDR should be enabled on a channel by default.
116 Setting this to "yes" will enable CDR on every channel unless it is explicitly disabled.
117 Setting this to "no" will disable CDR on every channel unless it is explicitly enabled.
118 </para>
119 <para>Note that CDR must still be globally enabled (<literal>enable = yes</literal>) for this
120 option to have any effect. This only applies to whether CDR is enabled or disabled on
121 newly created channels, which can be changed in the dialplan during a call.</para>
122 <para>If this is set to "yes", you should use <literal>Set(CDR_PROP(disable)=1)</literal>
123 to disable CDR for a call.</para>
124 <para>If this is set to "no", you should use <literal>Set(CDR_PROP(disable)=0)</literal>
125 to undisable (enable) CDR for a call.</para>
126 </description>
127 </configOption>
128 <configOption name="ignorestatechanges" default="no">
129 <since>
130 <version>16.30.0</version>
131 <version>18.16.0</version>
132 <version>19.8.0</version>
133 <version>20.1.0</version>
134 </since>
135 <synopsis>Whether CDR is updated or forked by bridging changes.</synopsis>
136 <description><para>Define whether or not CDR should be updated by bridging changes.
137 This includes entering and leaving bridges and call parking.</para>
138 <para>If this is set to "no", bridging changes will be ignored for all CDRs.
139 This should only be done if these events should not affect CDRs and are undesired,
140 such as to use a single CDR for the lifetime of the channel.</para>
141 <para>This setting cannot be changed on a reload.</para>
142 </description>
143 </configOption>
144 <configOption name="ignoredialchanges" default="no">
145 <since>
146 <version>16.30.0</version>
147 <version>18.16.0</version>
148 <version>19.8.0</version>
149 <version>20.1.0</version>
150 </since>
151 <synopsis>Whether CDR is updated or forked by dial updates.</synopsis>
152 <description><para>Define whether or not CDR should be updated by dial updates.</para>
153 <para>If this is set to "no", a single CDR will be used for the channel, even if
154 multiple endpoints or destinations are dialed sequentially. Note that you will also
155 lose detailed nonanswer dial dispositions if this option is enabled, which may not be acceptable,
156 e.g. instead of detailed no-answer dispositions like BUSY and CONGESTION, the disposition
157 will always be NO ANSWER if the channel was unanswered (it will still be ANSWERED
158 if the channel was answered).</para>
159 <para>This option should be enabled if a single CDR is desired for the lifetime of
160 the channel.</para>
161 </description>
162 </configOption>
163 <configOption name="unanswered">
164 <since>
165 <version>12.0.0</version>
166 </since>
167 <synopsis>Log calls that are never answered and don't set an outgoing party.</synopsis>
168 <description><para>
169 Define whether or not to log unanswered calls that don't involve an outgoing party. Setting
170 this to "yes" will make calls to extensions that don't answer and don't set a side B channel
171 (such as by using the Dial application) receive CDR log entries. If this option is set to
172 "no", then those log entries will not be created. Unanswered calls which get offered to an
173 outgoing line will always receive log entries regardless of this option, and that is the
174 intended behavior.
175 </para>
176 </description>
177 </configOption>
178 <configOption name="congestion">
179 <since>
180 <version>12.0.0</version>
181 </since>
182 <synopsis>Log congested calls.</synopsis>
183 <description><para>Define whether or not to log congested calls. Setting this to "yes" will
184 report each call that fails to complete due to congestion conditions.</para>
185 </description>
186 </configOption>
187 <configOption name="endbeforehexten">
188 <since>
189 <version>12.0.0</version>
190 </since>
191 <synopsis>Don't produce CDRs while executing hangup logic</synopsis>
192 <description>
193 <para>As each CDR for a channel is finished, its end time is updated
194 and the CDR is finalized. When a channel is hung up and hangup
195 logic is present (in the form of a hangup handler or the
196 <literal>h</literal> extension), a new CDR is generated for the
197 channel. Any statistics are gathered from this new CDR. By enabling
198 this option, no new CDR is created for the dialplan logic that is
199 executed in <literal>h</literal> extensions or attached hangup handler
200 subroutines. The default value is <literal>yes</literal>, indicating
201 that a CDR will be generated during hangup logic.</para>
202 </description>
203 </configOption>
204 <configOption name="initiatedseconds">
205 <since>
206 <version>12.0.0</version>
207 </since>
208 <synopsis>Count microseconds for billsec purposes</synopsis>
209 <description><para>Normally, the <literal>billsec</literal> field logged to the CDR backends
210 is simply the end time (hangup time) minus the answer time in seconds. Internally,
211 asterisk stores the time in terms of microseconds and seconds. By setting
212 initiatedseconds to <literal>yes</literal>, you can force asterisk to report any seconds
213 that were initiated (a sort of round up method). Technically, this is
214 when the microsecond part of the end time is greater than the microsecond
215 part of the answer time, then the billsec time is incremented one second.</para>
216 </description>
217 </configOption>
218 <configOption name="batch">
219 <since>
220 <version>12.0.0</version>
221 </since>
222 <synopsis>Submit CDRs to the backends for processing in batches</synopsis>
223 <description><para>Define the CDR batch mode, where instead of posting the CDR at the end of
224 every call, the data will be stored in a buffer to help alleviate load on the
225 asterisk server.</para>
226 <warning><para>Use of batch mode may result in data loss after unsafe asterisk termination,
227 i.e., software crash, power failure, kill -9, etc.</para>
228 </warning>
229 </description>
230 </configOption>
231 <configOption name="size">
232 <since>
233 <version>12.0.0</version>
234 </since>
235 <synopsis>The maximum number of CDRs to accumulate before triggering a batch</synopsis>
236 <description><para>Define the maximum number of CDRs to accumulate in the buffer before posting
237 them to the backend engines. batch must be set to <literal>yes</literal>.</para>
238 </description>
239 </configOption>
240 <configOption name="time">
241 <since>
242 <version>13.22.0</version>
243 <version>15.5.0</version>
244 </since>
245 <synopsis>The maximum time to accumulate CDRs before triggering a batch</synopsis>
246 <description><para>Define the maximum time to accumulate CDRs before posting them in a batch to the
247 backend engines. If this time limit is reached, then it will post the records, regardless of the value
248 defined for size. batch must be set to <literal>yes</literal>.</para>
249 <note><para>Time is expressed in seconds.</para></note>
250 </description>
251 </configOption>
252 <configOption name="scheduleronly">
253 <since>
254 <version>12.0.0</version>
255 </since>
256 <synopsis>Post batched CDRs on their own thread instead of the scheduler</synopsis>
257 <description><para>The CDR engine uses the internal asterisk scheduler to determine when to post
258 records. Posting can either occur inside the scheduler thread, or a new
259 thread can be spawned for the submission of every batch. For small batches,
260 it might be acceptable to just use the scheduler thread, so set this to <literal>yes</literal>.
261 For large batches, say anything over size=10, a new thread is recommended, so
262 set this to <literal>no</literal>.</para>
263 </description>
264 </configOption>
265 <configOption name="safeshutdown">
266 <since>
267 <version>12.0.0</version>
268 </since>
269 <synopsis>Block shutdown of Asterisk until CDRs are submitted</synopsis>
270 <description><para>When shutting down asterisk, you can block until the CDRs are submitted. If
271 you don't, then data will likely be lost. You can always check the size of
272 the CDR batch buffer with the CLI <astcli>cdr status</astcli> command. To enable blocking on
273 submission of CDR data during asterisk shutdown, set this to <literal>yes</literal>.</para>
274 </description>
275 </configOption>
276 <configOption name="canceldispositionenabled" default="no">
277 <synopsis>Whether to enable CANCEL disposition in CDR</synopsis>
278 <description><para>
279 Define if the CANCEL disposition state should be used.
280 When enabled, The NO ANSWER disposition will be split into two distinct dispositions: CANCEL and NO ANSWER.
281 </para>
282 </description>
283 </configOption>
284 </configObject>
285 </configFile>
286 </configInfo>
287 ***/
288
289#define DEFAULT_ENABLED "1"
290#define DEFAULT_BATCHMODE "0"
291#define DEFAULT_UNANSWERED "0"
292#define DEFAULT_CONGESTION "0"
293#define DEFAULT_END_BEFORE_H_EXTEN "1"
294#define DEFAULT_INITIATED_SECONDS "0"
295#define DEFAULT_CHANNEL_ENABLED "1"
296#define DEFAULT_IGNORE_STATE_CHANGES "0"
297#define DEFAULT_IGNORE_DIAL_CHANGES "0"
298
299#define DEFAULT_BATCH_SIZE "100"
300#define MAX_BATCH_SIZE 1000
301#define DEFAULT_BATCH_TIME "300"
302#define MAX_BATCH_TIME 86400
303#define DEFAULT_BATCH_SCHEDULER_ONLY "0"
304#define DEFAULT_BATCH_SAFE_SHUTDOWN "1"
305
306#define cdr_set_debug_mode(mod_cfg) \
307 do { \
308 cdr_debug_enabled = ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG); \
309 } while (0)
310
313
314#define CDR_DEBUG(fmt, ...) \
315 do { \
316 if (cdr_debug_enabled) { \
317 ast_verbose((fmt), ##__VA_ARGS__); \
318 } \
319 } while (0)
320
321static void cdr_detach(struct ast_cdr *cdr);
322static void cdr_submit_batch(int shutdown);
323static int cdr_toggle_runtime_options(void);
324
325/*! \brief The configuration settings for this module */
327 struct ast_cdr_config *general; /*!< CDR global settings */
328};
329
330/*! \brief The container for the module configuration */
331static AO2_GLOBAL_OBJ_STATIC(module_configs);
332
333/*! \brief The type definition for general options */
334static struct aco_type general_option = {
335 .type = ACO_GLOBAL,
336 .name = "general",
337 .item_offset = offsetof(struct module_config, general),
338 .category = "general",
339 .category_match = ACO_WHITELIST_EXACT,
340};
341
342/*! Config sections used by existing modules. Do not add to this list. */
343static const char *ignore_categories[] = {
344 "csv",
345 "custom",
346 "manager",
347 "odbc",
348 "pgsql",
349 "radius",
350 "sqlite",
351 "tds",
352 "mysql",
353 NULL,
354};
355
356static struct aco_type ignore_option = {
357 .type = ACO_IGNORE,
358 .name = "modules",
359 .category = (const char*)ignore_categories,
361};
362
363static void *module_config_alloc(void);
364static void module_config_destructor(void *obj);
365static void module_config_post_apply(void);
366
367/*! \brief The file definition */
368static struct aco_file module_file_conf = {
369 .filename = "cdr.conf",
371};
372
373CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc,
374 .files = ACO_FILES(&module_file_conf),
375 .post_apply_config = module_config_post_apply,
376);
377
379
381{
382 struct module_config *mod_cfg;
383
384 mod_cfg = ao2_global_obj_ref(module_configs);
385 if (!mod_cfg) {
386 return;
387 }
388 cdr_set_debug_mode(mod_cfg);
389 ao2_cleanup(mod_cfg);
390}
391
392/*! \brief Dispose of a module config object */
393static void module_config_destructor(void *obj)
394{
395 struct module_config *cfg = obj;
396
397 if (!cfg) {
398 return;
399 }
400 ao2_ref(cfg->general, -1);
401}
402
403/*! \brief Create a new module config object */
404static void *module_config_alloc(void)
405{
406 struct module_config *mod_cfg;
408
409 mod_cfg = ao2_alloc(sizeof(*mod_cfg), module_config_destructor);
410 if (!mod_cfg) {
411 return NULL;
412 }
413
414 cdr_config = ao2_alloc(sizeof(*cdr_config), NULL);
415 if (!cdr_config) {
416 ao2_ref(cdr_config, -1);
417 return NULL;
418 }
419 mod_cfg->general = cdr_config;
420
421 return mod_cfg;
422}
423
424/*! \brief Registration object for CDR backends */
426 char name[20];
427 char desc[80];
430 int suspended:1;
431};
432
433/*! \brief List of registered backends */
435
436/*! \brief List of registered modifiers */
438
439/*! \brief Queued CDR waiting to be batched */
441 struct ast_cdr *cdr;
443};
444
445/*! \brief The actual batch queue */
446static struct cdr_batch {
447 int size;
451
452/*! \brief The global sequence counter used for CDRs */
453static int global_cdr_sequence = 0;
454
455/*! \brief Scheduler items */
457static int cdr_sched = -1;
459static pthread_t cdr_thread = AST_PTHREADT_NULL;
460
461/*! \brief Lock protecting modifications to the batch queue */
463
464/*! \brief These are used to wake up the CDR thread when there's work to do */
467
468/*! \brief A container of the active master CDRs indexed by Party A channel uniqueid */
470
471/*! \brief A container of all active CDRs with a Party B indexed by Party B channel name */
473
474/*! \brief Message router for stasis messages regarding channel state */
476
477/*! \brief Our subscription for bridges */
479
480/*! \brief Our subscription for channels */
482
483/*! \brief Our subscription for parking */
485
486/*! \brief The parent topic for all topics we want to aggregate for CDRs */
487static struct stasis_topic *cdr_topic;
488
489/*! \brief A message type used to synchronize with the CDR topic */
490STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_sync_message_type);
491
492struct cdr_object;
493
494/*! \brief Return types for \p process_bridge_enter functions */
496 /*!
497 * The CDR was the only party in the bridge.
498 */
500 /*!
501 * The CDR was able to obtain a Party B from some other party already in the bridge
502 */
504 /*!
505 * The CDR was not able to obtain a Party B
506 */
508 /*!
509 * This CDR can't handle a bridge enter message and a new CDR needs to be created
510 */
512};
513
514/*!
515 * \brief A virtual table used for \ref cdr_object.
516 *
517 * Note that all functions are optional - if a subclass does not need an
518 * implementation, it is safe to leave it NULL.
519 */
521 /*! \brief Name of the subclass */
522 const char *name;
523
524 /*!
525 * \brief An initialization function. This will be called automatically
526 * when a \ref cdr_object is switched to this type in
527 * \ref cdr_object_transition_state
528 *
529 * \param cdr The \ref cdr_object that was just transitioned
530 */
531 void (* const init_function)(struct cdr_object *cdr);
532
533 /*!
534 * \brief Process a Party A update for the \ref cdr_object
535 *
536 * \param cdr The \ref cdr_object to process the update
537 * \param snapshot The snapshot for the CDR's Party A
538 * \retval 0 the CDR handled the update or ignored it
539 * \retval 1 the CDR is finalized and a new one should be made to handle it
540 */
541 int (* const process_party_a)(struct cdr_object *cdr,
542 struct ast_channel_snapshot *snapshot);
543
544 /*!
545 * \brief Process a Party B update for the \ref cdr_object
546 *
547 * \param cdr The \ref cdr_object to process the update
548 * \param snapshot The snapshot for the CDR's Party B
549 */
550 void (* const process_party_b)(struct cdr_object *cdr,
551 struct ast_channel_snapshot *snapshot);
552
553 /*!
554 * \brief Process the beginning of a dial. A dial message implies one of two
555 * things:
556 * The \ref cdr_object's Party A has been originated
557 * The \ref cdr_object's Party A is dialing its Party B
558 *
559 * \param cdr The \ref cdr_object
560 * \param caller The originator of the dial attempt
561 * \param peer The destination of the dial attempt
562 *
563 * \retval 0 if the parties in the dial were handled by this CDR
564 * \retval 1 if the parties could not be handled by this CDR
565 */
566 int (* const process_dial_begin)(struct cdr_object *cdr,
568 struct ast_channel_snapshot *peer);
569
570 /*!
571 * \brief Process the end of a dial. At the end of a dial, a CDR can be
572 * transitioned into one of two states - DialedPending
573 * (\ref dialed_pending_state_fn_table) or Finalized
574 * (\ref finalized_state_fn_table).
575 *
576 * \param cdr The \ref cdr_object
577 * \param caller The originator of the dial attempt
578 * \param peer the Destination of the dial attempt
579 * \param dial_status What happened
580 *
581 * \retval 0 if the parties in the dial were handled by this CDR
582 * \retval 1 if the parties could not be handled by this CDR
583 */
584 int (* const process_dial_end)(struct cdr_object *cdr,
587 const char *dial_status);
588
589 /*!
590 * \brief Process the entering of a bridge by this CDR. The purpose of this
591 * callback is to have the CDR prepare itself for the bridge and attempt to
592 * find a valid Party B. The act of creating new CDRs based on the entering
593 * of this channel into the bridge is handled by the higher level message
594 * handler.
595 *
596 * Note that this handler is for when a channel enters into a "normal"
597 * bridge, where people actually talk to each other. Parking is its own
598 * thing.
599 *
600 * \param cdr The \ref cdr_object
601 * \param bridge The bridge that the Party A just entered into
602 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
603 *
604 * \return process_bridge_enter_results Defines whether or not this CDR was able
605 * to fully handle the bridge enter message.
606 */
608 struct cdr_object *cdr,
609 struct ast_bridge_snapshot *bridge,
610 struct ast_channel_snapshot *channel);
611
612 /*!
613 * \brief Process entering into a parking bridge.
614 *
615 * \param cdr The \ref cdr_object
616 * \param bridge The parking bridge that Party A just entered into
617 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
618 *
619 * \retval 0 This CDR successfully transitioned itself into the parked state
620 * \retval 1 This CDR couldn't handle the parking transition and we need a
621 * new CDR.
622 */
623 int (* const process_parking_bridge_enter)(struct cdr_object *cdr,
624 struct ast_bridge_snapshot *bridge,
625 struct ast_channel_snapshot *channel);
626
627 /*!
628 * \brief Process the leaving of a bridge by this CDR.
629 *
630 * \param cdr The \ref cdr_object
631 * \param bridge The bridge that the Party A just left
632 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
633 *
634 * \retval 0 This CDR left successfully
635 * \retval 1 Error
636 */
637 int (* const process_bridge_leave)(struct cdr_object *cdr,
638 struct ast_bridge_snapshot *bridge,
639 struct ast_channel_snapshot *channel);
640
641 /*!
642 * \brief Process an update informing us that the channel got itself parked
643 *
644 * \param cdr The \ref cdr_object
645 * \param channel The parking information for this CDR's party A
646 *
647 * \retval 0 This CDR successfully parked itself
648 * \retval 1 This CDR couldn't handle the park
649 */
650 int (* const process_parked_channel)(struct cdr_object *cdr,
651 struct ast_parked_call_payload *parking_info);
652};
653
654static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
656static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
657static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
658static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info);
659
660static void single_state_init_function(struct cdr_object *cdr);
661static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
662static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
664static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
665
666/*!
667 * \brief The virtual table for the Single state.
668 *
669 * A \ref cdr_object starts off in this state. This represents a channel that
670 * has no Party B information itself.
671 *
672 * A \ref cdr_object from this state can go into any of the following states:
673 * * \ref dial_state_fn_table
674 * * \ref bridge_state_fn_table
675 * * \ref finalized_state_fn_table
676 */
678 .name = "Single",
679 .init_function = single_state_init_function,
680 .process_party_a = base_process_party_a,
681 .process_party_b = single_state_process_party_b,
682 .process_dial_begin = single_state_process_dial_begin,
683 .process_dial_end = base_process_dial_end,
684 .process_bridge_enter = single_state_process_bridge_enter,
685 .process_parking_bridge_enter = single_state_process_parking_bridge_enter,
686 .process_bridge_leave = base_process_bridge_leave,
687 .process_parked_channel = base_process_parked_channel,
688};
689
690static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
691static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
692static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
694
695/*!
696 * \brief The virtual table for the Dial state.
697 *
698 * A \ref cdr_object that has begun a dial operation. This state is entered when
699 * the Party A for a CDR is determined to be dialing out to a Party B or when
700 * a CDR is for an originated channel (in which case the Party A information is
701 * the originated channel, and there is no Party B).
702 *
703 * A \ref cdr_object from this state can go in any of the following states:
704 * * \ref dialed_pending_state_fn_table
705 * * \ref bridge_state_fn_table
706 * * \ref finalized_state_fn_table
707 */
709 .name = "Dial",
710 .process_party_a = base_process_party_a,
711 .process_party_b = dial_state_process_party_b,
712 .process_dial_begin = dial_state_process_dial_begin,
713 .process_dial_end = dial_state_process_dial_end,
714 .process_bridge_enter = dial_state_process_bridge_enter,
715 .process_bridge_leave = base_process_bridge_leave,
716};
717
718static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
719static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
722
723/*!
724 * \brief The virtual table for the Dialed Pending state.
725 *
726 * A \ref cdr_object that has successfully finished a dial operation, but we
727 * don't know what they're going to do yet. It's theoretically possible to dial
728 * a party and then have that party not be bridged with the caller; likewise,
729 * an origination can complete and the channel go off and execute dialplan. The
730 * pending state acts as a bridge between either:
731 * * Entering a bridge
732 * * Getting a new CDR for new dialplan execution
733 * * Switching from being originated to executing dialplan
734 *
735 * A \ref cdr_object from this state can go in any of the following states:
736 * * \ref single_state_fn_table
737 * * \ref dialed_pending_state_fn_table
738 * * \ref bridge_state_fn_table
739 * * \ref finalized_state_fn_table
740 */
742 .name = "DialedPending",
743 .process_party_a = dialed_pending_state_process_party_a,
744 .process_dial_begin = dialed_pending_state_process_dial_begin,
745 .process_bridge_enter = dialed_pending_state_process_bridge_enter,
746 .process_parking_bridge_enter = dialed_pending_state_process_parking_bridge_enter,
747 .process_bridge_leave = base_process_bridge_leave,
748 .process_parked_channel = base_process_parked_channel,
749};
750
751static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
752static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
753
754/*!
755 * \brief The virtual table for the Bridged state
756 *
757 * A \ref cdr_object enters this state when it receives notification that the
758 * channel has entered a bridge.
759 *
760 * A \ref cdr_object from this state can go to:
761 * * \ref finalized_state_fn_table
762 */
764 .name = "Bridged",
765 .process_party_a = base_process_party_a,
766 .process_party_b = bridge_state_process_party_b,
767 .process_bridge_leave = bridge_state_process_bridge_leave,
768 .process_parked_channel = base_process_parked_channel,
769};
770
771static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
772
773/*!
774 * \brief The virtual table for the Parked state
775 *
776 * Parking is weird. Unlike typical bridges, it has to be treated somewhat
777 * uniquely - a channel in a parking bridge (which is a subclass of a holding
778 * bridge) has to be handled as if the channel went into an application.
779 * However, when the channel comes out, we need a new CDR - unlike the Single
780 * state.
781 */
783 .name = "Parked",
784 .process_party_a = base_process_party_a,
785 .process_bridge_leave = parked_state_process_bridge_leave,
786 .process_parked_channel = base_process_parked_channel,
787};
788
789static void finalized_state_init_function(struct cdr_object *cdr);
790static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
791
792/*!
793 * \brief The virtual table for the finalized state.
794 *
795 * Once in the finalized state, the CDR is done. No modifications can be made
796 * to the CDR.
797 */
799 .name = "Finalized",
800 .init_function = finalized_state_init_function,
801 .process_party_a = finalized_state_process_party_a,
802 .process_bridge_enter = base_process_bridge_enter,
803};
804
805/*! \brief A wrapper object around a snapshot.
806 * Fields that are mutable by the CDR engine are replicated here.
807 */
809 struct ast_channel_snapshot *snapshot; /*!< The channel snapshot */
810 char userfield[AST_MAX_USER_FIELD]; /*!< Userfield for the channel */
811 unsigned int flags; /*!< Specific flags for this party */
812 struct varshead variables; /*!< CDR variables for the channel */
813};
814
815/*! \brief An in-memory representation of an active CDR */
817 struct cdr_object_snapshot party_a; /*!< The Party A information */
818 struct cdr_object_snapshot party_b; /*!< The Party B information */
819 struct cdr_object_fn_table *fn_table; /*!< The current virtual table */
820
821 enum ast_cdr_disposition disposition; /*!< The disposition of the CDR */
822 struct timeval start; /*!< When this CDR was created */
823 struct timeval answer; /*!< Either when the channel was answered, or when the path between channels was established */
824 struct timeval end; /*!< When this CDR was finalized */
825 struct timeval lastevent; /*!< The time at which the last event was created regarding this CDR */
826 unsigned int sequence; /*!< A monotonically increasing number for each CDR */
827 struct ast_flags flags; /*!< Flags on the CDR */
829 AST_STRING_FIELD(linkedid); /*!< Linked ID. Cached here as it may change out from party A, which must be immutable */
830 AST_STRING_FIELD(uniqueid); /*!< Unique id of party A. Cached here as it is the master CDR container key */
831 AST_STRING_FIELD(tenantid); /*!< Tenant ID. Cached here because the value can be manipulated through dialplan */
832 AST_STRING_FIELD(name); /*!< Channel name of party A. Cached here as the party A address may change */
833 AST_STRING_FIELD(bridge); /*!< The bridge the party A happens to be in. */
834 AST_STRING_FIELD(appl); /*!< The last accepted application party A was in */
835 AST_STRING_FIELD(data); /*!< The data for the last accepted application party A was in */
836 AST_STRING_FIELD(context); /*!< The accepted context for Party A */
837 AST_STRING_FIELD(exten); /*!< The accepted extension for Party A */
838 AST_STRING_FIELD(party_b_name); /*!< Party B channel name. Cached here as it is the all CDRs container key */
839 );
840 struct cdr_object *next; /*!< The next CDR object in the chain */
841 struct cdr_object *last; /*!< The last CDR object in the chain */
842 int is_root; /*!< True if this is the first CDR in the chain */
843};
844
845/*!
846 * \brief Copy variables from one list to another
847 * \param to_list destination
848 * \param from_list source
849 * \return The number of copied variables
850 */
851static int copy_variables(struct varshead *to_list, struct varshead *from_list)
852{
853 struct ast_var_t *variables;
854 struct ast_var_t *newvariable;
855 const char *var;
856 const char *val;
857 int x = 0;
858
859 AST_LIST_TRAVERSE(from_list, variables, entries) {
860 var = ast_var_name(variables);
861 if (ast_strlen_zero(var)) {
862 continue;
863 }
864 val = ast_var_value(variables);
865 if (ast_strlen_zero(val)) {
866 continue;
867 }
868 newvariable = ast_var_assign(var, val);
869 if (newvariable) {
870 AST_LIST_INSERT_HEAD(to_list, newvariable, entries);
871 ++x;
872 }
873 }
874
875 return x;
876}
877
878/*!
879 * \brief Delete all variables from a variable list
880 * \param headp The head pointer to the variable list to delete
881 */
882static void free_variables(struct varshead *headp)
883{
884 struct ast_var_t *vardata;
885
886 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
887 ast_var_delete(vardata);
888 }
889}
890
891/*!
892 * \brief Copy a snapshot and its details
893 * \param dst The destination
894 * \param src The source
895 */
897{
898 ao2_t_replace(dst->snapshot, src->snapshot, "CDR snapshot copy");
899 strcpy(dst->userfield, src->userfield);
900 dst->flags = src->flags;
901 copy_variables(&dst->variables, &src->variables);
902}
903
904/*!
905 * \brief Transition a \ref cdr_object to a new state with initiation flag
906 * \param cdr The \ref cdr_object to transition
907 * \param fn_table The \ref cdr_object_fn_table state to go to
908 * \param do_init
909 */
910static void cdr_object_transition_state_init(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table, int do_init)
911{
912 CDR_DEBUG("%p - Transitioning CDR for %s from state %s to %s\n",
913 cdr, cdr->party_a.snapshot->base->name,
914 cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
915 cdr->fn_table = fn_table;
916
917 if (cdr->fn_table->init_function && do_init) {
918 cdr->fn_table->init_function(cdr);
919 }
920}
921
922/*!
923 * \brief Transition a \ref cdr_object to a new state
924 * \param cdr The \ref cdr_object to transition
925 * \param fn_table The \ref cdr_object_fn_table state to go to
926 */
927static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
928{
929 cdr_object_transition_state_init(cdr, fn_table, 1);
930}
931
932/*!
933 * \internal
934 * \brief Hash function for master CDR container indexed by Party A uniqueid.
935 */
936static int cdr_master_hash_fn(const void *obj, const int flags)
937{
938 const struct cdr_object *cdr;
939 const char *key;
940
941 switch (flags & OBJ_SEARCH_MASK) {
942 case OBJ_SEARCH_KEY:
943 key = obj;
944 break;
946 cdr = obj;
947 key = cdr->uniqueid;
948 break;
949 default:
950 ast_assert(0);
951 return 0;
952 }
953 return ast_str_case_hash(key);
954}
955
956/*!
957 * \internal
958 * \brief Comparison function for master CDR container indexed by Party A uniqueid.
959 */
960static int cdr_master_cmp_fn(void *obj, void *arg, int flags)
961{
962 struct cdr_object *left = obj;
963 struct cdr_object *right = arg;
964 const char *right_key = arg;
965 int cmp;
966
967 switch (flags & OBJ_SEARCH_MASK) {
969 right_key = right->uniqueid;
970 /* Fall through */
971 case OBJ_SEARCH_KEY:
972 cmp = strcmp(left->uniqueid, right_key);
973 break;
975 /*
976 * We could also use a partial key struct containing a length
977 * so strlen() does not get called for every comparison instead.
978 */
979 cmp = strncmp(left->uniqueid, right_key, strlen(right_key));
980 break;
981 default:
982 /* Sort can only work on something with a full or partial key. */
983 ast_assert(0);
984 cmp = 0;
985 break;
986 }
987 return cmp ? 0 : CMP_MATCH;
988}
989
990/*!
991 * \internal
992 * \brief Hash function for all CDR container indexed by Party B channel name.
993 */
994static int cdr_all_hash_fn(const void *obj, const int flags)
995{
996 const struct cdr_object *cdr;
997 const char *key;
998
999 switch (flags & OBJ_SEARCH_MASK) {
1000 case OBJ_SEARCH_KEY:
1001 key = obj;
1002 break;
1003 case OBJ_SEARCH_OBJECT:
1004 cdr = obj;
1005 key = cdr->party_b_name;
1006 break;
1007 default:
1008 ast_assert(0);
1009 return 0;
1010 }
1011 return ast_str_case_hash(key);
1012}
1013
1014/*!
1015 * \internal
1016 * \brief Comparison function for all CDR container indexed by Party B channel name.
1017 */
1018static int cdr_all_cmp_fn(void *obj, void *arg, int flags)
1019{
1020 struct cdr_object *left = obj;
1021 struct cdr_object *right = arg;
1022 const char *right_key = arg;
1023 int cmp;
1024
1025 switch (flags & OBJ_SEARCH_MASK) {
1026 case OBJ_SEARCH_OBJECT:
1027 right_key = right->party_b_name;
1028 /* Fall through */
1029 case OBJ_SEARCH_KEY:
1030 cmp = strcasecmp(left->party_b_name, right_key);
1031 break;
1033 /*
1034 * We could also use a partial key struct containing a length
1035 * so strlen() does not get called for every comparison instead.
1036 */
1037 cmp = strncasecmp(left->party_b_name, right_key, strlen(right_key));
1038 break;
1039 default:
1040 /* Sort can only work on something with a full or partial key. */
1041 ast_assert(0);
1042 cmp = 0;
1043 break;
1044 }
1045 return cmp ? 0 : CMP_MATCH;
1046}
1047
1048/*!
1049 * \internal
1050 * \brief Relink the CDR because Party B's snapshot changed.
1051 * \since 13.19.0
1052 */
1053static void cdr_all_relink(struct cdr_object *cdr)
1054{
1056 if (cdr->party_b.snapshot) {
1057 if (strcasecmp(cdr->party_b_name, cdr->party_b.snapshot->base->name)) {
1061 }
1062 } else {
1065 }
1067}
1068
1069/*!
1070 * \internal
1071 * \brief Unlink the master CDR and chained records from the active_cdrs_all container.
1072 * \since 13.19.0
1073 */
1074static void cdr_all_unlink(struct cdr_object *cdr)
1075{
1076 struct cdr_object *cur;
1077 struct cdr_object *next;
1078
1079 ast_assert(cdr->is_root);
1080
1081 /* Hold a ref to the root CDR to ensure the list members don't go away on us. */
1082 ao2_ref(cdr, +1);
1084 for (cur = cdr; cur; cur = next) {
1085 next = cur->next;
1087 /*
1088 * It is safe to still use cur after unlinking because the
1089 * root CDR holds a ref to all the CDRs in the list and we
1090 * have a ref to the root CDR.
1091 */
1093 }
1095 ao2_ref(cdr, -1);
1096}
1097
1098/*!
1099 * \brief \ref cdr_object Destructor
1100 */
1101static void cdr_object_dtor(void *obj)
1102{
1103 struct cdr_object *cdr = obj;
1104 struct ast_var_t *it_var;
1105
1108 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_a.variables, entries))) {
1109 ast_var_delete(it_var);
1110 }
1111 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_b.variables, entries))) {
1112 ast_var_delete(it_var);
1113 }
1115
1116 /* CDR destruction used to work by calling ao2_cleanup(next) and
1117 * allowing the chain to destroy itself neatly. Unfortunately, for
1118 * really long chains, this can result in a stack overflow. So now
1119 * when the root CDR is destroyed, it is responsible for unreffing
1120 * all CDRs in the chain
1121 */
1122 if (cdr->is_root) {
1123 struct cdr_object *curr = cdr->next;
1124 struct cdr_object *next;
1125
1126 while (curr) {
1127 next = curr->next;
1128 ao2_cleanup(curr);
1129 curr = next;
1130 }
1131 }
1132}
1133
1134/*!
1135 * \brief \ref cdr_object constructor
1136 * \param chan The \ref ast_channel_snapshot that is the CDR's Party A
1137 * \param event_time
1138 *
1139 * This implicitly sets the state of the newly created CDR to the Single state
1140 * (\ref single_state_fn_table)
1141 */
1142static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
1143{
1144 struct cdr_object *cdr;
1145
1146 ast_assert(chan != NULL);
1147
1148 cdr = ao2_alloc(sizeof(*cdr), cdr_object_dtor);
1149 if (!cdr) {
1150 return NULL;
1151 }
1152 cdr->last = cdr;
1153 if (ast_string_field_init(cdr, 64)) {
1154 ao2_cleanup(cdr);
1155 return NULL;
1156 }
1158 ast_string_field_set(cdr, name, chan->base->name);
1162 cdr->lastevent = *event_time;
1163
1164 cdr->party_a.snapshot = chan;
1165 ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
1166
1167 CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->base->name);
1168
1170
1171 return cdr;
1172}
1173
1174/*!
1175 * \brief Create a new \ref cdr_object and append it to an existing chain
1176 * \param cdr The \ref cdr_object to append to
1177 * \param event_time
1178 */
1179static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
1180{
1181 struct cdr_object *new_cdr;
1182 struct cdr_object *it_cdr;
1183 struct cdr_object *cdr_last;
1184
1185 cdr_last = cdr->last;
1186 new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot, event_time);
1187 if (!new_cdr) {
1188 return NULL;
1189 }
1190 new_cdr->disposition = AST_CDR_NULL;
1191
1192 /* Copy over the linkedid, as it may have changed */
1193 ast_string_field_set(new_cdr, linkedid, cdr_last->linkedid);
1194 ast_string_field_set(new_cdr, appl, cdr_last->appl);
1195 ast_string_field_set(new_cdr, data, cdr_last->data);
1196 ast_string_field_set(new_cdr, context, cdr_last->context);
1197 ast_string_field_set(new_cdr, exten, cdr_last->exten);
1198
1199 /*
1200 * If the current CDR says to disable all future ones,
1201 * keep the disable chain going
1202 */
1203 if (ast_test_flag(&cdr_last->flags, AST_CDR_FLAG_DISABLE_ALL)) {
1205 }
1206
1207 /* Copy over other Party A information */
1208 cdr_object_snapshot_copy(&new_cdr->party_a, &cdr_last->party_a);
1209
1210 /* Append the CDR to the end of the list */
1211 for (it_cdr = cdr; it_cdr->next; it_cdr = it_cdr->next) {
1212 it_cdr->last = new_cdr;
1213 }
1214 it_cdr->last = new_cdr;
1215 it_cdr->next = new_cdr;
1216
1217 return new_cdr;
1218}
1219
1220/*!
1221 * \internal
1222 * \brief Determine if CDR flag is configured.
1223 *
1224 * \param cdr_flag The configured CDR flag to check.
1225 *
1226 * \retval 0 if the CDR flag is not configured.
1227 * \retval non-zero if the CDR flag is configured.
1228 */
1229static int is_cdr_flag_set(unsigned int cdr_flag)
1230{
1231 struct module_config *mod_cfg;
1232 int flag_set;
1233
1234 mod_cfg = ao2_global_obj_ref(module_configs);
1235 flag_set = mod_cfg && ast_test_flag(&mod_cfg->general->settings, cdr_flag);
1236 ao2_cleanup(mod_cfg);
1237 return flag_set;
1238}
1239
1240/*!
1241 * \brief Return whether or not a channel has changed its state in the dialplan, subject
1242 * to endbeforehexten logic
1243 *
1244 * \param old_snapshot The previous state
1245 * \param new_snapshot The new state
1246 *
1247 * \retval 0 if the state has not changed
1248 * \retval 1 if the state changed
1249 */
1250static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
1251 struct ast_channel_snapshot *new_snapshot)
1252{
1253 /* If we ignore hangup logic, don't indicate that we're executing anything new */
1256 return 0;
1257 }
1258
1259 /* When Party A is originated to an application and the application exits, the stack
1260 * will attempt to clear the application and restore the dummy originate application
1261 * of "AppDialX". Ignore application changes to AppDialX as a result.
1262 */
1263 if (strcmp(new_snapshot->dialplan->appl, old_snapshot->dialplan->appl)
1264 && strncasecmp(new_snapshot->dialplan->appl, "appdial", 7)
1265 && (strcmp(new_snapshot->dialplan->context, old_snapshot->dialplan->context)
1266 || strcmp(new_snapshot->dialplan->exten, old_snapshot->dialplan->exten)
1267 || new_snapshot->dialplan->priority != old_snapshot->dialplan->priority)) {
1268 return 1;
1269 }
1270
1271 return 0;
1272}
1273
1274/*!
1275 * \brief Return whether or not a \ref ast_channel_snapshot is for a channel
1276 * that was created as the result of a dial operation
1277 *
1278 * \retval 0 the channel was not created as the result of a dial
1279 * \retval 1 the channel was created as the result of a dial
1280 */
1281static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
1282{
1283 return (ast_test_flag(&snapshot->flags, AST_FLAG_OUTGOING)
1284 && !(ast_test_flag(&snapshot->flags, AST_FLAG_ORIGINATED)));
1285}
1286
1287/*!
1288 * \brief Given two CDR snapshots, figure out who should be Party A for the
1289 * resulting CDR
1290 * \param left One of the snapshots
1291 * \param right The other snapshot
1292 * \return The snapshot that won
1293 */
1295{
1296 /* Check whether or not the party is dialed. A dialed party is never the
1297 * Party A with a party that was not dialed.
1298 */
1299 if (!snapshot_is_dialed(left->snapshot) && snapshot_is_dialed(right->snapshot)) {
1300 return left;
1301 } else if (snapshot_is_dialed(left->snapshot) && !snapshot_is_dialed(right->snapshot)) {
1302 return right;
1303 }
1304
1305 /* Try the Party A flag */
1307 return left;
1309 return right;
1310 }
1311
1312 /* Neither party is dialed and neither has the Party A flag - defer to
1313 * creation time */
1314 if (left->snapshot->base->creationtime.tv_sec < right->snapshot->base->creationtime.tv_sec) {
1315 return left;
1316 } else if (left->snapshot->base->creationtime.tv_sec > right->snapshot->base->creationtime.tv_sec) {
1317 return right;
1318 } else if (left->snapshot->base->creationtime.tv_usec > right->snapshot->base->creationtime.tv_usec) {
1319 return right;
1320 } else {
1321 /* Okay, fine, take the left one */
1322 return left;
1323 }
1324}
1325
1326/*!
1327 * Compute the duration for a \ref cdr_object
1328 */
1329static long cdr_object_get_duration(struct cdr_object *cdr)
1330{
1331 return (long)(ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->start) / 1000);
1332}
1333
1334/*!
1335 * \brief Compute the billsec for a \ref cdr_object
1336 */
1337static long cdr_object_get_billsec(struct cdr_object *cdr)
1338{
1339 long int ms;
1340
1341 if (ast_tvzero(cdr->answer)) {
1342 return 0;
1343 }
1344
1345 ms = ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->answer);
1346 if (ms % 1000 >= 500
1348 ms = (ms / 1000) + 1;
1349 } else {
1350 ms = ms / 1000;
1351 }
1352
1353 return ms;
1354}
1355
1356/*!
1357 * \internal
1358 * \brief Set a variable on a CDR object
1359 *
1360 * \param headp The header pointer to the variable to set
1361 * \param name The name of the variable
1362 * \param value The value of the variable
1363 */
1364static void set_variable(struct varshead *headp, const char *name, const char *value)
1365{
1366 struct ast_var_t *newvariable;
1367
1368 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1369 if (!strcasecmp(ast_var_name(newvariable), name)) {
1371 ast_var_delete(newvariable);
1372 break;
1373 }
1374 }
1376
1377 if (value && (newvariable = ast_var_assign(name, value))) {
1378 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1379 }
1380}
1381
1382/*!
1383 * \brief Create a chain of \ref ast_cdr objects from a chain of \ref cdr_object
1384 * suitable for consumption by the registered CDR backends
1385 * \param cdr The \ref cdr_object to convert to a public record
1386 * \return A chain of \ref ast_cdr objects on success
1387 * \retval NULL on failure
1388 */
1390{
1391 struct ast_cdr *pub_cdr = NULL, *cdr_prev = NULL;
1392 struct cdr_object *it_cdr;
1393 struct ast_var_t *it_var, *it_copy_var;
1394 struct ast_channel_snapshot *party_a;
1395 struct ast_channel_snapshot *party_b;
1396
1397 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1398 struct ast_cdr *cdr_copy;
1399
1400 /* Don't create records for CDRs where the party A was a dialed channel */
1401 if (snapshot_is_dialed(it_cdr->party_a.snapshot) && !it_cdr->party_b.snapshot) {
1402 ast_debug(1, "CDR for %s is dialed and has no Party B; discarding\n",
1403 it_cdr->party_a.snapshot->base->name);
1404 continue;
1405 }
1406
1407 cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
1408 if (!cdr_copy) {
1409 ast_free(pub_cdr);
1410 return NULL;
1411 }
1412
1413 party_a = it_cdr->party_a.snapshot;
1414 party_b = it_cdr->party_b.snapshot;
1415
1416 /* Party A */
1417 ast_assert(party_a != NULL);
1418 ast_copy_string(cdr_copy->accountcode, party_a->base->accountcode, sizeof(cdr_copy->accountcode));
1419 cdr_copy->amaflags = party_a->amaflags;
1420 ast_copy_string(cdr_copy->channel, party_a->base->name, sizeof(cdr_copy->channel));
1421 ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller->name, party_a->caller->number, "");
1422 ast_copy_string(cdr_copy->src, party_a->caller->number, sizeof(cdr_copy->src));
1423 ast_copy_string(cdr_copy->uniqueid, party_a->base->uniqueid, sizeof(cdr_copy->uniqueid));
1424 ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
1425 ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
1426 ast_copy_string(cdr_copy->dst, it_cdr->exten, sizeof(cdr_copy->dst));
1427 ast_copy_string(cdr_copy->dcontext, it_cdr->context, sizeof(cdr_copy->dcontext));
1428 ast_copy_string(cdr_copy->tenantid, party_a->base->tenantid, sizeof(cdr_copy->tenantid));
1429
1430 /* Party B */
1431 if (party_b) {
1432 ast_copy_string(cdr_copy->dstchannel, party_b->base->name, sizeof(cdr_copy->dstchannel));
1433 ast_copy_string(cdr_copy->peeraccount, party_b->base->accountcode, sizeof(cdr_copy->peeraccount));
1434 if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
1435 snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
1436 }
1437 ast_copy_string(cdr_copy->peertenantid, party_b->base->tenantid, sizeof(cdr_copy->peertenantid));
1438 }
1439 if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) {
1440 ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield));
1441 }
1442
1443 /* Timestamps/durations */
1444 cdr_copy->start = it_cdr->start;
1445 cdr_copy->answer = it_cdr->answer;
1446 cdr_copy->end = it_cdr->end;
1447 cdr_copy->billsec = cdr_object_get_billsec(it_cdr);
1448 cdr_copy->duration = cdr_object_get_duration(it_cdr);
1449
1450 /* Flags and IDs */
1451 ast_copy_flags(cdr_copy, &it_cdr->flags, AST_FLAGS_ALL);
1452 ast_copy_string(cdr_copy->linkedid, it_cdr->linkedid, sizeof(cdr_copy->linkedid));
1453 cdr_copy->disposition = it_cdr->disposition;
1454 cdr_copy->sequence = it_cdr->sequence;
1455
1456 /* Variables */
1457 copy_variables(&cdr_copy->varshead, &it_cdr->party_a.variables);
1458 AST_LIST_TRAVERSE(&it_cdr->party_b.variables, it_var, entries) {
1459 int found = 0;
1460 struct ast_var_t *newvariable;
1461 AST_LIST_TRAVERSE(&cdr_copy->varshead, it_copy_var, entries) {
1462 if (!strcasecmp(ast_var_name(it_var), ast_var_name(it_copy_var))) {
1463 found = 1;
1464 break;
1465 }
1466 }
1467 if (!found && (newvariable = ast_var_assign(ast_var_name(it_var), ast_var_value(it_var)))) {
1468 AST_LIST_INSERT_TAIL(&cdr_copy->varshead, newvariable, entries);
1469 }
1470 }
1471
1472 if (!pub_cdr) {
1473 pub_cdr = cdr_copy;
1474 cdr_prev = pub_cdr;
1475 } else {
1476 cdr_prev->next = cdr_copy;
1477 cdr_prev = cdr_copy;
1478 }
1479 }
1480
1481 return pub_cdr;
1482}
1483
1484/*!
1485 * \brief Dispatch a CDR.
1486 * \param cdr The \ref cdr_object to dispatch
1487 *
1488 * This will create a \ref ast_cdr object and publish it to the various backends
1489 */
1490static void cdr_object_dispatch(struct cdr_object *cdr)
1491{
1492 struct ast_cdr *pub_cdr;
1493
1494 CDR_DEBUG("%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
1495 cdr->party_a.snapshot->base->name,
1496 cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<none>");
1497 pub_cdr = cdr_object_create_public_records(cdr);
1498 cdr_detach(pub_cdr);
1499}
1500
1501/*!
1502 * \brief Set the disposition on a \ref cdr_object based on a hangupcause code
1503 * \param cdr The \ref cdr_object
1504 * \param hangupcause The Asterisk hangup cause code
1505 */
1506static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
1507{
1508 /* Change the disposition based on the hang up cause */
1509 switch (hangupcause) {
1510 case AST_CAUSE_BUSY:
1512 break;
1516 } else {
1518 }
1519 break;
1523 break;
1527 break;
1528 default:
1529 break;
1530 }
1531}
1532
1533/*!
1534 * \brief Finalize a CDR.
1535 *
1536 * This function is safe to call multiple times. Note that you can call this
1537 * explicitly before going to the finalized state if there's a chance the CDR
1538 * will be re-activated, in which case the \p cdr's end time should be
1539 * cleared. This function is implicitly called when a CDR transitions to the
1540 * finalized state and right before it is dispatched
1541 *
1542 * \param cdr The CDR to finalize
1543 */
1544static void cdr_object_finalize(struct cdr_object *cdr)
1545{
1546 if (!ast_tvzero(cdr->end)) {
1547 return;
1548 }
1549 cdr->end = cdr->lastevent;
1550
1551 if (cdr->disposition == AST_CDR_NULL) {
1552 if (!ast_tvzero(cdr->answer)) {
1554 } else if (cdr->party_a.snapshot->hangup->cause) {
1556 } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangup->cause) {
1558 } else {
1560 }
1561 }
1562
1563 /* tv_usec is suseconds_t, which could be int or long */
1564 ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dur %.3f bill %.3f dispo %s\n",
1565 cdr->party_a.snapshot->base->name,
1566 (long)cdr->start.tv_sec,
1567 (long)cdr->start.tv_usec,
1568 (long)cdr->answer.tv_sec,
1569 (long)cdr->answer.tv_usec,
1570 (long)cdr->end.tv_sec,
1571 (long)cdr->end.tv_usec,
1572 (double)ast_tvdiff_ms(cdr->end, cdr->start) / 1000.0,
1573 (double)ast_tvdiff_ms(cdr->end, cdr->answer) / 1000.0,
1575}
1576
1577/*!
1578 * \brief Check to see if a CDR needs to move to the finalized state because
1579 * its Party A hungup.
1580 */
1582{
1586 }
1587
1589 && cdr->fn_table != &finalized_state_fn_table) {
1591 }
1592}
1593
1594/*!
1595 * \brief Check to see if a CDR needs to be answered based on its Party A.
1596 * Note that this is safe to call as much as you want - we won't answer twice
1597 */
1599{
1600 if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
1601 cdr->answer = cdr->lastevent;
1602 /* tv_usec is suseconds_t, which could be int or long */
1603 CDR_DEBUG("%p - Set answered time to %ld.%06ld\n", cdr,
1604 (long)cdr->answer.tv_sec,
1605 (long)cdr->answer.tv_usec);
1606 }
1607}
1608
1609/*! \brief Set Caller ID information on a CDR */
1610static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
1611{
1612 if (!old_snapshot->snapshot) {
1613 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
1614 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
1615 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
1616 return;
1617 }
1618 if (strcmp(old_snapshot->snapshot->caller->dnid, new_snapshot->caller->dnid)) {
1619 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
1620 }
1621 if (strcmp(old_snapshot->snapshot->caller->subaddr, new_snapshot->caller->subaddr)) {
1622 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
1623 }
1624 if (strcmp(old_snapshot->snapshot->caller->dialed_subaddr, new_snapshot->caller->dialed_subaddr)) {
1625 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
1626 }
1627}
1628
1629/*!
1630 * \brief Swap an old \ref cdr_object_snapshot's \ref ast_channel_snapshot for
1631 * a new \ref ast_channel_snapshot
1632 * \param old_snapshot The old \ref cdr_object_snapshot
1633 * \param new_snapshot The new \ref ast_channel_snapshot for old_snapshot
1634 */
1635static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot,
1636 struct ast_channel_snapshot *new_snapshot)
1637{
1638 cdr_object_update_cid(old_snapshot, new_snapshot);
1639 ao2_t_replace(old_snapshot->snapshot, new_snapshot, "Swap CDR snapshot");
1640}
1641
1642/* BASE METHOD IMPLEMENTATIONS */
1643
1644static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1645{
1646 ast_assert(strcasecmp(snapshot->base->name, cdr->party_a.snapshot->base->name) == 0);
1647
1648 /* Finalize the CDR if we're in hangup logic and we're set to do so */
1652 return 0;
1653 }
1654
1655 /*
1656 * Only record the context and extension if we aren't in a subroutine, or if
1657 * we are executing hangup logic.
1658 */
1661 if (strcmp(cdr->context, snapshot->dialplan->context)) {
1662 ast_string_field_set(cdr, context, snapshot->dialplan->context);
1663 }
1664 if (strcmp(cdr->exten, snapshot->dialplan->exten)) {
1665 ast_string_field_set(cdr, exten, snapshot->dialplan->exten);
1666 }
1667 }
1668
1669 cdr_object_swap_snapshot(&cdr->party_a, snapshot);
1670
1671 /* When Party A is originated to an application and the application exits, the stack
1672 * will attempt to clear the application and restore the dummy originate application
1673 * of "AppDialX". Prevent that, and any other application changes we might not want
1674 * here.
1675 */
1677 && !ast_strlen_zero(snapshot->dialplan->appl)
1678 && (strncasecmp(snapshot->dialplan->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))) {
1679 if (strcmp(cdr->appl, snapshot->dialplan->appl)) {
1680 ast_string_field_set(cdr, appl, snapshot->dialplan->appl);
1681 }
1682 if (strcmp(cdr->data, snapshot->dialplan->data)) {
1683 ast_string_field_set(cdr, data, snapshot->dialplan->data);
1684 }
1685
1686 /* Dial (app_dial) is a special case. Because pre-dial handlers, which
1687 * execute before the dial begins, will alter the application/data to
1688 * something people typically don't want to see, if we see a channel enter
1689 * into Dial here, we set the appl/data accordingly and lock it.
1690 */
1691 if (!strcmp(snapshot->dialplan->appl, "Dial")) {
1693 }
1694 }
1695
1696 if (strcmp(cdr->linkedid, snapshot->peer->linkedid)) {
1697 ast_string_field_set(cdr, linkedid, snapshot->peer->linkedid);
1698 }
1701
1702 return 0;
1703}
1704
1706{
1707 return 0;
1708}
1709
1710static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1711{
1712 return 0;
1713}
1714
1716{
1717 /* Base process bridge enter simply indicates that we can't handle it */
1718 return BRIDGE_ENTER_NEED_CDR;
1719}
1720
1721static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
1722{
1723 char park_info[128];
1724
1725 ast_assert(!strcasecmp(parking_info->parkee->base->name, cdr->party_a.snapshot->base->name));
1726
1727 /* Update Party A information regardless */
1728 cdr->fn_table->process_party_a(cdr, parking_info->parkee);
1729
1730 /* Fake out where we're parked */
1731 ast_string_field_set(cdr, appl, "Park");
1732 snprintf(park_info, sizeof(park_info), "%s:%u", parking_info->parkinglot, parking_info->parkingspace);
1733 ast_string_field_set(cdr, data, park_info);
1734
1735 /* Prevent any further changes to the App/Data fields for this record */
1737
1738 return 0;
1739}
1740
1741/* SINGLE STATE */
1742
1744{
1745 cdr->start = cdr->lastevent;
1747}
1748
1749static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1750{
1751 /* This should never happen! */
1753 ast_assert(0);
1754 return;
1755}
1756
1758{
1759 if (caller && !strcasecmp(cdr->party_a.snapshot->base->name, caller->base->name)) {
1760 base_process_party_a(cdr, caller);
1761 CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
1762 cdr->party_a.snapshot->base->name);
1763 cdr_object_swap_snapshot(&cdr->party_b, peer);
1764 cdr_all_relink(cdr);
1765 CDR_DEBUG("%p - Updated Party B %s snapshot\n", cdr,
1766 cdr->party_b.snapshot->base->name);
1767
1768 /* If we have two parties, lock the application that caused the
1769 * two parties to be associated. This prevents mid-call event
1770 * gosubs from perturbing the CDR application/data
1771 */
1773 } else if (!strcasecmp(cdr->party_a.snapshot->base->name, peer->base->name)) {
1774 /* We're the entity being dialed, i.e., outbound origination */
1775 base_process_party_a(cdr, peer);
1776 CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
1777 cdr->party_a.snapshot->base->name);
1778 }
1779
1781 return 0;
1782}
1783
1784/*!
1785 * \brief Handle a comparison between our \ref cdr_object and a \ref cdr_object
1786 * already in the bridge while in the Single state. The goal of this is to find
1787 * a Party B for our CDR.
1788 *
1789 * \param cdr Our \ref cdr_object in the Single state
1790 * \param cand_cdr The \ref cdr_object already in the Bridge state
1791 *
1792 * \retval 0 The cand_cdr had a Party A or Party B that we could use as our
1793 * Party B
1794 * \retval 1 No party in the cand_cdr could be used as our Party B
1795 */
1797 struct cdr_object *cand_cdr)
1798{
1799 struct cdr_object_snapshot *party_a;
1800
1801 /* Don't match on ourselves */
1802 if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
1803 return 1;
1804 }
1805
1806 /* Try the candidate CDR's Party A first */
1807 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
1808 if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1809 CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1810 cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name);
1811 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1812 cdr_all_relink(cdr);
1813 if (!cand_cdr->party_b.snapshot) {
1814 /* We just stole them - finalize their CDR. Note that this won't
1815 * transition their state, it just sets the end time and the
1816 * disposition - if we need to re-activate them later, we can.
1817 */
1818 cdr_object_finalize(cand_cdr);
1819 }
1820 return 0;
1821 }
1822
1823 /* Try their Party B, unless it's us */
1824 if (!cand_cdr->party_b.snapshot
1825 || !strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name)) {
1826 return 1;
1827 }
1828 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
1829 if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1830 CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1831 cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name);
1832 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
1833 cdr_all_relink(cdr);
1834 return 0;
1835 }
1836
1837 return 1;
1838}
1839
1841{
1842 struct ao2_iterator it_cdrs;
1843 char *channel_id;
1844 int success = 0;
1845
1846 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1847
1848 if (ao2_container_count(bridge->channels) == 1) {
1849 /* No one in the bridge yet but us! */
1852 }
1853
1854 for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
1855 !success && (channel_id = ao2_iterator_next(&it_cdrs));
1856 ao2_ref(channel_id, -1)) {
1857 struct cdr_object *cand_cdr_master;
1858 struct cdr_object *cand_cdr;
1859
1860 cand_cdr_master = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
1861 if (!cand_cdr_master) {
1862 continue;
1863 }
1864
1865 ao2_lock(cand_cdr_master);
1866 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1867 /* Skip any records that are not in a bridge or in this bridge.
1868 * I'm not sure how that would happen, but it pays to be careful. */
1869 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1870 strcmp(cdr->bridge, cand_cdr->bridge)) {
1871 continue;
1872 }
1873
1874 if (single_state_bridge_enter_comparison(cdr, cand_cdr)) {
1875 continue;
1876 }
1877 /* We successfully got a party B - break out */
1878 success = 1;
1879 break;
1880 }
1881 ao2_unlock(cand_cdr_master);
1882 ao2_cleanup(cand_cdr_master);
1883 }
1884 ao2_iterator_destroy(&it_cdrs);
1885
1886 /* We always transition state, even if we didn't get a peer */
1888
1889 /* Success implies that we have a Party B */
1890 if (success) {
1892 }
1893
1895}
1896
1898{
1900 return 0;
1901}
1902
1903
1904/* DIAL STATE */
1905
1906static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1907{
1908 ast_assert(snapshot != NULL);
1910 && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
1911
1912 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1913
1914 /* If party B hangs up, finalize this CDR */
1917 }
1918}
1919
1920static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1921{
1922 /* Don't process a begin dial here. A party A already in the dial state will
1923 * who receives a dial begin for something else will be handled by the
1924 * message router callback and will add a new CDR for the party A */
1925 return 1;
1926}
1927
1928/*!
1929 * \internal
1930 * \brief Convert a dial status to a CDR disposition
1931 */
1932static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
1933{
1934 if (!strcmp(dial_status, "ANSWER")) {
1935 return AST_CDR_ANSWERED;
1936 } else if (!strcmp(dial_status, "BUSY")) {
1937 return AST_CDR_BUSY;
1938 } else if (!strcmp(dial_status, "CANCEL")) {
1940 return AST_CDR_NOANSWER;
1941 } else {
1942 return AST_CDR_CANCEL;
1943 }
1944 } else if (!strcmp(dial_status, "NOANSWER")) {
1945 return AST_CDR_NOANSWER;
1946 } else if (!strcmp(dial_status, "CONGESTION")) {
1948 return AST_CDR_FAILED;
1949 } else {
1950 return AST_CDR_CONGESTION;
1951 }
1952 } else if (!strcmp(dial_status, "FAILED")) {
1953 return AST_CDR_FAILED;
1954 }
1955 return AST_CDR_FAILED;
1956}
1957
1958static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1959{
1960 struct ast_channel_snapshot *party_a;
1961
1962 if (caller) {
1963 party_a = caller;
1964 } else {
1965 party_a = peer;
1966 }
1967 ast_assert(!strcasecmp(cdr->party_a.snapshot->base->name, party_a->base->name));
1968 cdr_object_swap_snapshot(&cdr->party_a, party_a);
1969
1970 if (cdr->party_b.snapshot) {
1971 if (strcasecmp(cdr->party_b.snapshot->base->name, peer->base->name)) {
1972 /* Not the status for this CDR - defer back to the message router */
1973 return 1;
1974 }
1976 }
1977
1978 /* Set the disposition based on the dial string. */
1979 cdr->disposition = dial_status_to_disposition(dial_status);
1980 if (cdr->disposition == AST_CDR_ANSWERED) {
1981 /* Switch to dial pending to wait and see what the caller does */
1983 } else {
1985 }
1986
1987 return 0;
1988}
1989
1991{
1992 int success = 0;
1993
1994 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1995
1996 /* Get parties in the bridge */
1997 if (ao2_container_count(bridge->channels) == 1) {
1998 /* No one in the bridge yet but us! */
2001 }
2002
2003 /* If we don't have a Party B (originated channel), skip it */
2004 if (cdr->party_b.snapshot) {
2005 struct ao2_iterator it_cdrs;
2006 char *channel_id;
2007
2008 for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
2009 !success && (channel_id = ao2_iterator_next(&it_cdrs));
2010 ao2_ref(channel_id, -1)) {
2011 struct cdr_object *cand_cdr_master;
2012 struct cdr_object *cand_cdr;
2013
2014 cand_cdr_master = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
2015 if (!cand_cdr_master) {
2016 continue;
2017 }
2018
2019 ao2_lock(cand_cdr_master);
2020 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
2021 /* Skip any records that are not in a bridge or in this bridge.
2022 * I'm not sure how that would happen, but it pays to be careful. */
2023 if (cand_cdr->fn_table != &bridge_state_fn_table
2024 || strcmp(cdr->bridge, cand_cdr->bridge)) {
2025 continue;
2026 }
2027
2028 /* Skip any records that aren't our Party B */
2029 if (strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
2030 continue;
2031 }
2032 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
2033 /* If they have a Party B, they joined up with someone else as their
2034 * Party A. Don't finalize them as they're active. Otherwise, we
2035 * have stolen them so they need to be finalized.
2036 */
2037 if (!cand_cdr->party_b.snapshot) {
2038 cdr_object_finalize(cand_cdr);
2039 }
2040 success = 1;
2041 break;
2042 }
2043 ao2_unlock(cand_cdr_master);
2044 ao2_cleanup(cand_cdr_master);
2045 }
2046 ao2_iterator_destroy(&it_cdrs);
2047 }
2048
2049 /* We always transition state, even if we didn't get a peer */
2051
2052 /* Success implies that we have a Party B */
2053 if (success) {
2055 }
2057}
2058
2059/* DIALED PENDING STATE */
2060
2062{
2063 /* If we get a CEP change, we're executing dialplan. If we have a Party B
2064 * that means we need a new CDR; otherwise, switch us over to single.
2065 */
2066 if (snapshot_cep_changed(cdr->party_a.snapshot, snapshot)) {
2067 if (cdr->party_b.snapshot) {
2069 cdr->fn_table->process_party_a(cdr, snapshot);
2070 return 1;
2071 } else {
2072 /* The CDR does not need to be reinitialized when transitioning
2073 * to its single state as this would overwrite the start time,
2074 * causing potentially both the answer and the start time to be
2075 * the same which is incorrect.
2076 */
2078 cdr->fn_table->process_party_a(cdr, snapshot);
2079 return 0;
2080 }
2081 }
2082 base_process_party_a(cdr, snapshot);
2083 return 0;
2084}
2085
2087{
2089 return cdr->fn_table->process_bridge_enter(cdr, bridge, channel);
2090}
2091
2093{
2094 if (cdr->party_b.snapshot) {
2095 /* We can't handle this as we have a Party B - ask for a new one */
2096 return 1;
2097 }
2099 return 0;
2100}
2101
2103{
2105
2106 /* Ask for a new CDR */
2107 return 1;
2108}
2109
2110/* BRIDGE STATE */
2111
2112static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
2113{
2115 && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
2116
2117 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
2118
2119 /* If party B hangs up, finalize this CDR */
2122 }
2123}
2124
2126{
2127 if (strcmp(cdr->bridge, bridge->uniqueid)) {
2128 return 1;
2129 }
2130 if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)
2131 && cdr->party_b.snapshot
2132 && strcasecmp(cdr->party_b.snapshot->base->name, channel->base->name)) {
2133 return 1;
2134 }
2136
2137 return 0;
2138}
2139
2140/* PARKED STATE */
2141
2143{
2144 if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)) {
2145 return 1;
2146 }
2148
2149 return 0;
2150}
2151
2152/* FINALIZED STATE */
2153
2155{
2157}
2158
2159static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
2160{
2163 return 0;
2164 }
2165
2166 /* Indicate that, if possible, we should get a new CDR */
2167 return 1;
2168}
2169
2170/*!
2171 * \internal
2172 * \brief Filter channel snapshots by technology
2173 */
2175{
2176 return snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL;
2177}
2178
2179/*!
2180 * \internal
2181 * \brief Filter a channel snapshot update
2182 */
2184 struct ast_channel_snapshot *new_snapshot)
2185{
2186 int ret = 0;
2187
2188 /* Drop cache updates from certain channel technologies */
2189 if (old_snapshot) {
2190 ret |= filter_channel_snapshot(old_snapshot);
2191 }
2192 if (new_snapshot) {
2193 ret |= filter_channel_snapshot(new_snapshot);
2194 }
2195
2196 return ret;
2197}
2198
2199static int dial_status_end(const char *dialstatus)
2200{
2201 return (strcmp(dialstatus, "RINGING") &&
2202 strcmp(dialstatus, "PROCEEDING") &&
2203 strcmp(dialstatus, "PROGRESS"));
2204}
2205
2206/* TOPIC ROUTER CALLBACKS */
2207
2208/*!
2209 * \brief Handler for Stasis-Core dial messages
2210 * \param data Passed on
2211 * \param sub The stasis subscription for this message callback
2212 * \param message The message
2213 */
2215{
2216 struct cdr_object *cdr;
2219 struct ast_channel_snapshot *peer;
2220 struct cdr_object *it_cdr;
2221 struct ast_json *dial_status_blob;
2222 const char *dial_status = NULL;
2223 int res = 1;
2224
2225 caller = ast_multi_channel_blob_get_channel(payload, "caller");
2226 peer = ast_multi_channel_blob_get_channel(payload, "peer");
2227 if (!peer && !caller) {
2228 return;
2229 }
2230
2231 if (peer && filter_channel_snapshot(peer)) {
2232 return;
2233 }
2234
2235 if (caller && filter_channel_snapshot(caller)) {
2236 return;
2237 }
2238
2239 dial_status_blob = ast_json_object_get(ast_multi_channel_blob_get_json(payload), "dialstatus");
2240 if (dial_status_blob) {
2241 dial_status = ast_json_string_get(dial_status_blob);
2242 }
2243
2244 CDR_DEBUG("Dial %s message for %s, %s: %u.%08u\n",
2245 ast_strlen_zero(dial_status) ? "Begin" : "End",
2246 caller ? caller->base->name : "(none)",
2247 peer ? peer->base->name : "(none)",
2248 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2249 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2250
2251 /* Figure out who is running this show */
2252 if (caller) {
2254 } else {
2256 }
2257 if (!cdr) {
2258 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->base->name : peer->base->name);
2259 ast_assert(0);
2260 return;
2261 }
2262
2263 ao2_lock(cdr);
2264 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2266 if (ast_strlen_zero(dial_status)) {
2267 if (!it_cdr->fn_table->process_dial_begin) {
2268 continue;
2269 }
2271 CDR_DEBUG("%p - Ignoring Dial Begin message\n", it_cdr);
2272 continue;
2273 }
2274 CDR_DEBUG("%p - Processing Dial Begin message for channel %s, peer %s\n",
2275 it_cdr,
2276 caller ? caller->base->name : "(none)",
2277 peer ? peer->base->name : "(none)");
2278 res &= it_cdr->fn_table->process_dial_begin(it_cdr,
2279 caller,
2280 peer);
2281 } else if (dial_status_end(dial_status)) {
2282 if (!it_cdr->fn_table->process_dial_end) {
2283 continue;
2284 }
2286 /* Set the disposition, and do nothing else. */
2287 it_cdr->disposition = dial_status_to_disposition(dial_status);
2288 CDR_DEBUG("%p - Setting disposition and that's it (%s)\n", it_cdr, dial_status);
2289 continue;
2290 }
2291 CDR_DEBUG("%p - Processing Dial End message for channel %s, peer %s\n",
2292 it_cdr,
2293 caller ? caller->base->name : "(none)",
2294 peer ? peer->base->name : "(none)");
2295 it_cdr->fn_table->process_dial_end(it_cdr,
2296 caller,
2297 peer,
2298 dial_status);
2299 }
2300 }
2301
2302 /* If we're ignoring dial changes, don't allow multiple CDRs for this channel. */
2303 if (!dial_changes_ignored) {
2304 /* If no CDR handled a dial begin message, make a new one */
2305 if (res && ast_strlen_zero(dial_status)) {
2306 struct cdr_object *new_cdr;
2307
2309 if (new_cdr) {
2310 new_cdr->fn_table->process_dial_begin(new_cdr, caller, peer);
2311 }
2312 }
2313 }
2314
2315 ao2_unlock(cdr);
2316 ao2_cleanup(cdr);
2317}
2318
2319static int cdr_object_finalize_party_b(void *obj, void *arg, void *data, int flags)
2320{
2321 struct cdr_object *cdr = obj;
2322
2323 if (!strcasecmp(cdr->party_b_name, arg)) {
2324#ifdef AST_DEVMODE
2325 struct ast_channel_snapshot *party_b = data;
2326
2327 /*
2328 * For sanity's sake we also assert the party_b snapshot
2329 * is consistent with the key.
2330 */
2332 && !strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name));
2333#endif
2334
2335 /* Don't transition to the finalized state - let the Party A do
2336 * that when its ready
2337 */
2339 }
2340 return 0;
2341}
2342
2343static int cdr_object_update_party_b(void *obj, void *arg, void *data, int flags)
2344{
2345 struct cdr_object *cdr = obj;
2346
2347 if (cdr->fn_table->process_party_b
2348 && !strcasecmp(cdr->party_b_name, arg)) {
2349 struct ast_channel_snapshot *party_b = data;
2350
2351 /*
2352 * For sanity's sake we also check the party_b snapshot
2353 * for consistency with the key. The callback needs and
2354 * asserts the snapshot to be this way.
2355 */
2356 if (!cdr->party_b.snapshot
2357 || strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name)) {
2359 "CDR for Party A %s(%s) has inconsistent Party B %s name. Message can be ignored but this shouldn't happen.\n",
2360 cdr->linkedid,
2361 cdr->party_a.snapshot->base->name,
2362 cdr->party_b_name);
2363 return 0;
2364 }
2365
2366 cdr->fn_table->process_party_b(cdr, party_b);
2367 }
2368 return 0;
2369}
2370
2371/*! \brief Determine if we need to add a new CDR based on snapshots */
2372static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot,
2373 struct ast_channel_snapshot *new_snapshot)
2374{
2375 /* If we're dead, we don't need a new CDR */
2376 if (!new_snapshot
2379 return 0;
2380 }
2381
2382 /* Auto-fall through will increment the priority but have no application */
2383 if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
2384 return 0;
2385 }
2386
2387 if (old_snapshot && !snapshot_cep_changed(old_snapshot, new_snapshot)) {
2388 return 0;
2389 }
2390
2391 return 1;
2392}
2393
2394/*!
2395 * \brief Handler for channel snapshot update messages
2396 * \param data Passed on
2397 * \param sub The stasis subscription for this message callback
2398 * \param message The message
2399 */
2401{
2402 struct cdr_object *cdr;
2404 struct cdr_object *it_cdr;
2405
2406 if (filter_channel_snapshot_message(update->old_snapshot, update->new_snapshot)) {
2407 return;
2408 }
2409
2410 if (update->new_snapshot && !update->old_snapshot) {
2411 struct module_config *mod_cfg = NULL;
2412
2414 if (!cdr) {
2415 return;
2416 }
2417 mod_cfg = ao2_global_obj_ref(module_configs);
2418 cdr->is_root = 1;
2420
2421 /* If CDR should be disabled unless enabled on a per-channel basis, then disable
2422 CDR, right from the get go */
2423 if (mod_cfg) {
2425 ast_debug(3, "Disable CDR by default\n");
2427 }
2428 ao2_cleanup(mod_cfg);
2429 }
2430 } else {
2431 cdr = ao2_find(active_cdrs_master, update->new_snapshot->base->uniqueid, OBJ_SEARCH_KEY);
2432 }
2433
2434 /* Handle Party A */
2435 if (!cdr) {
2436 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->base->name);
2437 ast_assert(0);
2438 } else {
2439 int all_reject = 1;
2440
2441 ao2_lock(cdr);
2442 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2444 if (!it_cdr->fn_table->process_party_a) {
2445 continue;
2446 }
2447 all_reject &= it_cdr->fn_table->process_party_a(it_cdr, update->new_snapshot);
2448 }
2449 if (all_reject && check_new_cdr_needed(update->old_snapshot, update->new_snapshot)) {
2450 /* We're not hung up and we have a new snapshot - we need a new CDR */
2451 struct cdr_object *new_cdr;
2452
2454 if (new_cdr) {
2455 new_cdr->fn_table->process_party_a(new_cdr, update->new_snapshot);
2456 }
2457 }
2458 ao2_unlock(cdr);
2459 }
2460
2461 if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2462 ao2_lock(cdr);
2463 CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->base->name);
2464 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2466 cdr_object_finalize(it_cdr);
2467 }
2469 ao2_unlock(cdr);
2470
2471 cdr_all_unlink(cdr);
2473 }
2474
2475 /* Handle Party B */
2476 if (update->new_snapshot) {
2478 cdr_object_update_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2479 }
2480
2481 if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2483 cdr_object_finalize_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2484 }
2485
2486 ao2_cleanup(cdr);
2487}
2488
2492 const struct timeval *lastevent;
2493};
2494
2495/*! \brief Callback used to notify CDRs of a Party B leaving the bridge */
2496static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, void *data, int flags)
2497{
2498 struct cdr_object *cdr = obj;
2499 struct bridge_leave_data *leave_data = data;
2500
2501 if (cdr->fn_table == &bridge_state_fn_table
2502 && !strcmp(cdr->bridge, leave_data->bridge->uniqueid)
2503 && !strcasecmp(cdr->party_b_name, arg)) {
2504 /*
2505 * For sanity's sake we also assert the party_b snapshot
2506 * is consistent with the key.
2507 */
2509 && !strcasecmp(cdr->party_b.snapshot->base->name, leave_data->channel->base->name));
2510
2511 /* It is our Party B, in our bridge. Set the last event and let the handler
2512 * transition our CDR appropriately when we leave the bridge.
2513 */
2514 cdr->lastevent = *leave_data->lastevent;
2516 }
2517 return 0;
2518}
2519
2520/*! \brief Filter bridge messages based on bridge technology */
2522{
2523 /* Ignore holding bridge technology messages. We treat this simply as an application
2524 * that a channel enters into.
2525 */
2526 if (!strcmp(bridge->technology, "holding_bridge") && strcmp(bridge->subclass, "parking")) {
2527 return 1;
2528 }
2529 return 0;
2530}
2531
2532/*!
2533 * \brief Handler for when a channel leaves a bridge
2534 * \param data Passed on
2535 * \param sub The stasis subscription for this message callback
2536 * \param message The message - hopefully a bridge one!
2537 */
2539 struct stasis_message *message)
2540{
2542 struct ast_bridge_snapshot *bridge = update->bridge;
2543 struct ast_channel_snapshot *channel = update->channel;
2544 struct cdr_object *cdr;
2545 struct cdr_object *it_cdr;
2546 struct bridge_leave_data leave_data = {
2547 .bridge = bridge,
2548 .channel = channel,
2549 .lastevent = stasis_message_timestamp(message)
2550 };
2551 int left_bridge = 0;
2552
2554 return;
2555 }
2556
2558 return;
2559 }
2560
2561 CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n",
2562 channel->base->name,
2563 (unsigned int)leave_data.lastevent->tv_sec,
2564 (unsigned int)leave_data.lastevent->tv_usec);
2565
2567 if (!cdr) {
2568 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2569 ast_assert(0);
2570 return;
2571 }
2572
2573 /* Party A */
2574 ao2_lock(cdr);
2575 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2576 it_cdr->lastevent = *leave_data.lastevent;
2577 if (!it_cdr->fn_table->process_bridge_leave) {
2578 continue;
2579 }
2580 CDR_DEBUG("%p - Processing Bridge Leave for %s\n",
2581 it_cdr, channel->base->name);
2582 if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
2583 ast_string_field_set(it_cdr, bridge, "");
2584 left_bridge = 1;
2585 }
2586 }
2587 ao2_unlock(cdr);
2588
2589 /* Party B */
2590 if (left_bridge
2591 && strcmp(bridge->subclass, "parking")) {
2593 cdr_object_party_b_left_bridge_cb, (char *) leave_data.channel->base->name,
2594 &leave_data);
2595 }
2596
2597 ao2_cleanup(cdr);
2598}
2599
2600/*!
2601 * \internal
2602 * \brief Create a new CDR, append it to an existing CDR, and update its snapshots
2603 *
2604 * \note The new CDR will be automatically transitioned to the bridge state
2605 */
2607 struct cdr_object_snapshot *party_b)
2608{
2609 struct cdr_object *new_cdr;
2610
2611 new_cdr = cdr_object_create_and_append(cdr, &cdr->lastevent);
2612 if (!new_cdr) {
2613 return;
2614 }
2616 cdr_all_relink(new_cdr);
2618 ast_string_field_set(new_cdr, bridge, cdr->bridge);
2620 CDR_DEBUG("%p - Party A %s has new Party B %s\n",
2621 new_cdr, new_cdr->party_a.snapshot->base->name,
2623}
2624
2625/*!
2626 * \brief Process a single \c bridge_candidate
2627 *
2628 * When a CDR enters a bridge, it needs to make pairings with everyone else
2629 * that it is not currently paired with. This function determines, for the
2630 * CDR for the channel that entered the bridge and the CDR for every other
2631 * channel currently in the bridge, who is Party A and makes new CDRs.
2632 *
2633 * \param cdr The \ref cdr_object being processed
2634 * \param base_cand_cdr The \ref cdr_object that is a candidate
2635 *
2636 */
2637static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
2638{
2639 struct cdr_object_snapshot *party_a;
2640 struct cdr_object *cand_cdr;
2641
2642 ao2_lock(base_cand_cdr);
2643
2644 for (cand_cdr = base_cand_cdr; cand_cdr; cand_cdr = cand_cdr->next) {
2645 /* Skip any records that are not in this bridge */
2646 if (strcmp(cand_cdr->bridge, cdr->bridge)) {
2647 continue;
2648 }
2649
2650 /* If the candidate is us or someone we've taken on, pass on by */
2651 if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)
2652 || (cdr->party_b.snapshot
2653 && !strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name))) {
2654 break;
2655 }
2656
2657 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
2658 /* We're party A - make a new CDR, append it to us, and set the candidate as
2659 * Party B */
2660 if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2661 bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);
2662 break;
2663 }
2664
2665 /* We're Party B. Check if we can add ourselves immediately or if we need
2666 * a new CDR for them (they already have a Party B) */
2667 if (cand_cdr->party_b.snapshot
2668 && strcasecmp(cand_cdr->party_b.snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2669 bridge_candidate_add_to_cdr(cand_cdr, &cdr->party_a);
2670 } else {
2671 CDR_DEBUG("%p - Party A %s has new Party B %s\n",
2672 cand_cdr, cand_cdr->party_a.snapshot->base->name,
2673 cdr->party_a.snapshot->base->name);
2674 cdr_object_snapshot_copy(&cand_cdr->party_b, &cdr->party_a);
2675 cdr_all_relink(cand_cdr);
2676 /* It's possible that this joined at one point and was never chosen
2677 * as party A. Clear their end time, as it would be set in such a
2678 * case.
2679 */
2680 memset(&cand_cdr->end, 0, sizeof(cand_cdr->end));
2681 }
2682
2683 break;
2684 }
2685
2686 ao2_unlock(base_cand_cdr);
2687}
2688
2689/*!
2690 * \brief Handle creating bridge pairings for the \ref cdr_object that just
2691 * entered a bridge
2692 * \param cdr The \ref cdr_object that just entered the bridge
2693 * \param bridge The \ref ast_bridge_snapshot representing the bridge it just entered
2694 */
2696{
2697 struct ao2_iterator it_channels;
2698 char *channel_id;
2699
2700 it_channels = ao2_iterator_init(bridge->channels, 0);
2701 while ((channel_id = ao2_iterator_next(&it_channels))) {
2702 struct cdr_object *cand_cdr;
2703
2704 cand_cdr = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
2705 if (cand_cdr) {
2706 bridge_candidate_process(cdr, cand_cdr);
2707 ao2_ref(cand_cdr, -1);
2708 }
2709
2710 ao2_ref(channel_id, -1);
2711 }
2712 ao2_iterator_destroy(&it_channels);
2713}
2714
2715/*! \brief Handle entering into a parking bridge
2716 * \param cdr The CDR to operate on
2717 * \param bridge The bridge the channel just entered
2718 * \param channel The channel snapshot
2719 * \param event_time
2720 */
2723 struct ast_channel_snapshot *channel,
2724 const struct timeval *event_time)
2725{
2726 int res = 1;
2727 struct cdr_object *it_cdr;
2728 struct cdr_object *new_cdr;
2729
2730 ao2_lock(cdr);
2731
2732 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2733 it_cdr->lastevent = *event_time;
2734
2736 res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
2737 }
2738 if (it_cdr->fn_table->process_party_a) {
2739 CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2740 channel->base->name);
2741 it_cdr->fn_table->process_party_a(it_cdr, channel);
2742 }
2743 }
2744
2745 if (res) {
2746 /* No one handled it - we need a new one! */
2747 new_cdr = cdr_object_create_and_append(cdr, event_time);
2748 if (new_cdr) {
2749 /* Let the single state transition us to Parked */
2751 new_cdr->fn_table->process_parking_bridge_enter(new_cdr, bridge, channel);
2752 }
2753 }
2754 ao2_unlock(cdr);
2755}
2756
2757/*! \brief Handle a bridge enter message for a 'normal' bridge
2758 * \param cdr The CDR to operate on
2759 * \param bridge The bridge the channel just entered
2760 * \param channel The channel snapshot
2761 * \param event_time
2762 */
2765 struct ast_channel_snapshot *channel,
2766 const struct timeval *event_time)
2767{
2769 struct cdr_object *it_cdr;
2770 struct cdr_object *new_cdr;
2771 struct cdr_object *handled_cdr = NULL;
2772
2773 ao2_lock(cdr);
2774
2775try_again:
2776 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2777 it_cdr->lastevent = *event_time;
2778
2779 if (it_cdr->fn_table->process_party_a) {
2780 CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2781 channel->base->name);
2782 it_cdr->fn_table->process_party_a(it_cdr, channel);
2783 }
2784
2785 /* Notify all states that they have entered a bridge */
2786 if (it_cdr->fn_table->process_bridge_enter) {
2787 CDR_DEBUG("%p - Processing bridge enter for %s\n", it_cdr,
2788 channel->base->name);
2789 result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
2790 switch (result) {
2792 /* Fall through */
2794 if (!handled_cdr) {
2795 handled_cdr = it_cdr;
2796 }
2797 break;
2799 /* Pass */
2800 break;
2802 /* We didn't win on any - end this CDR. If someone else comes in later
2803 * that is Party B to this CDR, it can re-activate this CDR.
2804 */
2805 if (!handled_cdr) {
2806 handled_cdr = it_cdr;
2807 }
2809 break;
2810 }
2811 }
2812 }
2813
2814 /* Create the new matchings, but only for either:
2815 * * The first CDR in the chain that handled it. This avoids issues with
2816 * forked CDRs.
2817 * * If no one handled it, the last CDR in the chain. This would occur if
2818 * a CDR joined a bridge and it wasn't Party A for anyone. We still need
2819 * to make pairings with everyone in the bridge.
2820 */
2821 if (handled_cdr) {
2822 handle_bridge_pairings(handled_cdr, bridge);
2823 } else {
2824 /* Nothing handled it - we need a new one! */
2825 new_cdr = cdr_object_create_and_append(cdr, event_time);
2826 if (new_cdr) {
2827 /* This is guaranteed to succeed: the new CDR is created in the single state
2828 * and will be able to handle the bridge enter message
2829 */
2830 goto try_again;
2831 }
2832 }
2833 ao2_unlock(cdr);
2834}
2835
2836/*!
2837 * \internal
2838 * \brief Handler for Stasis-Core bridge enter messages
2839 * \param data Passed on
2840 * \param sub The stasis subscription for this message callback
2841 * \param message The message - hopefully a bridge one!
2842 */
2844 struct stasis_message *message)
2845{
2847 struct ast_bridge_snapshot *bridge = update->bridge;
2848 struct ast_channel_snapshot *channel = update->channel;
2849 struct cdr_object *cdr;
2850
2852 return;
2853 }
2854
2855 if (filter_channel_snapshot(channel)) {
2856 return;
2857 }
2858
2859 CDR_DEBUG("Bridge Enter message for channel %s: %u.%08u\n",
2860 channel->base->name,
2861 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2862 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2863
2865 if (!cdr) {
2866 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2867 ast_assert(0);
2868 return;
2869 }
2870
2871 if (!strcmp(bridge->subclass, "parking")) {
2873 } else {
2875 }
2876 ao2_cleanup(cdr);
2877}
2878
2879/*!
2880 * \brief Handler for when a channel is parked
2881 * \param data Passed on
2882 * \param sub The stasis subscription for this message callback
2883 * \param message The message about who got parked
2884 * */
2886 struct stasis_message *message)
2887{
2889 struct ast_channel_snapshot *channel = payload->parkee;
2890 struct cdr_object *cdr;
2891 int unhandled = 1;
2892 struct cdr_object *it_cdr;
2893
2894 /* Anything other than getting parked will be handled by other updates */
2895 if (payload->event_type != PARKED_CALL) {
2896 return;
2897 }
2898
2899 /* No one got parked? */
2900 if (!channel) {
2901 return;
2902 }
2903
2904 if (filter_channel_snapshot(channel)) {
2905 return;
2906 }
2907
2908 CDR_DEBUG("Parked Call message for channel %s: %u.%08u\n",
2909 channel->base->name,
2910 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2911 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2912
2914 if (!cdr) {
2915 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2916 ast_assert(0);
2917 return;
2918 }
2919
2920 ao2_lock(cdr);
2921
2922 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2924 if (it_cdr->fn_table->process_parked_channel) {
2925 unhandled &= it_cdr->fn_table->process_parked_channel(it_cdr, payload);
2926 }
2927 }
2928
2929 if (unhandled) {
2930 /* Nothing handled the message - we need a new one! */
2931 struct cdr_object *new_cdr;
2932
2934 if (new_cdr) {
2935 /* As the new CDR is created in the single state, it is guaranteed
2936 * to have a function for the parked call message and will handle
2937 * the message */
2938 new_cdr->fn_table->process_parked_channel(new_cdr, payload);
2939 }
2940 }
2941
2942 ao2_unlock(cdr);
2943
2944 ao2_cleanup(cdr);
2945}
2946
2947/*!
2948 * \brief Handler for a synchronization message
2949 * \param data Passed on
2950 * \param sub The stasis subscription for this message callback
2951 * \param message A blank ao2 object
2952 * */
2954 struct stasis_message *message)
2955{
2956 return;
2957}
2958
2960{
2961 struct ast_cdr_config *general;
2962 struct module_config *mod_cfg;
2963
2964 mod_cfg = ao2_global_obj_ref(module_configs);
2965 if (!mod_cfg) {
2966 return NULL;
2967 }
2968 general = ao2_bump(mod_cfg->general);
2969 ao2_cleanup(mod_cfg);
2970 return general;
2971}
2972
2974{
2975 struct module_config *mod_cfg;
2976
2977 if (!config) {
2978 return;
2979 }
2980
2981 mod_cfg = ao2_global_obj_ref(module_configs);
2982 if (!mod_cfg) {
2983 return;
2984 }
2985
2986 ao2_replace(mod_cfg->general, config);
2987
2988 cdr_set_debug_mode(mod_cfg);
2990
2991 ao2_cleanup(mod_cfg);
2992}
2993
2995{
2997}
2998
3000{
3001 int success = -1;
3002 struct cdr_beitem *i = NULL;
3003
3005 AST_RWLIST_TRAVERSE(&be_list, i, list) {
3006 if (!strcasecmp(name, i->name)) {
3007 ast_debug(3, "Suspending CDR backend %s\n", i->name);
3008 i->suspended = 1;
3009 success = 0;
3010 }
3011 }
3013
3014 return success;
3015}
3016
3018{
3019 int success = -1;
3020 struct cdr_beitem *i = NULL;
3021
3023 AST_RWLIST_TRAVERSE(&be_list, i, list) {
3024 if (!strcasecmp(name, i->name)) {
3025 ast_debug(3, "Unsuspending CDR backend %s\n", i->name);
3026 i->suspended = 0;
3027 success = 0;
3028 }
3029 }
3031
3032 return success;
3033}
3034
3035static int cdr_generic_register(struct be_list *generic_list, const char *name, const char *desc, ast_cdrbe be)
3036{
3037 struct cdr_beitem *i;
3038 struct cdr_beitem *cur;
3039
3040 if (!name) {
3041 return -1;
3042 }
3043
3044 if (!be) {
3045 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
3046
3047 return -1;
3048 }
3049
3050 i = ast_calloc(1, sizeof(*i));
3051 if (!i) {
3052 return -1;
3053 }
3054
3055 i->be = be;
3056 ast_copy_string(i->name, name, sizeof(i->name));
3057 ast_copy_string(i->desc, desc, sizeof(i->desc));
3058
3059 AST_RWLIST_WRLOCK(generic_list);
3060 AST_RWLIST_TRAVERSE(generic_list, cur, list) {
3061 if (!strcasecmp(name, cur->name)) {
3062 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
3063 AST_RWLIST_UNLOCK(generic_list);
3064 ast_free(i);
3065
3066 return -1;
3067 }
3068 }
3069
3070 AST_RWLIST_INSERT_HEAD(generic_list, i, list);
3071 AST_RWLIST_UNLOCK(generic_list);
3072
3073 return 0;
3074}
3075
3076int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
3077{
3079}
3080
3081int ast_cdr_modifier_register(const char *name, const char *desc, ast_cdrbe be)
3082{
3083 return cdr_generic_register((struct be_list *)&mo_list, name, desc, be);
3084}
3085
3086static int ast_cdr_generic_unregister(struct be_list *generic_list, const char *name)
3087{
3088 struct cdr_beitem *match = NULL;
3089 int active_count;
3090
3091 AST_RWLIST_WRLOCK(generic_list);
3092 AST_RWLIST_TRAVERSE(generic_list, match, list) {
3093 if (!strcasecmp(name, match->name)) {
3094 break;
3095 }
3096 }
3097
3098 if (!match) {
3099 AST_RWLIST_UNLOCK(generic_list);
3100 return 0;
3101 }
3102
3104
3105 if (!match->suspended && active_count != 0) {
3106 AST_RWLIST_UNLOCK(generic_list);
3107 ast_log(AST_LOG_WARNING, "Unable to unregister CDR backend %s; %d CDRs are still active\n",
3108 name, active_count);
3109 return -1;
3110 }
3111
3112 AST_RWLIST_REMOVE(generic_list, match, list);
3113 AST_RWLIST_UNLOCK(generic_list);
3114
3115 ast_verb(5, "Unregistered '%s' CDR backend\n", name);
3116 ast_free(match);
3117
3118 return 0;
3119}
3120
3121int ast_cdr_unregister(const char *name)
3122{
3124}
3125
3127{
3128 return ast_cdr_generic_unregister((struct be_list *)&mo_list, name);
3129}
3130
3131struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
3132{
3133 struct ast_cdr *newcdr;
3134
3135 if (!cdr) {
3136 return NULL;
3137 }
3138 newcdr = ast_cdr_alloc();
3139 if (!newcdr) {
3140 return NULL;
3141 }
3142
3143 *newcdr = *cdr;
3145 copy_variables(&newcdr->varshead, &cdr->varshead);
3146 newcdr->next = NULL;
3147
3148 return newcdr;
3149}
3150
3151static const char *cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
3152{
3153 struct ast_var_t *variables;
3154
3155 if (ast_strlen_zero(name)) {
3156 return NULL;
3157 }
3158
3159 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
3160 if (!strcasecmp(name, ast_var_name(variables))) {
3161 return ast_var_value(variables);
3162 }
3163 }
3164
3165 return NULL;
3166}
3167
3168static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
3169{
3170 if (fmt == NULL) { /* raw mode */
3171 snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec);
3172 } else {
3173 buf[0] = '\0';/* Ensure the buffer is initialized. */
3174 if (when.tv_sec) {
3175 struct ast_tm tm;
3176
3177 ast_localtime(&when, &tm, NULL);
3178 ast_strftime(buf, bufsize, fmt, &tm);
3179 }
3180 }
3181}
3182
3183void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
3184{
3185 const char *fmt = "%Y-%m-%d %T";
3186 const char *varbuf;
3187
3188 if (!cdr) {
3189 return;
3190 }
3191
3192 *ret = NULL;
3193
3194 if (!strcasecmp(name, "clid")) {
3195 ast_copy_string(workspace, cdr->clid, workspacelen);
3196 } else if (!strcasecmp(name, "src")) {
3197 ast_copy_string(workspace, cdr->src, workspacelen);
3198 } else if (!strcasecmp(name, "dst")) {
3199 ast_copy_string(workspace, cdr->dst, workspacelen);
3200 } else if (!strcasecmp(name, "dcontext")) {
3201 ast_copy_string(workspace, cdr->dcontext, workspacelen);
3202 } else if (!strcasecmp(name, "channel")) {
3203 ast_copy_string(workspace, cdr->channel, workspacelen);
3204 } else if (!strcasecmp(name, "dstchannel")) {
3205 ast_copy_string(workspace, cdr->dstchannel, workspacelen);
3206 } else if (!strcasecmp(name, "lastapp")) {
3207 ast_copy_string(workspace, cdr->lastapp, workspacelen);
3208 } else if (!strcasecmp(name, "lastdata")) {
3209 ast_copy_string(workspace, cdr->lastdata, workspacelen);
3210 } else if (!strcasecmp(name, "start")) {
3211 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
3212 } else if (!strcasecmp(name, "answer")) {
3213 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
3214 } else if (!strcasecmp(name, "end")) {
3215 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
3216 } else if (!strcasecmp(name, "duration")) {
3217 snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
3218 } else if (!strcasecmp(name, "billsec")) {
3219 snprintf(workspace, workspacelen, "%ld", (cdr->billsec || !ast_tvzero(cdr->end) || ast_tvzero(cdr->answer)) ? cdr->billsec : (long)ast_tvdiff_ms(ast_tvnow(), cdr->answer) / 1000);
3220 } else if (!strcasecmp(name, "disposition")) {
3221 if (raw) {
3222 snprintf(workspace, workspacelen, "%ld", cdr->disposition);
3223 } else {
3224 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
3225 }
3226 } else if (!strcasecmp(name, "amaflags")) {
3227 if (raw) {
3228 snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
3229 } else {
3230 ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
3231 }
3232 } else if (!strcasecmp(name, "accountcode")) {
3233 ast_copy_string(workspace, cdr->accountcode, workspacelen);
3234 } else if (!strcasecmp(name, "peeraccount")) {
3235 ast_copy_string(workspace, cdr->peeraccount, workspacelen);
3236 } else if (!strcasecmp(name, "uniqueid")) {
3237 ast_copy_string(workspace, cdr->uniqueid, workspacelen);
3238 } else if (!strcasecmp(name, "linkedid")) {
3239 ast_copy_string(workspace, cdr->linkedid, workspacelen);
3240 } else if (!strcasecmp(name, "tenantid")) {
3241 ast_copy_string(workspace, cdr->tenantid, workspacelen);
3242 } else if (!strcasecmp(name, "peertenantid")) {
3243 ast_copy_string(workspace, cdr->peertenantid, workspacelen);
3244 } else if (!strcasecmp(name, "userfield")) {
3245 ast_copy_string(workspace, cdr->userfield, workspacelen);
3246 } else if (!strcasecmp(name, "sequence")) {
3247 snprintf(workspace, workspacelen, "%d", cdr->sequence);
3248 } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
3249 ast_copy_string(workspace, varbuf, workspacelen);
3250 } else {
3251 workspace[0] = '\0';
3252 }
3253
3254 if (!ast_strlen_zero(workspace)) {
3255 *ret = workspace;
3256 }
3257}
3258
3259/*!
3260 * \internal
3261 * \brief Callback that finds all CDRs that reference a particular channel by name
3262 */
3263static int cdr_object_select_all_by_name_cb(void *obj, void *arg, int flags)
3264{
3265 struct cdr_object *cdr = obj;
3266 const char *name = arg;
3267
3268 if (!strcasecmp(cdr->party_a.snapshot->base->name, name) ||
3269 (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->base->name, name))) {
3270 return CMP_MATCH;
3271 }
3272 return 0;
3273}
3274
3275/*!
3276 * \internal
3277 * \brief Callback that finds a CDR by channel name
3278 */
3279static int cdr_object_get_by_name_cb(void *obj, void *arg, int flags)
3280{
3281 struct cdr_object *cdr = obj;
3282 const char *name = arg;
3283
3284 if (!strcasecmp(cdr->party_a.snapshot->base->name, name)) {
3285 return CMP_MATCH;
3286 }
3287 return 0;
3288}
3289
3290/* Read Only CDR variables */
3291static const char * const cdr_readonly_vars[] = {
3292 "clid",
3293 "src",
3294 "dst",
3295 "dcontext",
3296 "channel",
3297 "dstchannel",
3298 "lastapp",
3299 "lastdata",
3300 "start",
3301 "answer",
3302 "end",
3303 "duration",
3304 "billsec",
3305 "disposition",
3306 "amaflags",
3307 "accountcode",
3308 "uniqueid",
3309 "linkedid",
3310 "tenantid",
3311 "userfield",
3312 "sequence",
3313 NULL
3314};
3315
3316int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
3317{
3318 struct cdr_object *cdr;
3319 struct cdr_object *it_cdr;
3320 struct ao2_iterator *it_cdrs;
3321 char *arg = ast_strdupa(channel_name);
3322 int x;
3323
3324 for (x = 0; cdr_readonly_vars[x]; x++) {
3325 if (!strcasecmp(name, cdr_readonly_vars[x])) {
3326 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
3327 return -1;
3328 }
3329 }
3330
3332 if (!it_cdrs) {
3333 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3334 return -1;
3335 }
3336
3337 for (; (cdr = ao2_iterator_next(it_cdrs)); ao2_unlock(cdr), ao2_cleanup(cdr)) {
3338 ao2_lock(cdr);
3339 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3340 struct varshead *headp = NULL;
3341
3342 if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3343 continue;
3344 }
3345 if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->base->name)) {
3346 headp = &it_cdr->party_a.variables;
3347 } else if (it_cdr->party_b.snapshot
3348 && !strcasecmp(channel_name, it_cdr->party_b.snapshot->base->name)) {
3349 headp = &it_cdr->party_b.variables;
3350 }
3351 if (headp) {
3352 set_variable(headp, name, value);
3353 }
3354 }
3355 }
3356 ao2_iterator_destroy(it_cdrs);
3357
3358 return 0;
3359}
3360
3361/*!
3362 * \brief Format a variable on a \ref cdr_object
3363 */
3364static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
3365{
3366 struct ast_var_t *variable;
3367
3368 AST_LIST_TRAVERSE(&cdr->party_a.variables, variable, entries) {
3369 if (!strcasecmp(name, ast_var_name(variable))) {
3370 ast_copy_string(value, ast_var_value(variable), length);
3371 return;
3372 }
3373 }
3374
3375 *value = '\0';
3376}
3377
3378/*!
3379 * \brief Format one of the standard properties on a \ref cdr_object
3380 */
3381static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
3382{
3383 struct ast_channel_snapshot *party_a = cdr_obj->party_a.snapshot;
3384 struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;
3385
3386 if (!strcasecmp(name, "clid")) {
3387 ast_callerid_merge(value, length, party_a->caller->name, party_a->caller->number, "");
3388 } else if (!strcasecmp(name, "src")) {
3389 ast_copy_string(value, party_a->caller->number, length);
3390 } else if (!strcasecmp(name, "dst")) {
3391 ast_copy_string(value, party_a->dialplan->exten, length);
3392 } else if (!strcasecmp(name, "dcontext")) {
3393 ast_copy_string(value, party_a->dialplan->context, length);
3394 } else if (!strcasecmp(name, "channel")) {
3395 ast_copy_string(value, party_a->base->name, length);
3396 } else if (!strcasecmp(name, "dstchannel")) {
3397 if (party_b) {
3398 ast_copy_string(value, party_b->base->name, length);
3399 } else {
3400 ast_copy_string(value, "", length);
3401 }
3402 } else if (!strcasecmp(name, "lastapp")) {
3403 ast_copy_string(value, party_a->dialplan->appl, length);
3404 } else if (!strcasecmp(name, "lastdata")) {
3405 ast_copy_string(value, party_a->dialplan->data, length);
3406 } else if (!strcasecmp(name, "start")) {
3407 cdr_get_tv(cdr_obj->start, NULL, value, length);
3408 } else if (!strcasecmp(name, "answer")) {
3409 cdr_get_tv(cdr_obj->answer, NULL, value, length);
3410 } else if (!strcasecmp(name, "end")) {
3411 cdr_get_tv(cdr_obj->end, NULL, value, length);
3412 } else if (!strcasecmp(name, "duration")) {
3413 snprintf(value, length, "%ld", cdr_object_get_duration(cdr_obj));
3414 } else if (!strcasecmp(name, "billsec")) {
3415 snprintf(value, length, "%ld", cdr_object_get_billsec(cdr_obj));
3416 } else if (!strcasecmp(name, "disposition")) {
3417 snprintf(value, length, "%u", cdr_obj->disposition);
3418 } else if (!strcasecmp(name, "amaflags")) {
3419 snprintf(value, length, "%d", party_a->amaflags);
3420 } else if (!strcasecmp(name, "accountcode")) {
3421 ast_copy_string(value, party_a->base->accountcode, length);
3422 } else if (!strcasecmp(name, "peeraccount")) {
3423 if (party_b) {
3424 ast_copy_string(value, party_b->base->accountcode, length);
3425 } else {
3426 ast_copy_string(value, "", length);
3427 }
3428 } else if (!strcasecmp(name, "uniqueid")) {
3429 ast_copy_string(value, party_a->base->uniqueid, length);
3430 } else if (!strcasecmp(name, "linkedid")) {
3431 ast_copy_string(value, cdr_obj->linkedid, length);
3432 } else if (!strcasecmp(name, "tenantid")) {
3433 ast_copy_string(value, party_a->base->tenantid, length);
3434 } else if (!strcasecmp(name, "peertenantid")) {
3435 if (party_b) {
3436 ast_copy_string(value, party_b->base->tenantid, length);
3437 } else {
3438 ast_copy_string(value, "", length);
3439 }
3440 } else if (!strcasecmp(name, "userfield")) {
3441 ast_copy_string(value, cdr_obj->party_a.userfield, length);
3442 } else if (!strcasecmp(name, "sequence")) {
3443 snprintf(value, length, "%u", cdr_obj->sequence);
3444 } else {
3445 return 1;
3446 }
3447
3448 return 0;
3449}
3450
3451/*! \internal
3452 * \brief Look up and retrieve a CDR object by channel name
3453 * \param name The name of the channel
3454 * \retval NULL on error
3455 * \return The \ref cdr_object for the channel on success, with the reference
3456 * count bumped by one.
3457 */
3458static struct cdr_object *cdr_object_get_by_name(const char *name)
3459{
3460 char *param;
3461
3462 if (ast_strlen_zero(name)) {
3463 return NULL;
3464 }
3465
3466 param = ast_strdupa(name);
3468}
3469
3470int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
3471{
3472 struct cdr_object *cdr;
3473 struct cdr_object *cdr_obj;
3474
3475 if (ast_strlen_zero(name)) {
3476 return 1;
3477 }
3478
3479 cdr = cdr_object_get_by_name(channel_name);
3480 if (!cdr) {
3481 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3482 return 1;
3483 }
3484
3485 ao2_lock(cdr);
3486
3487 cdr_obj = cdr->last;
3488 if (cdr_object_format_property(cdr_obj, name, value, length)) {
3489 /* Property failed; attempt variable */
3490 cdr_object_format_var_internal(cdr_obj, name, value, length);
3491 }
3492
3493 ao2_unlock(cdr);
3494
3495 ao2_cleanup(cdr);
3496 return 0;
3497}
3498
3499int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
3500{
3501 struct cdr_object *cdr;
3502 struct cdr_object *it_cdr;
3503 struct ast_var_t *variable;
3504 const char *var;
3505 char workspace[256];
3506 int total = 0, x = 0, i;
3507
3508 cdr = cdr_object_get_by_name(channel_name);
3509 if (!cdr) {
3511 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3512 }
3513 return 0;
3514 }
3515
3517
3518 ao2_lock(cdr);
3519 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3520 if (++x > 1) {
3521 ast_str_append(buf, 0, "\n");
3522 }
3523
3524 AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
3525 if (!(var = ast_var_name(variable))) {
3526 continue;
3527 }
3528
3529 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
3530 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3531 break;
3532 }
3533
3534 total++;
3535 }
3536
3537 for (i = 0; cdr_readonly_vars[i]; i++) {
3538 if (cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace))) {
3539 /* Unhandled read-only CDR variable. */
3540 ast_assert(0);
3541 continue;
3542 }
3543
3544 if (!ast_strlen_zero(workspace)
3545 && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
3546 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3547 break;
3548 }
3549 total++;
3550 }
3551 }
3552 ao2_unlock(cdr);
3553 ao2_cleanup(cdr);
3554 return total;
3555}
3556
3557void ast_cdr_free(struct ast_cdr *cdr)
3558{
3559 while (cdr) {
3560 struct ast_cdr *next = cdr->next;
3561
3562 free_variables(&cdr->varshead);
3563 ast_free(cdr);
3564 cdr = next;
3565 }
3566}
3567
3569{
3570 struct ast_cdr *x;
3571
3572 x = ast_calloc(1, sizeof(*x));
3573 return x;
3574}
3575
3577{
3578 switch (disposition) {
3579 case AST_CDR_NULL:
3580 return "NO ANSWER"; /* by default, for backward compatibility */
3581 case AST_CDR_NOANSWER:
3582 return "NO ANSWER";
3583 case AST_CDR_FAILED:
3584 return "FAILED";
3585 case AST_CDR_BUSY:
3586 return "BUSY";
3587 case AST_CDR_ANSWERED:
3588 return "ANSWERED";
3589 case AST_CDR_CONGESTION:
3590 return "CONGESTION";
3591 case AST_CDR_CANCEL:
3592 return "CANCEL";
3593 }
3594 return "UNKNOWN";
3595}
3596
3598 const char *channel_name;
3599 const char *userfield;
3600};
3601
3602/*! \brief Callback used to update the userfield on Party B on all CDRs */
3603static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, void *data, int flags)
3604{
3605 struct cdr_object *cdr = obj;
3606
3607 if ((cdr->fn_table != &finalized_state_fn_table || !cdr->next)
3608 && !strcasecmp(cdr->party_b_name, arg)) {
3609 struct party_b_userfield_update *info = data;
3610
3611 /*
3612 * For sanity's sake we also assert the party_b snapshot
3613 * is consistent with the key.
3614 */
3616 && !strcasecmp(cdr->party_b.snapshot->base->name, info->channel_name));
3617
3618 ast_copy_string(cdr->party_b.userfield, info->userfield,
3619 sizeof(cdr->party_b.userfield));
3620 }
3621
3622 return 0;
3623}
3624
3625void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
3626{
3627 struct cdr_object *cdr;
3628 struct party_b_userfield_update party_b_info = {
3630 .userfield = userfield,
3631 };
3632 struct cdr_object *it_cdr;
3633
3634 /* Handle Party A */
3635 cdr = cdr_object_get_by_name(channel_name);
3636 if (cdr) {
3637 ao2_lock(cdr);
3638 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3639 if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3640 continue;
3641 }
3642 ast_copy_string(it_cdr->party_a.userfield, userfield,
3643 sizeof(it_cdr->party_a.userfield));
3644 }
3645 ao2_unlock(cdr);
3646 }
3647
3648 /* Handle Party B */
3651 &party_b_info);
3652
3653 ao2_cleanup(cdr);
3654}
3655
3656static void post_cdr(struct ast_cdr *cdr)
3657{
3658 struct module_config *mod_cfg;
3659 struct cdr_beitem *i;
3660
3661 mod_cfg = ao2_global_obj_ref(module_configs);
3662 if (!mod_cfg) {
3663 return;
3664 }
3665
3666 for (; cdr ; cdr = cdr->next) {
3667 /* For people, who don't want to see unanswered single-channel events */
3668 if (!ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) &&
3671 ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel);
3672 continue;
3673 }
3674
3675 /* Modify CDR's */
3677 AST_RWLIST_TRAVERSE(&mo_list, i, list) {
3678 i->be(cdr);
3679 }
3681
3683 continue;
3684 }
3686 AST_RWLIST_TRAVERSE(&be_list, i, list) {
3687 if (!i->suspended) {
3688 i->be(cdr);
3689 }
3690 }
3692 }
3693 ao2_cleanup(mod_cfg);
3694}
3695
3696int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
3697{
3698 struct cdr_object *cdr;
3699 struct cdr_object *it_cdr;
3700
3701 cdr = cdr_object_get_by_name(channel_name);
3702 if (!cdr) {
3703 return -1;
3704 }
3705
3706 ao2_lock(cdr);
3707 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3708 if (it_cdr->fn_table == &finalized_state_fn_table) {
3709 continue;
3710 }
3711 /* Note: in general, set the flags on both the CDR record as well as the
3712 * Party A. Sometimes all we have is the Party A to look at.
3713 */
3714 ast_set_flag(&it_cdr->flags, option);
3715 ast_set_flag(&it_cdr->party_a, option);
3716 }
3717 ao2_unlock(cdr);
3718
3719 ao2_cleanup(cdr);
3720 return 0;
3721}
3722
3723int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
3724{
3725 struct cdr_object *cdr;
3726 struct cdr_object *it_cdr;
3727
3728 cdr = cdr_object_get_by_name(channel_name);
3729 if (!cdr) {
3730 return -1;
3731 }
3732
3733 ao2_lock(cdr);
3734 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3735 if (it_cdr->fn_table == &finalized_state_fn_table) {
3736 continue;
3737 }
3738 ast_clear_flag(&it_cdr->flags, option);
3739 }
3740 ao2_unlock(cdr);
3741
3742 ao2_cleanup(cdr);
3743 return 0;
3744}
3745
3746int ast_cdr_reset(const char *channel_name, int keep_variables)
3747{
3748 struct cdr_object *cdr;
3749 struct ast_var_t *vardata;
3750 struct cdr_object *it_cdr;
3751
3752 cdr = cdr_object_get_by_name(channel_name);
3753 if (!cdr) {
3754 return -1;
3755 }
3756
3757 ao2_lock(cdr);
3758 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3759 /* clear variables */
3760 if (!keep_variables) {
3761 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
3762 ast_var_delete(vardata);
3763 }
3764 if (cdr->party_b.snapshot) {
3765 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
3766 ast_var_delete(vardata);
3767 }
3768 }
3769 }
3770
3771 /* Reset to initial state */
3772 memset(&it_cdr->start, 0, sizeof(it_cdr->start));
3773 memset(&it_cdr->end, 0, sizeof(it_cdr->end));
3774 memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
3775 it_cdr->start = ast_tvnow();
3776 it_cdr->lastevent = it_cdr->start;
3778 }
3779 ao2_unlock(cdr);
3780
3781 ao2_cleanup(cdr);
3782 return 0;
3783}
3784
3785int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
3786{
3787 RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3788 struct cdr_object *new_cdr;
3789 struct cdr_object *it_cdr;
3790 struct cdr_object *cdr_obj;
3791
3792 if (!cdr) {
3793 return -1;
3794 }
3795
3796 {
3797 SCOPED_AO2LOCK(lock, cdr);
3798 struct timeval now = ast_tvnow();
3799
3800 cdr_obj = cdr->last;
3801 if (cdr_obj->fn_table == &finalized_state_fn_table) {
3802 /* If the last CDR in the chain is finalized, don't allow a fork -
3803 * things are already dying at this point
3804 */
3805 return -1;
3806 }
3807
3808 /* Copy over the basic CDR information. The Party A information is
3809 * copied over automatically as part of the append
3810 */
3811 ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->base->name);
3812 new_cdr = cdr_object_create_and_append(cdr, &now);
3813 if (!new_cdr) {
3814 return -1;
3815 }
3816 new_cdr->fn_table = cdr_obj->fn_table;
3817 ast_string_field_set(new_cdr, bridge, cdr->bridge);
3818 ast_string_field_set(new_cdr, appl, cdr->appl);
3819 ast_string_field_set(new_cdr, data, cdr->data);
3820 ast_string_field_set(new_cdr, context, cdr->context);
3821 ast_string_field_set(new_cdr, exten, cdr->exten);
3822 new_cdr->flags = cdr->flags;
3823 /* Explicitly clear the AST_CDR_LOCK_APP flag - we want
3824 * the application to be changed on the new CDR if the
3825 * dialplan demands it
3826 */
3828
3829 /* If there's a Party B, copy it over as well */
3830 if (cdr_obj->party_b.snapshot) {
3831 new_cdr->party_b.snapshot = cdr_obj->party_b.snapshot;
3832 ao2_ref(new_cdr->party_b.snapshot, +1);
3833 cdr_all_relink(new_cdr);
3834 strcpy(new_cdr->party_b.userfield, cdr_obj->party_b.userfield);
3835 new_cdr->party_b.flags = cdr_obj->party_b.flags;
3837 copy_variables(&new_cdr->party_b.variables, &cdr_obj->party_b.variables);
3838 }
3839 }
3840 new_cdr->start = cdr_obj->start;
3841 new_cdr->answer = cdr_obj->answer;
3842 new_cdr->lastevent = ast_tvnow();
3843
3844 /* Modify the times based on the flags passed in */
3846 && new_cdr->party_a.snapshot->state == AST_STATE_UP) {
3847 new_cdr->answer = ast_tvnow();
3848 }
3850 new_cdr->answer = ast_tvnow();
3851 new_cdr->start = ast_tvnow();
3852 }
3853
3854 /* Create and append, by default, copies over the variables */
3856 free_variables(&new_cdr->party_a.variables);
3857 }
3858
3859 /* Finalize any current CDRs */
3861 for (it_cdr = cdr; it_cdr != new_cdr; it_cdr = it_cdr->next) {
3862 if (it_cdr->fn_table == &finalized_state_fn_table) {
3863 continue;
3864 }
3865 /* Force finalization on the CDR. This will bypass any checks for
3866 * end before 'h' extension.
3867 */
3868 cdr_object_finalize(it_cdr);
3870 }
3871 }
3872 }
3873
3874 return 0;
3875}
3876
3877/*! \note Don't call without cdr_batch_lock */
3878static void reset_batch(void)
3879{
3880 batch->size = 0;
3881 batch->head = NULL;
3882 batch->tail = NULL;
3883}
3884
3885/*! \note Don't call without cdr_batch_lock */
3886static int init_batch(void)
3887{
3888 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
3889 if (!(batch = ast_malloc(sizeof(*batch))))
3890 return -1;
3891
3892 reset_batch();
3893
3894 return 0;
3895}
3896
3897static void *do_batch_backend_process(void *data)
3898{
3899 struct cdr_batch_item *processeditem;
3900 struct cdr_batch_item *batchitem = data;
3901
3902 /* Push each CDR into storage mechanism(s) and free all the memory */
3903 while (batchitem) {
3904 post_cdr(batchitem->cdr);
3905 ast_cdr_free(batchitem->cdr);
3906 processeditem = batchitem;
3907 batchitem = batchitem->next;
3908 ast_free(processeditem);
3909 }
3910
3911 return NULL;
3912}
3913
3914static void cdr_submit_batch(int do_shutdown)
3915{
3916 struct module_config *mod_cfg;
3917 struct cdr_batch_item *oldbatchitems = NULL;
3918 pthread_t batch_post_thread = AST_PTHREADT_NULL;
3919
3920 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
3921 if (!batch || !batch->head) {
3922 return;
3923 }
3924
3925 /* move the old CDRs aside, and prepare a new CDR batch */
3927 oldbatchitems = batch->head;
3928 reset_batch();
3930
3931 mod_cfg = ao2_global_obj_ref(module_configs);
3932
3933 /* if configured, spawn a new thread to post these CDRs,
3934 also try to save as much as possible if we are shutting down safely */
3935 if (!mod_cfg
3937 || do_shutdown) {
3938 ast_debug(1, "CDR single-threaded batch processing begins now\n");
3939 do_batch_backend_process(oldbatchitems);
3940 } else {
3941 if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
3942 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
3943 do_batch_backend_process(oldbatchitems);
3944 } else {
3945 ast_debug(1, "CDR multi-threaded batch processing begins now\n");
3946 }
3947 }
3948
3949 ao2_cleanup(mod_cfg);
3950}
3951
3952static int submit_scheduled_batch(const void *data)
3953{
3954 struct module_config *mod_cfg;
3955 int nextms;
3956
3958
3959 mod_cfg = ao2_global_obj_ref(module_configs);
3960 if (!mod_cfg) {
3961 return 0;
3962 }
3963
3964 /* Calculate the next scheduled interval */
3965 nextms = mod_cfg->general->batch_settings.time * 1000;
3966
3967 ao2_cleanup(mod_cfg);
3968
3969 return nextms;
3970}
3971
3972/*! Do not hold the batch lock while calling this function */
3973static void start_batch_mode(void)
3974{
3975 /* Prevent two deletes from happening at the same time */
3977 /* this is okay since we are not being called from within the scheduler */
3979 /* schedule the submission to occur ASAP (1 ms) */
3982
3983 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
3987}
3988
3989static void cdr_detach(struct ast_cdr *cdr)
3990{
3991 struct cdr_batch_item *newtail;
3992 int curr;
3993 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3994 int submit_batch = 0;
3995
3996 if (!cdr) {
3997 return;
3998 }
3999
4000 /* maybe they disabled CDR stuff completely, so just drop it */
4001 if (!mod_cfg || !ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4002 ast_debug(1, "Dropping CDR !\n");
4004 return;
4005 }
4006
4007 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
4008 if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4009 post_cdr(cdr);
4011 return;
4012 }
4013
4014 /* otherwise, each CDR gets put into a batch list (at the end) */
4015 ast_debug(1, "CDR detaching from this thread\n");
4016
4017 /* we'll need a new tail for every CDR */
4018 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
4019 post_cdr(cdr);
4021 return;
4022 }
4023
4024 /* don't traverse a whole list (just keep track of the tail) */
4026 if (!batch)
4027 init_batch();
4028 if (!batch->head) {
4029 /* new batch is empty, so point the head at the new tail */
4030 batch->head = newtail;
4031 } else {
4032 /* already got a batch with something in it, so just append a new tail */
4033 batch->tail->next = newtail;
4034 }
4035 newtail->cdr = cdr;
4036 batch->tail = newtail;
4037 curr = batch->size++;
4038
4039 /* if we have enough stuff to post, then do it */
4040 if (curr >= (mod_cfg->general->batch_settings.size - 1)) {
4041 submit_batch = 1;
4042 }
4044
4045 /* Don't submit a batch with cdr_batch_lock held */
4046 if (submit_batch) {
4048 }
4049}
4050
4051static void *do_cdr(void *data)
4052{
4053 struct timespec timeout;
4054 int schedms;
4055 int numevents = 0;
4056
4057 for (;;) {
4058 struct timeval now;
4059 schedms = ast_sched_wait(sched);
4060 /* this shouldn't happen, but provide a 1 second default just in case */
4061 if (schedms < 0)
4062 schedms = 1000;
4063 now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
4064 timeout.tv_sec = now.tv_sec;
4065 timeout.tv_nsec = now.tv_usec * 1000;
4066 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
4069 numevents = ast_sched_runq(sched);
4071 ast_debug(2, "Processed %d CDR batches from the run queue\n", numevents);
4072 }
4073
4074 return NULL;
4075}
4076
4077static char *handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4078{
4079 struct module_config *mod_cfg;
4080
4081 switch (cmd) {
4082 case CLI_INIT:
4083 e->command = "cdr set debug [on|off]";
4084 e->usage = "Enable or disable extra debugging in the CDR Engine. Note\n"
4085 "that this will dump debug information to the VERBOSE setting\n"
4086 "and should only be used when debugging information from the\n"
4087 "CDR engine is needed.\n";
4088 return NULL;
4089 case CLI_GENERATE:
4090 return NULL;
4091 }
4092
4093 if (a->argc != 4) {
4094 return CLI_SHOWUSAGE;
4095 }
4096
4097 mod_cfg = ao2_global_obj_ref(module_configs);
4098 if (!mod_cfg) {
4099 ast_cli(a->fd, "Could not set CDR debugging mode\n");
4100 return CLI_SUCCESS;
4101 }
4102 if (!strcasecmp(a->argv[3], "on")
4103 && !ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
4105 ast_cli(a->fd, "CDR debugging enabled\n");
4106 } else if (!strcasecmp(a->argv[3], "off")
4107 && ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
4109 ast_cli(a->fd, "CDR debugging disabled\n");
4110 }
4111 cdr_set_debug_mode(mod_cfg);
4112 ao2_cleanup(mod_cfg);
4113
4114 return CLI_SUCCESS;
4115}
4116
4117/*! \brief Complete user input for 'cdr show' */
4118static char *cli_complete_show(struct ast_cli_args *a)
4119{
4120 int wordlen = strlen(a->word);
4121 struct ao2_iterator it_cdrs;
4122 struct cdr_object *cdr;
4123
4125 while ((cdr = ao2_iterator_next(&it_cdrs))) {
4126 if (!strncasecmp(a->word, cdr->party_a.snapshot->base->name, wordlen)) {
4128 ao2_ref(cdr, -1);
4129 break;
4130 }
4131 }
4132 ao2_ref(cdr, -1);
4133 }
4134 ao2_iterator_destroy(&it_cdrs);
4135
4136 return NULL;
4137}
4138
4140{
4141 struct ao2_iterator it_cdrs;
4142 struct cdr_object *cdr;
4143 char start_time_buffer[64];
4144 char answer_time_buffer[64];
4145 char end_time_buffer[64];
4146
4147#define TITLE_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
4148#define FORMAT_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
4149
4150 ast_cli(a->fd, "\n");
4151 ast_cli(a->fd, "Channels with Call Detail Record (CDR) Information\n");
4152 ast_cli(a->fd, "--------------------------------------------------\n");
4153 ast_cli(a->fd, TITLE_STRING, "Channel", "Dst. Channel", "LastApp", "Start", "Answer", "End", "Billsec", "Duration");
4154
4156 for (; (cdr = ao2_iterator_next(&it_cdrs)); ao2_cleanup(cdr)) {
4157 struct cdr_object *it_cdr;
4158 struct timeval start_time = { 0, };
4159 struct timeval answer_time = { 0, };
4160 struct timeval end_time = { 0, };
4161
4162 SCOPED_AO2LOCK(lock, cdr);
4163
4164 /* Calculate the start, end, answer, billsec, and duration over the
4165 * life of all of the CDR entries
4166 */
4167 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4168 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
4169 continue;
4170 }
4171 if (ast_tvzero(start_time)) {
4172 start_time = it_cdr->start;
4173 }
4174 if (!ast_tvzero(it_cdr->answer) && ast_tvzero(answer_time)) {
4175 answer_time = it_cdr->answer;
4176 }
4177 }
4178
4179 /* If there was no start time, then all CDRs were for a dialed channel; skip */
4180 if (ast_tvzero(start_time)) {
4181 continue;
4182 }
4183 it_cdr = cdr->last;
4184
4185 end_time = ast_tvzero(it_cdr->end) ? ast_tvnow() : it_cdr->end;
4186 cdr_get_tv(start_time, "%T", start_time_buffer, sizeof(start_time_buffer));
4187 cdr_get_tv(answer_time, "%T", answer_time_buffer, sizeof(answer_time_buffer));
4188 cdr_get_tv(end_time, "%T", end_time_buffer, sizeof(end_time_buffer));
4190 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
4191 it_cdr->appl,
4192 start_time_buffer,
4193 answer_time_buffer,
4194 end_time_buffer,
4195 ast_tvzero(answer_time) ? 0 : (long)ast_tvdiff_ms(end_time, answer_time) / 1000,
4196 (long)ast_tvdiff_ms(end_time, start_time) / 1000);
4197 }
4198 ao2_iterator_destroy(&it_cdrs);
4199#undef FORMAT_STRING
4200#undef TITLE_STRING
4201}
4202
4203static void cli_show_channel(struct ast_cli_args *a)
4204{
4205 struct cdr_object *it_cdr;
4206 char clid[64];
4207 char start_time_buffer[64];
4208 char answer_time_buffer[64];
4209 char end_time_buffer[64];
4210 const char *channel_name = a->argv[3];
4211 struct cdr_object *cdr;
4212
4213#define TITLE_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
4214#define FORMAT_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
4215
4216 cdr = cdr_object_get_by_name(channel_name);
4217 if (!cdr) {
4218 ast_cli(a->fd, "Unknown channel: %s\n", channel_name);
4219 return;
4220 }
4221
4222 ast_cli(a->fd, "\n");
4223 ast_cli(a->fd, "Call Detail Record (CDR) Information for %s\n", channel_name);
4224 ast_cli(a->fd, "--------------------------------------------------\n");
4225 ast_cli(a->fd, TITLE_STRING, "AccountCode", "CallerID", "Dst. Channel", "LastApp", "Data", "Start", "Answer", "End", "Billsec", "Duration");
4226
4227 ao2_lock(cdr);
4228 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4229 struct timeval end;
4230
4231 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
4232 continue;
4233 }
4234 ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller->name, it_cdr->party_a.snapshot->caller->number, "");
4235 if (ast_tvzero(it_cdr->end)) {
4236 end = ast_tvnow();
4237 } else {
4238 end = it_cdr->end;
4239 }
4240 cdr_get_tv(it_cdr->start, "%T", start_time_buffer, sizeof(start_time_buffer));
4241 cdr_get_tv(it_cdr->answer, "%T", answer_time_buffer, sizeof(answer_time_buffer));
4242 cdr_get_tv(end, "%T", end_time_buffer, sizeof(end_time_buffer));
4243 ast_cli(a->fd, FORMAT_STRING,
4244 it_cdr->party_a.snapshot->base->accountcode,
4245 clid,
4246 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
4247 it_cdr->appl,
4248 it_cdr->data,
4249 start_time_buffer,
4250 answer_time_buffer,
4251 end_time_buffer,
4252 (long)ast_tvdiff_ms(end, it_cdr->answer) / 1000,
4253 (long)ast_tvdiff_ms(end, it_cdr->start) / 1000);
4254 }
4255 ao2_unlock(cdr);
4256
4257 ao2_cleanup(cdr);
4258
4259#undef FORMAT_STRING
4260#undef TITLE_STRING
4261}
4262
4263static char *handle_cli_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4264{
4265 switch (cmd) {
4266 case CLI_INIT:
4267 e->command = "cdr show active";
4268 e->usage =
4269 "Usage: cdr show active [channel]\n"
4270 " Displays a summary of all Call Detail Records when [channel]\n"
4271 " is omitted; displays all of the Call Detail Records\n"
4272 " currently in flight for a given [channel] when [channel] is\n"
4273 " specified.\n\n"
4274 " Note that this will not display Call Detail Records that\n"
4275 " have already been dispatched to a backend storage, nor for\n"
4276 " channels that are no longer active.\n";
4277 return NULL;
4278 case CLI_GENERATE:
4279 return cli_complete_show(a);
4280 }
4281
4282 if (a->argc > 4) {
4283 return CLI_SHOWUSAGE;
4284 } else if (a->argc < 4) {
4286 } else {
4288 }
4289
4290 return CLI_SUCCESS;
4291}
4292
4293static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4294{
4295 struct cdr_beitem *beitem = NULL;
4296 struct module_config *mod_cfg;
4297 int cnt = 0;
4298 long nextbatchtime = 0;
4299
4300 switch (cmd) {
4301 case CLI_INIT:
4302 e->command = "cdr show status";
4303 e->usage =
4304 "Usage: cdr show status\n"
4305 " Displays the Call Detail Record engine system status.\n";
4306 return NULL;
4307 case CLI_GENERATE:
4308 return NULL;
4309 }
4310
4311 if (a->argc > 3) {
4312 return CLI_SHOWUSAGE;
4313 }
4314
4315 mod_cfg = ao2_global_obj_ref(module_configs);
4316 if (!mod_cfg) {
4317 return CLI_FAILURE;
4318 }
4319
4320 ast_cli(a->fd, "\n");
4321 ast_cli(a->fd, "Call Detail Record (CDR) settings\n");
4322 ast_cli(a->fd, "----------------------------------\n");
4323 ast_cli(a->fd, " Logging: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED) ? "Enabled" : "Disabled");
4324 ast_cli(a->fd, " Mode: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE) ? "Batch" : "Simple");
4325 if (ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4326 ast_cli(a->fd, " Log calls by default: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_CHANNEL_DEFAULT_ENABLED) ? "Yes" : "No");
4327 ast_cli(a->fd, " Log unanswered calls: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) ? "Yes" : "No");
4328 ast_cli(a->fd, " Log congestion: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION) ? "Yes" : "No");
4329 ast_cli(a->fd, " Ignore bridging changes: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_STATE_CHANGES) ? "Yes" : "No");
4330 ast_cli(a->fd, " Ignore dial state changes: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_DIAL_CHANGES) ? "Yes" : "No");
4331 ast_cli(a->fd, " Cancel disposition enabled: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_CANCEL_DISPOSITION_ENABLED) ? "Yes" : "No");
4332 if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4333 ast_cli(a->fd, "* Batch Mode Settings\n");
4334 ast_cli(a->fd, " -------------------\n");
4335 if (batch)
4336 cnt = batch->size;
4337 if (cdr_sched > -1)
4338 nextbatchtime = ast_sched_when(sched, cdr_sched);
4339 ast_cli(a->fd, " Safe shutdown: %s\n", ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SAFE_SHUTDOWN) ? "Enabled" : "Disabled");
4340 ast_cli(a->fd, " Threading model: %s\n", ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SCHEDULER_ONLY) ? "Scheduler only" : "Scheduler plus separate threads");
4341 ast_cli(a->fd, " Current batch size: %d record%s\n", cnt, ESS(cnt));
4342 ast_cli(a->fd, " Maximum batch size: %u record%s\n", mod_cfg->general->batch_settings.size, ESS(mod_cfg->general->batch_settings.size));
4343 ast_cli(a->fd, " Maximum batch time: %u second%s\n", mod_cfg->general->batch_settings.time, ESS(mod_cfg->general->batch_settings.time));
4344 ast_cli(a->fd, " Next batch processing time: %ld second%s\n\n", nextbatchtime, ESS(nextbatchtime));
4345 }
4346 ast_cli(a->fd, "* Registered Backends\n");
4347 ast_cli(a->fd, " -------------------\n");
4349 if (AST_RWLIST_EMPTY(&be_list)) {
4350 ast_cli(a->fd, " (none)\n");
4351 } else {
4352 AST_RWLIST_TRAVERSE(&be_list, beitem, list) {
4353 ast_cli(a->fd, " %s%s\n", beitem->name, beitem->suspended ? " (suspended) " : "");
4354 }
4355 }
4357 ast_cli(a->fd, "\n");
4358 }
4359
4360 ao2_cleanup(mod_cfg);
4361 return CLI_SUCCESS;
4362}
4363
4364static char *handle_cli_submit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4365{
4366 struct module_config *mod_cfg;
4367
4368 switch (cmd) {
4369 case CLI_INIT:
4370 e->command = "cdr submit";
4371 e->usage =
4372 "Usage: cdr submit\n"
4373 "Posts all pending batched CDR data to the configured CDR\n"
4374 "backend engine modules.\n";
4375 return NULL;
4376 case CLI_GENERATE:
4377 return NULL;
4378 }
4379 if (a->argc > 2) {
4380 return CLI_SHOWUSAGE;
4381 }
4382
4383 mod_cfg = ao2_global_obj_ref(module_configs);
4384 if (!mod_cfg) {
4385 return CLI_FAILURE;
4386 }
4387
4388 if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4389 ast_cli(a->fd, "Cannot submit CDR batch: CDR engine disabled.\n");
4390 } else if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4391 ast_cli(a->fd, "Cannot submit CDR batch: batch mode not enabled.\n");
4392 } else {
4394 ast_cli(a->fd, "Submitted CDRs to backend engines for processing. This may take a while.\n");
4395 }
4396 ao2_cleanup(mod_cfg);
4397
4398 return CLI_SUCCESS;
4399}
4400
4401static struct ast_cli_entry cli_commands[] = {
4402 AST_CLI_DEFINE(handle_cli_submit, "Posts all pending batched CDR data"),
4403 AST_CLI_DEFINE(handle_cli_status, "Display the CDR status"),
4404 AST_CLI_DEFINE(handle_cli_show, "Display active CDRs for channels"),
4405 AST_CLI_DEFINE(handle_cli_debug, "Enable debugging in the CDR engine"),
4406};
4407
4408/*!
4409 * \brief This dispatches *all* \ref cdr_object. It should only be used during
4410 * shutdown, so that we get billing records for everything that we can.
4411 */
4412static int cdr_object_dispatch_all_cb(void *obj, void *arg, int flags)
4413{
4414 struct cdr_object *cdr = obj;
4415 struct cdr_object *it_cdr;
4416
4417 ao2_lock(cdr);
4418 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4420 }
4422 ao2_unlock(cdr);
4423
4424 cdr_all_unlink(cdr);
4425
4426 return CMP_MATCH;
4427}
4428
4429static void finalize_batch_mode(void)
4430{
4432 return;
4433 }
4434 /* wake up the thread so it will exit */
4435 pthread_cancel(cdr_thread);
4436 pthread_kill(cdr_thread, SIGURG);
4437 pthread_join(cdr_thread, NULL);
4441}
4442
4444{
4445 if (!stasis_router) {
4446 return NULL;
4447 }
4448
4450 return stasis_router;
4451}
4452
4453/*!
4454 * \brief Destroy the active Stasis subscriptions
4455 */
4456static void destroy_subscriptions(void)
4457{
4461}
4462
4463/*!
4464 * \brief Create the Stasis subscriptions for CDRs
4465 */
4466static int create_subscriptions(void)
4467{
4468 if (!cdr_topic) {
4469 return -1;
4470 }
4471
4473 return 0;
4474 }
4475
4477 if (!channel_subscription) {
4478 return -1;
4479 }
4481 if (!bridge_subscription) {
4482 return -1;
4483 }
4485 if (!parking_subscription) {
4486 return -1;
4487 }
4488
4489 return 0;
4490}
4491
4492static int process_config(int reload)
4493{
4494 if (!reload) {
4495 if (aco_info_init(&cfg_info)) {
4496 return 1;
4497 }
4498
4514 }
4515
4516 if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) {
4517 struct module_config *mod_cfg;
4518
4519 if (reload) {
4520 return 1;
4521 }
4522
4523 /* If we couldn't process the configuration and this wasn't a reload,
4524 * create a default config
4525 */
4526 mod_cfg = module_config_alloc();
4527 if (!mod_cfg
4528 || aco_set_defaults(&general_option, "general", mod_cfg->general)) {
4529 ao2_cleanup(mod_cfg);
4530 return 1;
4531 }
4532 ast_log(LOG_NOTICE, "Failed to process CDR configuration; using defaults\n");
4533 ao2_global_obj_replace_unref(module_configs, mod_cfg);
4534 cdr_set_debug_mode(mod_cfg);
4535 ao2_cleanup(mod_cfg);
4536 }
4537
4538 return 0;
4539}
4540
4541static void cdr_engine_shutdown(void)
4542{
4545
4547 cdr_topic = NULL;
4548
4549 STASIS_MESSAGE_TYPE_CLEANUP(cdr_sync_message_type);
4550
4556 sched = NULL;
4557 ast_free(batch);
4558 batch = NULL;
4559
4560 aco_info_destroy(&cfg_info);
4561 ao2_global_obj_release(module_configs);
4562
4563 ao2_container_unregister("cdrs_master");
4566
4567 ao2_container_unregister("cdrs_all");
4570}
4571
4573{
4574 /* Only create the thread level portions once */
4578 ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
4579 return;
4580 }
4581 }
4582
4583 /* Start the batching process */
4585
4586 ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %u or time %u seconds.\n",
4587 config->batch_settings.size, config->batch_settings.time);
4588}
4589
4590/*!
4591 * \internal
4592 * \brief Print master CDR container object.
4593 * \since 12.0.0
4594 *
4595 * \param v_obj A pointer to the object we want printed.
4596 * \param where User data needed by prnt to determine where to put output.
4597 * \param prnt Print output callback function to use.
4598 */
4599static void cdr_master_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
4600{
4601 struct cdr_object *cdr = v_obj;
4602 struct cdr_object *it_cdr;
4603
4604 if (!cdr) {
4605 return;
4606 }
4607 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4608 prnt(where, "Party A: %s; Party B: %s; Bridge %s\n",
4609 it_cdr->party_a.snapshot->base->name,
4610 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<unknown>",
4611 it_cdr->bridge);
4612 }
4613}
4614
4615/*!
4616 * \internal
4617 * \brief Print all CDR container object.
4618 * \since 13.19.0
4619 *
4620 * \param v_obj A pointer to the object we want printed.
4621 * \param where User data needed by prnt to determine where to put output.
4622 * \param prnt Print output callback function to use.
4623 */
4624static void cdr_all_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
4625{
4626 struct cdr_object *cdr = v_obj;
4627
4628 if (!cdr) {
4629 return;
4630 }
4631 prnt(where, "Party A: %s; Party B: %s; Bridge %s",
4632 cdr->party_a.snapshot->base->name,
4633 cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<unknown>",
4634 cdr->bridge);
4635}
4636
4637/*!
4638 * \brief Checks if CDRs are enabled and enables/disables the necessary options
4639 */
4641{
4642 struct module_config *mod_cfg;
4643
4644 mod_cfg = ao2_global_obj_ref(module_configs);
4645 if (mod_cfg
4646 && ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4647 if (create_subscriptions()) {
4649 ast_log(AST_LOG_ERROR, "Failed to create Stasis subscriptions\n");
4650 ao2_cleanup(mod_cfg);
4651 return -1;
4652 }
4653 if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4655 } else {
4656 ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
4657 }
4658 } else {
4660 ast_log(LOG_NOTICE, "CDR logging disabled.\n");
4661 }
4662 ao2_cleanup(mod_cfg);
4663
4664 return mod_cfg ? 0 : -1;
4665}
4666
4667static int unload_module(void)
4668{
4670
4671 return 0;
4672}
4673
4674static int load_module(void)
4675{
4676 struct module_config *mod_cfg = NULL;
4677 if (process_config(0)) {
4679 }
4680
4681 cdr_topic = stasis_topic_create("cdr:aggregator");
4682 if (!cdr_topic) {
4684 }
4685
4687 if (!stasis_router) {
4689 }
4692
4693 if (STASIS_MESSAGE_TYPE_INIT(cdr_sync_message_type)) {
4695 }
4696
4697 mod_cfg = ao2_global_obj_ref(module_configs);
4698
4700
4701 /* Always process dial messages, because even if we ignore most of it, we do want the dial status for the disposition. */
4703 if (!mod_cfg || !ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_DIAL_CHANGES)) {
4705 } else {
4707 CDR_DEBUG("Dial messages will be mostly ignored\n");
4708 }
4709
4710 /* If explicitly instructed to ignore call state changes, then ignore bridging events, parking, etc. */
4711 if (!mod_cfg || !ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_STATE_CHANGES)) {
4715 } else {
4716 CDR_DEBUG("All bridge and parking messages will be ignored\n");
4717 }
4718
4720
4721 if (mod_cfg) {
4722 ao2_cleanup(mod_cfg);
4723 } else {
4724 ast_log(LOG_WARNING, "Unable to obtain CDR configuration during module load?\n");
4725 }
4726
4729 if (!active_cdrs_master) {
4731 }
4733
4736 if (!active_cdrs_all) {
4738 }
4740
4742 if (!sched) {
4743 ast_log(LOG_ERROR, "Unable to create schedule context.\n");
4745 }
4746
4749
4751}
4752
4754{
4755 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
4756
4757 /* Since this is called explicitly during process shutdown, we might not have ever
4758 * been initialized. If so, the config object will be NULL.
4759 */
4760 if (!mod_cfg) {
4761 return;
4762 }
4763
4764 if (cdr_sync_message_type()) {
4765 void *payload;
4766 struct stasis_message *message;
4767
4768 if (!stasis_router) {
4769 return;
4770 }
4771
4772 /* Make sure we have the needed items */
4773 payload = ao2_alloc(sizeof(*payload), NULL);
4774 if (!payload) {
4775 return;
4776 }
4777
4778 ast_debug(1, "CDR Engine termination request received; waiting on messages...\n");
4779
4780 message = stasis_message_create(cdr_sync_message_type(), payload);
4781 if (message) {
4783 }
4785 ao2_cleanup(payload);
4786 }
4787
4788 if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4789 cdr_submit_batch(ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SAFE_SHUTDOWN));
4790 }
4791}
4792
4793static int reload_module(void)
4794{
4795 struct module_config *old_mod_cfg;
4796 struct module_config *mod_cfg;
4797
4798 old_mod_cfg = ao2_global_obj_ref(module_configs);
4799
4800 if (!old_mod_cfg || process_config(1)) {
4801 ao2_cleanup(old_mod_cfg);
4802 return -1;
4803 }
4804
4805 mod_cfg = ao2_global_obj_ref(module_configs);
4806 if (!mod_cfg
4807 || !ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)
4808 || !ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4809 /* If batch mode used to be enabled, finalize the batch */
4810 if (ast_test_flag(&old_mod_cfg->general->settings, CDR_BATCHMODE)) {
4812 }
4813 }
4814 ao2_cleanup(mod_cfg);
4815
4816 ao2_cleanup(old_mod_cfg);
4818}
4819
4821 .support_level = AST_MODULE_SUPPORT_CORE,
4822 .load = load_module,
4823 .unload = unload_module,
4825 .load_pri = AST_MODPRI_CORE,
4826 .requires = "extconfig",
ast_mutex_t lock
Definition: app_sla.c:337
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
#define ao2_t_ref(o, delta, tag)
Definition: astobj2.h:460
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
Definition: astobj2.h:901
#define ao2_t_replace(dst, src, tag)
Definition: astobj2.h:504
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1723
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_UNLINK
Definition: astobj2.h:1039
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
Definition: astobj2.h:1435
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1273
Internal Asterisk hangup causes.
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition: causes.h:100
#define AST_CAUSE_UNREGISTERED
Definition: causes.h:154
#define AST_CAUSE_BUSY
Definition: causes.h:149
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:109
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
static void reset_batch(void)
Definition: cdr.c:3878
struct cdr_object_fn_table dial_state_fn_table
The virtual table for the Dial state.
Definition: cdr.c:708
static void finalized_state_init_function(struct cdr_object *cdr)
Definition: cdr.c:2154
struct cdr_object_fn_table single_state_fn_table
The virtual table for the Single state.
Definition: cdr.c:677
static int dial_changes_ignored
Definition: cdr.c:312
static struct aco_type ignore_option
Definition: cdr.c:356
static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
Definition: cdr.c:1932
static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2159
static int cdr_object_dispatch_all_cb(void *obj, void *arg, int flags)
This dispatches all cdr_object. It should only be used during shutdown, so that we get billing record...
Definition: cdr.c:4412
static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
Format one of the standard properties on a cdr_object.
Definition: cdr.c:3381
static void cdr_object_transition_state_init(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table, int do_init)
Transition a cdr_object to a new state with initiation flag.
Definition: cdr.c:910
static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
Definition: cdr.c:2102
#define DEFAULT_BATCH_SIZE
Definition: cdr.c:299
static void handle_parked_call_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for when a channel is parked.
Definition: cdr.c:2885
static struct ast_cdr * cdr_object_create_public_records(struct cdr_object *cdr)
Create a chain of ast_cdr objects from a chain of cdr_object suitable for consumption by the register...
Definition: cdr.c:1389
int ast_cdr_is_enabled(void)
Return TRUE if CDR subsystem is enabled.
Definition: cdr.c:2994
#define MAX_BATCH_SIZE
Definition: cdr.c:300
static struct ast_cli_entry cli_commands[]
Definition: cdr.c:4401
static pthread_t cdr_thread
Definition: cdr.c:459
void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:3625
static void cdr_all_unlink(struct cdr_object *cdr)
Definition: cdr.c:1074
static const char *const cdr_readonly_vars[]
Definition: cdr.c:3291
STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_sync_message_type)
A message type used to synchronize with the CDR topic.
static void handle_standard_bridge_enter_message(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel, const struct timeval *event_time)
Handle a bridge enter message for a 'normal' bridge.
Definition: cdr.c:2763
static int process_config(int reload)
Definition: cdr.c:4492
static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:2092
static char * handle_cli_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cdr.c:4263
static struct cdr_object * cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
cdr_object constructor
Definition: cdr.c:1142
int ast_cdr_modifier_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR modifier.
Definition: cdr.c:3081
static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
Definition: cdr.c:3168
static int single_state_bridge_enter_comparison(struct cdr_object *cdr, struct cdr_object *cand_cdr)
Handle a comparison between our cdr_object and a cdr_object already in the bridge while in the Single...
Definition: cdr.c:1796
static struct cdr_object * cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
Create a new cdr_object and append it to an existing chain.
Definition: cdr.c:1179
static const char * ignore_categories[]
Definition: cdr.c:343
static void cdr_all_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: cdr.c:4624
static long cdr_object_get_duration(struct cdr_object *cdr)
Definition: cdr.c:1329
void ast_cdr_free(struct ast_cdr *cdr)
Free a CDR record.
Definition: cdr.c:3557
struct cdr_object_fn_table dialed_pending_state_fn_table
The virtual table for the Dialed Pending state.
Definition: cdr.c:741
static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2112
void ast_cdr_set_config(struct ast_cdr_config *config)
Set the current CDR configuration.
Definition: cdr.c:2973
#define DEFAULT_BATCHMODE
Definition: cdr.c:290
static ast_cond_t cdr_pending_cond
Definition: cdr.c:466
struct stasis_message_router * ast_cdr_message_router(void)
Return the message router for the CDR engine.
Definition: cdr.c:4443
static void single_state_init_function(struct cdr_object *cdr)
Definition: cdr.c:1743
static int create_subscriptions(void)
Create the Stasis subscriptions for CDRs.
Definition: cdr.c:4466
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1544
static struct ast_sched_context * sched
Scheduler items.
Definition: cdr.c:456
static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1705
static int cdr_object_update_party_b(void *obj, void *arg, void *data, int flags)
Definition: cdr.c:2343
#define DEFAULT_IGNORE_STATE_CHANGES
Definition: cdr.c:296
static ast_mutex_t cdr_batch_lock
Lock protecting modifications to the batch queue.
Definition: cdr.c:462
process_bridge_enter_results
Return types for process_bridge_enter functions.
Definition: cdr.c:495
@ BRIDGE_ENTER_ONLY_PARTY
Definition: cdr.c:499
@ BRIDGE_ENTER_NO_PARTY_B
Definition: cdr.c:507
@ BRIDGE_ENTER_NEED_CDR
Definition: cdr.c:511
@ BRIDGE_ENTER_OBTAINED_PARTY_B
Definition: cdr.c:503
int ast_cdr_modifier_unregister(const char *name)
Unregister a CDR modifier.
Definition: cdr.c:3126
static int cdr_generic_register(struct be_list *generic_list, const char *name, const char *desc, ast_cdrbe be)
Definition: cdr.c:3035
static void cdr_detach(struct ast_cdr *cdr)
Definition: cdr.c:3989
static int cdr_object_finalize_party_b(void *obj, void *arg, void *data, int flags)
Definition: cdr.c:2319
static struct cdr_batch * batch
static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
Process a single bridge_candidate.
Definition: cdr.c:2637
struct cdr_object_fn_table bridge_state_fn_table
The virtual table for the Bridged state.
Definition: cdr.c:763
static char * handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cdr.c:4077
static void cli_show_channels(struct ast_cli_args *a)
Definition: cdr.c:4139
#define FORMAT_STRING
static struct stasis_forward * bridge_subscription
Our subscription for bridges.
Definition: cdr.c:478
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:3723
static int cdr_object_select_all_by_name_cb(void *obj, void *arg, int flags)
Definition: cdr.c:3263
static int cdr_sched
Definition: cdr.c:457
int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
Set a variable on a CDR.
Definition: cdr.c:3316
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:3183
static const char * cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
Definition: cdr.c:3151
static int cdr_all_hash_fn(const void *obj, const int flags)
Definition: cdr.c:994
static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2174
static enum process_bridge_enter_results base_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1715
static void cdr_object_dispatch(struct cdr_object *cdr)
Dispatch a CDR.
Definition: cdr.c:1490
static struct stasis_forward * channel_subscription
Our subscription for channels.
Definition: cdr.c:481
#define DEFAULT_UNANSWERED
Definition: cdr.c:291
void ast_cdr_engine_term(void)
Definition: cdr.c:4753
static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
Definition: cdr.c:1710
static struct aco_file module_file_conf
The file definition.
Definition: cdr.c:368
static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
Definition: cdr.c:1721
static char * handle_cli_submit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cdr.c:4364
static struct aco_type general_option
The type definition for general options.
Definition: cdr.c:334
static int cdr_master_cmp_fn(void *obj, void *arg, int flags)
Definition: cdr.c:960
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:3568
#define MAX_BATCH_TIME
Definition: cdr.c:302
static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Swap an old cdr_object_snapshot's ast_channel_snapshot for a new ast_channel_snapshot.
Definition: cdr.c:1635
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:798
static void handle_bridge_leave_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for when a channel leaves a bridge.
Definition: cdr.c:2538
#define cdr_set_debug_mode(mod_cfg)
Definition: cdr.c:306
static AO2_GLOBAL_OBJ_STATIC(module_configs)
The container for the module configuration.
int ast_cdr_backend_unsuspend(const char *name)
Unsuspend a CDR backend.
Definition: cdr.c:3017
static char * cli_complete_show(struct ast_cli_args *a)
Complete user input for 'cdr show'.
Definition: cdr.c:4118
static void cdr_object_check_party_a_hangup(struct cdr_object *cdr)
Check to see if a CDR needs to move to the finalized state because its Party A hungup.
Definition: cdr.c:1581
static void module_config_destructor(void *obj)
Dispose of a module config object.
Definition: cdr.c:393
static struct stasis_message_router * stasis_router
Message router for stasis messages regarding channel state.
Definition: cdr.c:475
static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Determine if we need to add a new CDR based on snapshots.
Definition: cdr.c:2372
static void handle_channel_snapshot_update_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for channel snapshot update messages.
Definition: cdr.c:2400
static int dial_status_end(const char *dialstatus)
Definition: cdr.c:2199
static int ast_cdr_generic_unregister(struct be_list *generic_list, const char *name)
Definition: cdr.c:3086
struct cdr_object_fn_table parked_state_fn_table
The virtual table for the Parked state.
Definition: cdr.c:782
static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:1749
static int cdr_toggle_runtime_options(void)
Checks if CDRs are enabled and enables/disables the necessary options.
Definition: cdr.c:4640
static void handle_bridge_enter_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: cdr.c:2843
static void handle_cdr_sync_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for a synchronization message.
Definition: cdr.c:2953
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:851
static int reload_module(void)
Definition: cdr.c:4793
static void finalize_batch_mode(void)
Definition: cdr.c:4429
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:314
int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
Fork a CDR.
Definition: cdr.c:3785
static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
Definition: cdr.c:1958
static void cdr_object_check_party_a_answer(struct cdr_object *cdr)
Check to see if a CDR needs to be answered based on its Party A. Note that this is safe to call as mu...
Definition: cdr.c:1598
static void set_variable(struct varshead *headp, const char *name, const char *value)
Definition: cdr.c:1364
static int filter_bridge_messages(struct ast_bridge_snapshot *bridge)
Filter bridge messages based on bridge technology.
Definition: cdr.c:2521
static int init_batch(void)
Definition: cdr.c:3886
static int submit_scheduled_batch(const void *data)
Definition: cdr.c:3952
static struct aco_type * general_options[]
Definition: cdr.c:378
static void start_batch_mode(void)
Definition: cdr.c:3973
static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:1644
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:3470
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:3121
static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
Copy a snapshot and its details.
Definition: cdr.c:896
static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
Format a variable on a cdr_object.
Definition: cdr.c:3364
static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, void *data, int flags)
Callback used to update the userfield on Party B on all CDRs.
Definition: cdr.c:3603
static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:1906
static void cdr_all_relink(struct cdr_object *cdr)
Definition: cdr.c:1053
static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
Definition: cdr.c:1920
static void handle_parking_bridge_enter_message(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel, const struct timeval *event_time)
Handle entering into a parking bridge.
Definition: cdr.c:2721
#define DEFAULT_INITIATED_SECONDS
Definition: cdr.c:294
static void cdr_master_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: cdr.c:4599
int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
Serializes all the data and variables for a current CDR record.
Definition: cdr.c:3499
static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:2125
static struct stasis_forward * parking_subscription
Our subscription for parking.
Definition: cdr.c:484
static void cdr_enable_batch_mode(struct ast_cdr_config *config)
Definition: cdr.c:4572
static long cdr_object_get_billsec(struct cdr_object *cdr)
Compute the billsec for a cdr_object.
Definition: cdr.c:1337
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:469
static int global_cdr_sequence
The global sequence counter used for CDRs.
Definition: cdr.c:453
#define DEFAULT_IGNORE_DIAL_CHANGES
Definition: cdr.c:297
static int cdr_all_cmp_fn(void *obj, void *arg, int flags)
Definition: cdr.c:1018
static void * do_batch_backend_process(void *data)
Definition: cdr.c:3897
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3576
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1229
static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
Return whether or not a ast_channel_snapshot is for a channel that was created as the result of a dia...
Definition: cdr.c:1281
static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
Set the disposition on a cdr_object based on a hangupcause code.
Definition: cdr.c:1506
static struct ao2_container * active_cdrs_all
A container of all active CDRs with a Party B indexed by Party B channel name.
Definition: cdr.c:472
static void bridge_candidate_add_to_cdr(struct cdr_object *cdr, struct cdr_object_snapshot *party_b)
Definition: cdr.c:2606
static struct stasis_topic * cdr_topic
The parent topic for all topics we want to aggregate for CDRs.
Definition: cdr.c:487
static char * handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cdr.c:4293
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:3076
static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Return whether or not a channel has changed its state in the dialplan, subject to endbeforehexten log...
Definition: cdr.c:1250
#define DEFAULT_BATCH_SAFE_SHUTDOWN
Definition: cdr.c:304
static void handle_dial_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for Stasis-Core dial messages.
Definition: cdr.c:2214
#define DEFAULT_BATCH_TIME
Definition: cdr.c:301
static int filter_channel_snapshot_message(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Definition: cdr.c:2183
static int load_module(void)
Definition: cdr.c:4674
static void cli_show_channel(struct ast_cli_args *a)
Definition: cdr.c:4203
static int cdr_object_get_by_name_cb(void *obj, void *arg, int flags)
Definition: cdr.c:3279
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3458
int ast_cdr_backend_suspend(const char *name)
Suspend a CDR backend temporarily.
Definition: cdr.c:2999
static void cdr_engine_shutdown(void)
Definition: cdr.c:4541
static ast_mutex_t cdr_pending_lock
These are used to wake up the CDR thread when there's work to do.
Definition: cdr.c:465
static void post_cdr(struct ast_cdr *cdr)
Definition: cdr.c:3656
static int unload_module(void)
Definition: cdr.c:4667
#define DEFAULT_BATCH_SCHEDULER_ONLY
Definition: cdr.c:303
static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1897
struct ast_cdr_config * ast_cdr_get_config(void)
Obtain the current CDR configuration.
Definition: cdr.c:2959
static enum process_bridge_enter_results dialed_pending_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:2086
#define DEFAULT_CHANNEL_ENABLED
Definition: cdr.c:295
#define DEFAULT_ENABLED
Definition: cdr.c:289
static void * module_config_alloc(void)
Create a new module config object.
Definition: cdr.c:404
static struct cdr_object_snapshot * cdr_object_pick_party_a(struct cdr_object_snapshot *left, struct cdr_object_snapshot *right)
Given two CDR snapshots, figure out who should be Party A for the resulting CDR.
Definition: cdr.c:1294
static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Set Caller ID information on a CDR.
Definition: cdr.c:1610
static void free_variables(struct varshead *headp)
Delete all variables from a variable list.
Definition: cdr.c:882
static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
Definition: cdr.c:1757
static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, void *data, int flags)
Callback used to notify CDRs of a Party B leaving the bridge.
Definition: cdr.c:2496
#define TITLE_STRING
static int cdr_master_hash_fn(const void *obj, const int flags)
Definition: cdr.c:936
static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:2142
static void destroy_subscriptions(void)
Destroy the active Stasis subscriptions.
Definition: cdr.c:4456
static void cdr_submit_batch(int shutdown)
Definition: cdr.c:3914
static void cdr_object_dtor(void *obj)
cdr_object Destructor
Definition: cdr.c:1101
static void module_config_post_apply(void)
Definition: cdr.c:380
static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2061
#define DEFAULT_END_BEFORE_H_EXTEN
Definition: cdr.c:293
static ast_mutex_t cdr_sched_lock
Definition: cdr.c:458
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:927
static int cdr_debug_enabled
Definition: cdr.c:311
static void handle_bridge_pairings(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge)
Handle creating bridge pairings for the cdr_object that just entered a bridge.
Definition: cdr.c:2695
struct ast_cdr * ast_cdr_dup(struct ast_cdr *cdr)
Duplicate a public CDR.
Definition: cdr.c:3131
static void * do_cdr(void *data)
Definition: cdr.c:4051
CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc,.files=ACO_FILES(&module_file_conf),.post_apply_config=module_config_post_apply,)
int ast_cdr_reset(const char *channel_name, int keep_variables)
Reset the detail record.
Definition: cdr.c:3746
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:3696
static enum process_bridge_enter_results dial_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1990
static enum process_bridge_enter_results single_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1840
Call Detail Record API.
@ CDR_UNANSWERED
Definition: cdr.h:222
@ CDR_IGNORE_STATE_CHANGES
Definition: cdr.h:228
@ CDR_CANCEL_DISPOSITION_ENABLED
Definition: cdr.h:230
@ CDR_INITIATED_SECONDS
Definition: cdr.h:225
@ CDR_ENABLED
Definition: cdr.h:220
@ CDR_CHANNEL_DEFAULT_ENABLED
Definition: cdr.h:227
@ CDR_END_BEFORE_H_EXTEN
Definition: cdr.h:224
@ CDR_IGNORE_DIAL_CHANGES
Definition: cdr.h:229
@ CDR_BATCHMODE
Definition: cdr.h:221
@ CDR_CONGESTION
Definition: cdr.h:223
@ BATCH_MODE_SAFE_SHUTDOWN
Definition: cdr.h:236
@ BATCH_MODE_SCHEDULER_ONLY
Definition: cdr.h:235
ast_cdr_disposition
CDR Flags - Disposition.
Definition: cdr.h:257
@ AST_CDR_CONGESTION
Definition: cdr.h:263
@ AST_CDR_NULL
Definition: cdr.h:259
@ AST_CDR_NOANSWER
Definition: cdr.h:258
@ AST_CDR_ANSWERED
Definition: cdr.h:262
@ AST_CDR_CANCEL
Definition: cdr.h:264
@ AST_CDR_BUSY
Definition: cdr.h:261
@ AST_CDR_FAILED
Definition: cdr.h:260
int(* ast_cdrbe)(struct ast_cdr *cdr)
CDR backend callback.
Definition: cdr.h:467
ast_cdr_options
CDR manipulation options. Certain function calls will manipulate the state of a CDR object based on t...
Definition: cdr.h:243
@ AST_CDR_FLAG_DISABLE_ALL
Definition: cdr.h:246
@ AST_CDR_LOCK_APP
Definition: cdr.h:251
@ AST_CDR_FLAG_FINALIZE
Definition: cdr.h:248
@ AST_CDR_FLAG_DISABLE
Definition: cdr.h:245
@ AST_CDR_FLAG_PARTY_A
Definition: cdr.h:247
@ AST_CDR_FLAG_KEEP_VARS
Definition: cdr.h:244
@ AST_CDR_FLAG_RESET
Definition: cdr.h:250
@ AST_CDR_FLAG_SET_ANSWER
Definition: cdr.h:249
static const char cdr_config[]
Definition: cdr_radius.c:86
static const char desc[]
Definition: cdr_radius.c:84
static struct cdr_tds_config * settings
Definition: cdr_tds.c:95
static PGresult * result
Definition: cel_pgsql.c:84
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2388
static const char config[]
Definition: chan_ooh323.c:111
General Asterisk PBX channel definitions.
@ AST_FLAG_OUTGOING
Definition: channel.h:1019
@ AST_FLAG_DEAD
Definition: channel.h:1065
@ AST_FLAG_SUBROUTINE_EXEC
Definition: channel.h:1078
@ AST_FLAG_ORIGINATED
Definition: channel.h:1059
#define AST_NUM_CHANNEL_BUCKETS
Definition: channel.h:157
@ AST_SOFTHANGUP_HANGUP_EXEC
Definition: channel.h:1174
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
Definition: channel.c:4340
#define AST_MAX_USER_FIELD
Definition: channel.h:176
@ AST_CHAN_TP_INTERNAL
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:991
@ AST_STATE_UP
Definition: channelstate.h:42
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
#define ast_var_assign(name, value)
Definition: chanvars.h:40
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2469
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2737
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ESS(x)
Definition: cli.h:59
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition: codec_g726.c:367
Configuration option-handling.
@ ACO_EXACT
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
@ ACO_PROCESS_ERROR
Their was an error and no changes were applied.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
#define ACO_FILES(...)
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_BOOLFLAG_T
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag.
@ ACO_GLOBAL
@ ACO_IGNORE
@ ACO_WHITELIST_ARRAY
@ ACO_WHITELIST_EXACT
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
char * be
Definition: eagi_proxy.c:73
char * end
Definition: eagi_proxy.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static const char name[]
Definition: format_mp3.c:68
struct stasis_topic * ast_parking_topic(void)
accessor for the parking stasis topic
Definition: parking.c:67
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
struct stasis_message_type * ast_channel_dial_type(void)
Message type for when a channel dials another channel.
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
struct ast_json * ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
Retrieve the JSON blob from a ast_multi_channel_blob. Returned ast_json is still owned by obj.
Configuration File Parser.
#define AST_LOG_WARNING
#define AST_LOG_ERROR
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
Asterisk JSON abstraction layer.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
A set of macros to manage forward-linked lists.
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:452
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
Definition: linkedlists.h:333
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:885
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:718
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:415
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 locking-related definitions:
#define ast_cond_destroy(cond)
Definition: lock.h:209
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:611
#define AST_PTHREADT_NULL
Definition: lock.h:73
#define ast_cond_init(cond, attr)
Definition: lock.h:208
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:213
#define ast_mutex_unlock(a)
Definition: lock.h:197
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:764
pthread_cond_t ast_cond_t
Definition: lock.h:185
#define ast_mutex_lock(a)
Definition: lock.h:196
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:527
#define ast_cond_signal(cond)
Definition: lock.h:210
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:331
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:330
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_CORE
Definition: module.h:338
@ 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_FAILURE
Module could not be loaded properly.
Definition: module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
Call Parking API.
@ PARKED_CALL
Definition: parking.h:47
static int total
Definition: res_adsi.c:970
static int reload(void)
struct stasis_forward * sub
Definition: res_corosync.c:240
#define NULL
Definition: resample.c:96
Scheduler Routines (derived from cheops)
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
long ast_sched_when(struct ast_sched_context *con, int id)
Returns the number of seconds before an event takes place.
Definition: sched.c:851
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:786
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Adds a scheduled event with rescheduling support.
Definition: sched.c:526
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:433
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition: stasis.c:1575
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition: stasis.c:644
#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.
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
Definition: stasis.c:1605
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
struct stasis_message_type * ast_channel_entered_bridge_type(void)
Message type for ast_channel enter bridge blob messages.
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
struct stasis_message_type * ast_channel_left_bridge_type(void)
Message type for ast_channel leave bridge blob messages.
int stasis_message_router_set_congestion_limits(struct stasis_message_router *router, long low_water, long high_water)
Set the high and low alert water marks of the stasis message router.
#define stasis_message_router_create(topic)
Create a new message router object.
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_unsubscribe_and_join(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic, blocking until the final message has been processed.
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.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:341
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:303
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1303
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
The representation of a single configuration file to be processed.
const char * filename
Type information about a category-level configurable object.
enum aco_type_t type
enum aco_category_op category_match
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Blob of data associated with a bridge.
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:318
const ast_string_field uniqueid
Definition: bridge.h:332
const ast_string_field technology
Definition: bridge.h:332
struct ao2_container * channels
Definition: bridge.h:335
const ast_string_field subclass
Definition: bridge.h:332
struct ast_flags settings
Definition: cdr.h:274
The global options available for CDRs.
Definition: cdr.h:269
struct ast_flags settings
Definition: cdr.h:270
struct ast_cdr_config::batch_settings batch_settings
Responsible for call detail data.
Definition: cdr.h:281
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:293
long int disposition
Definition: cdr.h:309
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:297
char linkedid[AST_MAX_UNIQUEID]
Definition: cdr.h:321
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:327
char peertenantid[AST_MAX_TENANT_ID]
Definition: cdr.h:325
long int billsec
Definition: cdr.h:307
struct timeval answer
Definition: cdr.h:301
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:291
char peeraccount[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:315
struct ast_cdr * next
Definition: cdr.h:334
long int duration
Definition: cdr.h:305
struct varshead varshead
Definition: cdr.h:332
long int amaflags
Definition: cdr.h:311
char src[AST_MAX_EXTENSION]
Definition: cdr.h:285
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:287
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:283
char uniqueid[AST_MAX_UNIQUEID]
Definition: cdr.h:319
char tenantid[AST_MAX_TENANT_ID]
Definition: cdr.h:323
int sequence
Definition: cdr.h:329
struct timeval start
Definition: cdr.h:299
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:313
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:295
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:289
struct timeval end
Definition: cdr.h:303
const ast_string_field tenantid
const ast_string_field accountcode
const ast_string_field uniqueid
const ast_string_field name
const ast_string_field dialed_subaddr
const ast_string_field number
const ast_string_field name
const ast_string_field subaddr
const ast_string_field dnid
const ast_string_field data
const ast_string_field context
const ast_string_field exten
const ast_string_field appl
Structure representing a change of snapshot of channel state.
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_dialplan * dialplan
struct ast_channel_snapshot_peer * peer
struct ast_channel_snapshot_bridge * bridge
struct ast_channel_snapshot_base * base
enum ast_channel_state state
struct ast_flags softhangup_flags
struct ast_channel_snapshot_caller * caller
struct ast_flags flags
struct ast_channel_snapshot_hangup * hangup
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Structure used to handle boolean flags.
Definition: utils.h:217
unsigned int flags
Definition: utils.h:218
Abstract JSON element (object, array, string, int, ...).
A multi channel blob data structure for multi_channel_blob stasis messages.
A parked call message payload.
Definition: parking.h:59
unsigned int parkingspace
Definition: parking.h:65
const ast_string_field parkinglot
Definition: parking.h:69
struct ast_channel_snapshot * parkee
Definition: parking.h:60
enum ast_parked_call_event_type event_type
Definition: parking.h:62
Support for dynamic strings.
Definition: strings.h:623
struct ast_var_t::@216 entries
List of registered backends.
Definition: cdr.c:434
const struct timeval * lastevent
Definition: cdr.c:2492
struct ast_bridge_snapshot * bridge
Definition: cdr.c:2490
struct ast_channel_snapshot * channel
Definition: cdr.c:2491
Queued CDR waiting to be batched.
Definition: cdr.c:440
struct ast_cdr * cdr
Definition: cdr.c:441
struct cdr_batch_item * next
Definition: cdr.c:442
The actual batch queue.
Definition: cdr.c:446
int size
Definition: cdr.c:447
struct cdr_batch_item * head
Definition: cdr.c:448
struct cdr_batch_item * tail
Definition: cdr.c:449
Registration object for CDR backends.
Definition: cdr.c:425
char name[20]
Definition: cdr.c:426
ast_cdrbe be
Definition: cdr.c:428
char desc[80]
Definition: cdr.c:427
A virtual table used for cdr_object.
Definition: cdr.c:520
int(*const process_party_a)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party A update for the cdr_object.
Definition: cdr.c:541
int(*const process_dial_end)(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
Process the end of a dial. At the end of a dial, a CDR can be transitioned into one of two states - D...
Definition: cdr.c:584
void(*const process_party_b)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party B update for the cdr_object.
Definition: cdr.c:550
enum process_bridge_enter_results(*const process_bridge_enter)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process the entering of a bridge by this CDR. The purpose of this callback is to have the CDR prepare...
Definition: cdr.c:607
int(*const process_dial_begin)(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
Process the beginning of a dial. A dial message implies one of two things: The cdr_object's Party A h...
Definition: cdr.c:566
int(*const process_bridge_leave)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process the leaving of a bridge by this CDR.
Definition: cdr.c:637
const char * name
Name of the subclass.
Definition: cdr.c:522
int(*const process_parking_bridge_enter)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process entering into a parking bridge.
Definition: cdr.c:623
void(*const init_function)(struct cdr_object *cdr)
An initialization function. This will be called automatically when a cdr_object is switched to this t...
Definition: cdr.c:531
int(*const process_parked_channel)(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
Process an update informing us that the channel got itself parked.
Definition: cdr.c:650
A wrapper object around a snapshot. Fields that are mutable by the CDR engine are replicated here.
Definition: cdr.c:808
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:810
struct varshead variables
Definition: cdr.c:812
struct ast_channel_snapshot * snapshot
Definition: cdr.c:809
unsigned int flags
Definition: cdr.c:811
An in-memory representation of an active CDR.
Definition: cdr.c:816
unsigned int sequence
Definition: cdr.c:826
struct cdr_object_fn_table * fn_table
Definition: cdr.c:819
const ast_string_field tenantid
Definition: cdr.c:839
enum ast_cdr_disposition disposition
Definition: cdr.c:821
const ast_string_field linkedid
Definition: cdr.c:839
struct cdr_object * next
Definition: cdr.c:840
const ast_string_field party_b_name
Definition: cdr.c:839
struct timeval answer
Definition: cdr.c:823
struct cdr_object_snapshot party_a
Definition: cdr.c:817
const ast_string_field uniqueid
Definition: cdr.c:839
struct timeval lastevent
Definition: cdr.c:825
struct cdr_object * last
Definition: cdr.c:841
const ast_string_field data
Definition: cdr.c:839
const ast_string_field context
Definition: cdr.c:839
const ast_string_field exten
Definition: cdr.c:839
int is_root
Definition: cdr.c:842
const ast_string_field name
Definition: cdr.c:839
struct timeval start
Definition: cdr.c:822
struct ast_flags flags
Definition: cdr.c:827
const ast_string_field bridge
Definition: cdr.c:839
struct timeval end
Definition: cdr.c:824
const ast_string_field appl
Definition: cdr.c:839
struct cdr_object_snapshot party_b
Definition: cdr.c:818
List of registered modifiers.
Definition: cdr.c:437
The configuration settings for this module.
Definition: cdr.c:326
struct ast_cdr_config * general
Definition: cdr.c:327
const char * userfield
Definition: cdr.c:3599
const char * channel_name
Definition: cdr.c:3598
Definition: sched.c:76
Forwarding information.
Definition: stasis.c:1558
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
An API for managing task processing threads that can be shared across modules.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:64
static struct test_options options
static struct test_val a
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2280
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
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:978
#define ast_assert(a)
Definition: utils.h:776
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:629
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:634
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ARRAY_LEN(a)
Definition: utils.h:703
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
#define AST_FLAGS_ALL
Definition: utils.h:214