2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
21 * \brief Call Detail Record API
23 * \author Mark Spencer <markster@digium.com>
25 * \note Includes code and algorithms from the Zapata library.
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.
33 /*! \li \ref cdr.c uses the configuration file \ref cdr.conf
34 * \addtogroup configuration_file Configuration Files
38 * \page cdr.conf cdr.conf
39 * \verbinclude cdr.conf.sample
43 <support_level>core</support_level>
48 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
53 #include "asterisk/lock.h"
54 #include "asterisk/channel.h"
55 #include "asterisk/cdr.h"
56 #include "asterisk/callerid.h"
57 #include "asterisk/manager.h"
58 #include "asterisk/causes.h"
59 #include "asterisk/linkedlists.h"
60 #include "asterisk/utils.h"
61 #include "asterisk/sched.h"
62 #include "asterisk/config.h"
63 #include "asterisk/cli.h"
64 #include "asterisk/stringfields.h"
65 #include "asterisk/data.h"
66 #include "asterisk/config_options.h"
67 #include "asterisk/json.h"
68 #include "asterisk/parking.h"
69 #include "asterisk/stasis.h"
70 #include "asterisk/stasis_channels.h"
71 #include "asterisk/stasis_bridges.h"
72 #include "asterisk/stasis_message_router.h"
73 #include "asterisk/astobj2.h"
76 <configInfo name="cdr" language="en_US">
77 <synopsis>Call Detail Record configuration</synopsis>
79 <para>CDR is Call Detail Record, which provides logging services via a variety of
80 pluggable backend modules. Detailed call information can be recorded to
81 databases, files, etc. Useful for billing, fraud prevention, compliance with
82 Sarbanes-Oxley aka The Enron Act, QOS evaluations, and more.</para>
84 <configFile name="cdr.conf">
85 <configObject name="general">
86 <synopsis>Global settings applied to the CDR engine.</synopsis>
87 <configOption name="debug">
88 <synopsis>Enable/disable verbose CDR debugging.</synopsis>
89 <description><para>When set to <literal>True</literal>, verbose updates
90 of changes in CDR information will be logged. Note that this is only
91 of use when debugging CDR behavior.</para>
94 <configOption name="enable">
95 <synopsis>Enable/disable CDR logging.</synopsis>
96 <description><para>Define whether or not to use CDR logging. Setting this to "no" will override
97 any loading of backend CDR modules. Default is "yes".</para>
100 <configOption name="unanswered">
101 <synopsis>Log calls that are never answered.</synopsis>
102 <description><para>Define whether or not to log unanswered calls. Setting this to "yes" will
103 report every attempt to ring a phone in dialing attempts, when it was not
104 answered. For example, if you try to dial 3 extensions, and this option is "yes",
105 you will get 3 CDR's, one for each phone that was rung. Some find this information horribly
106 useless. Others find it very valuable. Note, in "yes" mode, you will see one CDR, with one of
107 the call targets on one side, and the originating channel on the other, and then one CDR for
108 each channel attempted. This may seem redundant, but cannot be helped.</para>
109 <para>In brief, this option controls the reporting of unanswered calls which only have an A
110 party. Calls which get offered to an outgoing line, but are unanswered, are still
111 logged, and that is the intended behavior. (It also results in some B side CDRs being
112 output, as they have the B side channel as their source channel, and no destination
116 <configOption name="congestion">
117 <synopsis>Log congested calls.</synopsis>
118 <description><para>Define whether or not to log congested calls. Setting this to "yes" will
119 report each call that fails to complete due to congestion conditions.</para>
122 <configOption name="endbeforehexten">
123 <synopsis>Don't produce CDRs while executing hangup logic</synopsis>
125 <para>As each CDR for a channel is finished, its end time is updated
126 and the CDR is finalized. When a channel is hung up and hangup
127 logic is present (in the form of a hangup handler or the
128 <literal>h</literal> extension), a new CDR is generated for the
129 channel. Any statistics are gathered from this new CDR. By enabling
130 this option, no new CDR is created for the dialplan logic that is
131 executed in <literal>h</literal> extensions or attached hangup handler
132 subroutines. The default value is <literal>no</literal>, indicating
133 that a CDR will be generated during hangup logic.</para>
136 <configOption name="initiatedseconds">
137 <synopsis>Count microseconds for billsec purposes</synopsis>
138 <description><para>Normally, the <literal>billsec</literal> field logged to the CDR backends
139 is simply the end time (hangup time) minus the answer time in seconds. Internally,
140 asterisk stores the time in terms of microseconds and seconds. By setting
141 initiatedseconds to <literal>yes</literal>, you can force asterisk to report any seconds
142 that were initiated (a sort of round up method). Technically, this is
143 when the microsecond part of the end time is greater than the microsecond
144 part of the answer time, then the billsec time is incremented one second.</para>
147 <configOption name="batch">
148 <synopsis>Submit CDRs to the backends for processing in batches</synopsis>
149 <description><para>Define the CDR batch mode, where instead of posting the CDR at the end of
150 every call, the data will be stored in a buffer to help alleviate load on the
151 asterisk server.</para>
152 <warning><para>Use of batch mode may result in data loss after unsafe asterisk termination,
153 i.e., software crash, power failure, kill -9, etc.</para>
157 <configOption name="size">
158 <synopsis>The maximum number of CDRs to accumulate before triggering a batch</synopsis>
159 <description><para>Define the maximum number of CDRs to accumulate in the buffer before posting
160 them to the backend engines. batch must be set to <literal>yes</literal>.</para>
163 <configOption name="time">
164 <synopsis>The maximum time to accumulate CDRs before triggering a batch</synopsis>
165 <description><para>Define the maximum time to accumulate CDRs before posting them in a batch to the
166 backend engines. If this time limit is reached, then it will post the records, regardless of the value
167 defined for size. batch must be set to <literal>yes</literal>.</para>
168 <note><para>Time is expressed in seconds.</para></note>
171 <configOption name="scheduleronly">
172 <synopsis>Post batched CDRs on their own thread instead of the scheduler</synopsis>
173 <description><para>The CDR engine uses the internal asterisk scheduler to determine when to post
174 records. Posting can either occur inside the scheduler thread, or a new
175 thread can be spawned for the submission of every batch. For small batches,
176 it might be acceptable to just use the scheduler thread, so set this to <literal>yes</literal>.
177 For large batches, say anything over size=10, a new thread is recommended, so
178 set this to <literal>no</literal>.</para>
181 <configOption name="safeshutdown">
182 <synopsis>Block shutdown of Asterisk until CDRs are submitted</synopsis>
183 <description><para>When shutting down asterisk, you can block until the CDRs are submitted. If
184 you don't, then data will likely be lost. You can always check the size of
185 the CDR batch buffer with the CLI <astcli>cdr status</astcli> command. To enable blocking on
186 submission of CDR data during asterisk shutdown, set this to <literal>yes</literal>.</para>
195 #define DEFAULT_ENABLED "1"
196 #define DEFAULT_BATCHMODE "0"
197 #define DEFAULT_UNANSWERED "0"
198 #define DEFAULT_CONGESTION "0"
199 #define DEFAULT_END_BEFORE_H_EXTEN "0"
200 #define DEFAULT_INITIATED_SECONDS "0"
202 #define DEFAULT_BATCH_SIZE "100"
203 #define MAX_BATCH_SIZE 1000
204 #define DEFAULT_BATCH_TIME "300"
205 #define MAX_BATCH_TIME 86400
206 #define DEFAULT_BATCH_SCHEDULER_ONLY "0"
207 #define DEFAULT_BATCH_SAFE_SHUTDOWN "1"
209 #define CDR_DEBUG(mod_cfg, fmt, ...) \
211 if (ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG)) { \
212 ast_verb(1, (fmt), ##__VA_ARGS__); \
215 static void cdr_detach(struct ast_cdr *cdr);
216 static void cdr_submit_batch(int shutdown);
218 /*! \brief The configuration settings for this module */
219 struct module_config {
220 struct ast_cdr_config *general; /*< CDR global settings */
223 /*! \brief The container for the module configuration */
224 static AO2_GLOBAL_OBJ_STATIC(module_configs);
226 /*! \brief The type definition for general options */
227 static struct aco_type general_option = {
230 .item_offset = offsetof(struct module_config, general),
231 .category = "^general$",
232 .category_match = ACO_WHITELIST,
235 static void *module_config_alloc(void);
236 static void module_config_destructor(void *obj);
238 /*! \brief The file definition */
239 static struct aco_file module_file_conf = {
240 .filename = "cdr.conf",
241 .skip_category = "(^csv$|^custom$|^manager$|^odbc$|^pgsql$|^radius$|^sqlite$|^tds$|^mysql$)",
242 .types = ACO_TYPES(&general_option),
245 CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc,
246 .files = ACO_FILES(&module_file_conf),
249 static struct aco_type *general_options[] = ACO_TYPES(&general_option);
251 /*! \brief Dispose of a module config object */
252 static void module_config_destructor(void *obj)
254 struct module_config *cfg = obj;
259 ao2_ref(cfg->general, -1);
262 /*! \brief Create a new module config object */
263 static void *module_config_alloc(void)
265 struct module_config *mod_cfg;
266 struct ast_cdr_config *cdr_config;
268 mod_cfg = ao2_alloc(sizeof(*mod_cfg), module_config_destructor);
273 cdr_config = ao2_alloc(sizeof(*cdr_config), NULL);
275 ao2_ref(cdr_config, -1);
278 mod_cfg->general = cdr_config;
283 /*! \brief Registration object for CDR backends */
288 AST_RWLIST_ENTRY(cdr_beitem) list;
291 /*! \brief List of registered backends */
292 static AST_RWLIST_HEAD_STATIC(be_list, cdr_beitem);
294 /*! \brief Queued CDR waiting to be batched */
295 struct cdr_batch_item {
297 struct cdr_batch_item *next;
300 /*! \brief The actual batch queue */
301 static struct cdr_batch {
303 struct cdr_batch_item *head;
304 struct cdr_batch_item *tail;
307 /*! \brief The global sequence counter used for CDRs */
308 static int global_cdr_sequence = 0;
310 /*! \brief Scheduler items */
311 static struct ast_sched_context *sched;
312 static int cdr_sched = -1;
313 AST_MUTEX_DEFINE_STATIC(cdr_sched_lock);
314 static pthread_t cdr_thread = AST_PTHREADT_NULL;
316 /*! \brief Lock protecting modifications to the batch queue */
317 AST_MUTEX_DEFINE_STATIC(cdr_batch_lock);
319 /*! \brief These are used to wake up the CDR thread when there's work to do */
320 AST_MUTEX_DEFINE_STATIC(cdr_pending_lock);
321 static ast_cond_t cdr_pending_cond;
323 /*! \brief A container of the active CDRs indexed by Party A channel name */
324 static struct ao2_container *active_cdrs_by_channel;
326 /*! \brief Message router for stasis messages regarding channel state */
327 static struct stasis_message_router *stasis_router;
329 /*! \brief Our subscription for bridges */
330 static struct stasis_subscription *bridge_subscription;
332 /*! \brief Our subscription for channels */
333 static struct stasis_subscription *channel_subscription;
335 /*! \brief Our subscription for parking */
336 static struct stasis_subscription *parking_subscription;
338 /*! \brief The parent topic for all topics we want to aggregate for CDRs */
339 static struct stasis_topic *cdr_topic;
343 /*! \brief Return types for \ref process_bridge_enter functions */
344 enum process_bridge_enter_results {
346 * The CDR was the only party in the bridge.
348 BRIDGE_ENTER_ONLY_PARTY,
350 * The CDR was able to obtain a Party B from some other party already in the bridge
352 BRIDGE_ENTER_OBTAINED_PARTY_B,
354 * The CDR was not able to obtain a Party B
356 BRIDGE_ENTER_NO_PARTY_B,
358 * This CDR can't handle a bridge enter message and a new CDR needs to be created
360 BRIDGE_ENTER_NEED_CDR,
364 * \brief A virtual table used for \ref cdr_object.
366 * Note that all functions are optional - if a subclass does not need an
367 * implementation, it is safe to leave it NULL.
369 struct cdr_object_fn_table {
370 /*! \brief Name of the subclass */
374 * \brief An initialization function. This will be called automatically
375 * when a \ref cdr_object is switched to this type in
376 * \ref cdr_object_transition_state
378 * \param cdr The \ref cdr_object that was just transitioned
380 void (* const init_function)(struct cdr_object *cdr);
383 * \brief Process a Party A update for the \ref cdr_object
385 * \param cdr The \ref cdr_object to process the update
386 * \param snapshot The snapshot for the CDR's Party A
387 * \retval 0 the CDR handled the update or ignored it
388 * \retval 1 the CDR is finalized and a new one should be made to handle it
390 int (* const process_party_a)(struct cdr_object *cdr,
391 struct ast_channel_snapshot *snapshot);
394 * \brief Process a Party B update for the \ref cdr_object
396 * \param cdr The \ref cdr_object to process the update
397 * \param snapshot The snapshot for the CDR's Party B
399 void (* const process_party_b)(struct cdr_object *cdr,
400 struct ast_channel_snapshot *snapshot);
403 * \brief Process the beginning of a dial. A dial message implies one of two
405 * The \ref cdr_object's Party A has been originated
406 * The \ref cdr_object's Party A is dialing its Party B
408 * \param cdr The \ref cdr_object
409 * \param caller The originator of the dial attempt
410 * \param peer The destination of the dial attempt
412 * \retval 0 if the parties in the dial were handled by this CDR
413 * \retval 1 if the parties could not be handled by this CDR
415 int (* const process_dial_begin)(struct cdr_object *cdr,
416 struct ast_channel_snapshot *caller,
417 struct ast_channel_snapshot *peer);
420 * \brief Process the end of a dial. At the end of a dial, a CDR can be
421 * transitioned into one of two states - DialedPending
422 * (\ref dialed_pending_state_fn_table) or Finalized
423 * (\ref finalized_state_fn_table).
425 * \param cdr The \ref cdr_object
426 * \param caller The originator of the dial attempt
427 * \param peer the Destination of the dial attempt
428 * \param dial_status What happened
430 * \retval 0 if the parties in the dial were handled by this CDR
431 * \retval 1 if the parties could not be handled by this CDR
433 int (* const process_dial_end)(struct cdr_object *cdr,
434 struct ast_channel_snapshot *caller,
435 struct ast_channel_snapshot *peer,
436 const char *dial_status);
439 * \brief Process the entering of a bridge by this CDR. The purpose of this
440 * callback is to have the CDR prepare itself for the bridge and attempt to
441 * find a valid Party B. The act of creating new CDRs based on the entering
442 * of this channel into the bridge is handled by the higher level message
445 * Note that this handler is for when a channel enters into a "normal"
446 * bridge, where people actually talk to each other. Parking is its own
449 * \param cdr The \ref cdr_object
450 * \param bridge The bridge that the Party A just entered into
451 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
453 * \retval process_bridge_enter_results Defines whether or not this CDR was able
454 * to fully handle the bridge enter message.
456 enum process_bridge_enter_results (* const process_bridge_enter)(
457 struct cdr_object *cdr,
458 struct ast_bridge_snapshot *bridge,
459 struct ast_channel_snapshot *channel);
462 * \brief Process entering into a parking bridge.
464 * \param cdr The \ref cdr_object
465 * \param bridge The parking bridge that Party A just entered into
466 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
468 * \retval 0 This CDR successfully transitioned itself into the parked state
469 * \retval 1 This CDR couldn't handle the parking transition and we need a
472 int (* const process_parking_bridge_enter)(struct cdr_object *cdr,
473 struct ast_bridge_snapshot *bridge,
474 struct ast_channel_snapshot *channel);
477 * \brief Process the leaving of a bridge by this CDR.
479 * \param cdr The \ref cdr_object
480 * \param bridge The bridge that the Party A just left
481 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
483 * \retval 0 This CDR left successfully
486 int (* const process_bridge_leave)(struct cdr_object *cdr,
487 struct ast_bridge_snapshot *bridge,
488 struct ast_channel_snapshot *channel);
491 * \brief Process an update informing us that the channel got itself parked
493 * \param cdr The \ref cdr_object
494 * \param channel The parking information for this CDR's party A
496 * \retval 0 This CDR successfully parked itself
497 * \retval 1 This CDR couldn't handle the park
499 int (* const process_parked_channel)(struct cdr_object *cdr,
500 struct ast_parked_call_payload *parking_info);
503 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
504 static enum process_bridge_enter_results base_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
505 static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
506 static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
507 static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info);
509 static void single_state_init_function(struct cdr_object *cdr);
510 static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
511 static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
512 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);
513 static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
516 * \brief The virtual table for the Single state.
518 * A \ref cdr_object starts off in this state. This represents a channel that
519 * has no Party B information itself.
521 * A \ref cdr_object from this state can go into any of the following states:
522 * * \ref dial_state_fn_table
523 * * \ref bridge_state_fn_table
524 * * \ref finalized_state_fn_table
526 struct cdr_object_fn_table single_state_fn_table = {
528 .init_function = single_state_init_function,
529 .process_party_a = base_process_party_a,
530 .process_party_b = single_state_process_party_b,
531 .process_dial_begin = single_state_process_dial_begin,
532 .process_dial_end = base_process_dial_end,
533 .process_bridge_enter = single_state_process_bridge_enter,
534 .process_parking_bridge_enter = single_state_process_parking_bridge_enter,
535 .process_bridge_leave = base_process_bridge_leave,
536 .process_parked_channel = base_process_parked_channel,
539 static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
540 static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
541 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);
542 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);
545 * \brief The virtual table for the Dial state.
547 * A \ref cdr_object that has begun a dial operation. This state is entered when
548 * the Party A for a CDR is determined to be dialing out to a Party B or when
549 * a CDR is for an originated channel (in which case the Party A information is
550 * the originated channel, and there is no Party B).
552 * A \ref cdr_object from this state can go in any of the following states:
553 * * \ref dialed_pending_state_fn_table
554 * * \ref bridge_state_fn_table
555 * * \ref finalized_state_fn_table
557 struct cdr_object_fn_table dial_state_fn_table = {
559 .process_party_a = base_process_party_a,
560 .process_party_b = dial_state_process_party_b,
561 .process_dial_begin = dial_state_process_dial_begin,
562 .process_dial_end = dial_state_process_dial_end,
563 .process_bridge_enter = dial_state_process_bridge_enter,
564 .process_bridge_leave = base_process_bridge_leave,
567 static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
568 static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
569 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);
570 static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
573 * \brief The virtual table for the Dialed Pending state.
575 * A \ref cdr_object that has successfully finished a dial operation, but we
576 * don't know what they're going to do yet. It's theoretically possible to dial
577 * a party and then have that party not be bridged with the caller; likewise,
578 * an origination can complete and the channel go off and execute dialplan. The
579 * pending state acts as a bridge between either:
580 * * Entering a bridge
581 * * Getting a new CDR for new dialplan execution
582 * * Switching from being originated to executing dialplan
584 * A \ref cdr_object from this state can go in any of the following states:
585 * * \ref single_state_fn_table
586 * * \ref dialed_pending_state_fn_table
587 * * \ref bridge_state_fn_table
588 * * \ref finalized_state_fn_table
590 struct cdr_object_fn_table dialed_pending_state_fn_table = {
591 .name = "DialedPending",
592 .process_party_a = dialed_pending_state_process_party_a,
593 .process_dial_begin = dialed_pending_state_process_dial_begin,
594 .process_bridge_enter = dialed_pending_state_process_bridge_enter,
595 .process_parking_bridge_enter = dialed_pending_state_process_parking_bridge_enter,
596 .process_bridge_leave = base_process_bridge_leave,
597 .process_parked_channel = base_process_parked_channel,
600 static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
601 static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
604 * \brief The virtual table for the Bridged state
606 * A \ref cdr_object enters this state when it receives notification that the
607 * channel has entered a bridge.
609 * A \ref cdr_object from this state can go to:
610 * * \ref finalized_state_fn_table
612 struct cdr_object_fn_table bridge_state_fn_table = {
614 .process_party_a = base_process_party_a,
615 .process_party_b = bridge_state_process_party_b,
616 .process_bridge_leave = bridge_state_process_bridge_leave,
617 .process_parked_channel = base_process_parked_channel,
620 static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
623 * \brief The virtual table for the Parked state
625 * Parking is weird. Unlike typical bridges, it has to be treated somewhat
626 * uniquely - a channel in a parking bridge (which is a subclass of a holding
627 * bridge) has to be handled as if the channel went into an application.
628 * However, when the channel comes out, we need a new CDR - unlike the Single
631 struct cdr_object_fn_table parked_state_fn_table = {
633 .process_party_a = base_process_party_a,
634 .process_bridge_leave = parked_state_process_bridge_leave,
635 .process_parked_channel = base_process_parked_channel,
638 static void finalized_state_init_function(struct cdr_object *cdr);
639 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
642 * \brief The virtual table for the finalized state.
644 * Once in the finalized state, the CDR is done. No modifications can be made
647 struct cdr_object_fn_table finalized_state_fn_table = {
649 .init_function = finalized_state_init_function,
650 .process_party_a = finalized_state_process_party_a,
651 .process_bridge_enter = base_process_bridge_enter,
654 /*! \brief A wrapper object around a snapshot.
655 * Fields that are mutable by the CDR engine are replicated here.
657 struct cdr_object_snapshot {
658 struct ast_channel_snapshot *snapshot; /*!< The channel snapshot */
659 char userfield[AST_MAX_USER_FIELD]; /*!< Userfield for the channel */
660 unsigned int flags; /*!< Specific flags for this party */
661 struct varshead variables; /*!< CDR variables for the channel */
664 /*! \brief An in-memory representation of an active CDR */
666 struct cdr_object_snapshot party_a; /*!< The Party A information */
667 struct cdr_object_snapshot party_b; /*!< The Party B information */
668 struct cdr_object_fn_table *fn_table; /*!< The current virtual table */
670 enum ast_cdr_disposition disposition; /*!< The disposition of the CDR */
671 struct timeval start; /*!< When this CDR was created */
672 struct timeval answer; /*!< Either when the channel was answered, or when the path between channels was established */
673 struct timeval end; /*!< When this CDR was finalized */
674 unsigned int sequence; /*!< A monotonically increasing number for each CDR */
675 struct ast_flags flags; /*!< Flags on the CDR */
676 AST_DECLARE_STRING_FIELDS(
677 AST_STRING_FIELD(linkedid); /*!< Linked ID. Cached here as it may change out from party A, which must be immutable */
678 AST_STRING_FIELD(name); /*!< Channel name of party A. Cached here as the party A address may change */
679 AST_STRING_FIELD(bridge); /*!< The bridge the party A happens to be in. */
680 AST_STRING_FIELD(appl); /*!< The last accepted application party A was in */
681 AST_STRING_FIELD(data); /*!< The data for the last accepted application party A was in */
683 struct cdr_object *next; /*!< The next CDR object in the chain */
684 struct cdr_object *last; /*!< The last CDR object in the chain */
688 * \brief Copy variables from one list to another
689 * \param to_list destination
690 * \param from_list source
691 * \retval The number of copied variables
693 static int copy_variables(struct varshead *to_list, struct varshead *from_list)
695 struct ast_var_t *variables, *newvariable = NULL;
696 const char *var, *val;
699 AST_LIST_TRAVERSE(from_list, variables, entries) {
701 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
702 !ast_strlen_zero(var) && !ast_strlen_zero(val) &&
703 (newvariable = ast_var_assign(var, val))) {
704 AST_LIST_INSERT_HEAD(to_list, newvariable, entries);
713 * \brief Delete all variables from a variable list
714 * \param headp The head pointer to the variable list to delete
716 static void free_variables(struct varshead *headp)
718 struct ast_var_t *vardata;
720 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
721 ast_var_delete(vardata);
726 * \brief Copy a snapshot and its details
727 * \param dst The destination
728 * \param src The source
730 static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
733 ao2_t_ref(dst->snapshot, -1, "release old snapshot during copy");
735 dst->snapshot = src->snapshot;
736 ao2_t_ref(dst->snapshot, +1, "bump new snapshot during copy");
737 strcpy(dst->userfield, src->userfield);
738 dst->flags = src->flags;
739 copy_variables(&dst->variables, &src->variables);
743 * \brief Transition a \ref cdr_object to a new state
744 * \param cdr The \ref cdr_object to transition
745 * \param fn_table The \ref cdr_object_fn_table state to go to
747 static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
749 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
751 CDR_DEBUG(mod_cfg, "%p - Transitioning CDR for %s from state %s to %s\n",
752 cdr, cdr->party_a.snapshot->name,
753 cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
754 cdr->fn_table = fn_table;
755 if (cdr->fn_table->init_function) {
756 cdr->fn_table->init_function(cdr);
760 * \brief Hash function for containers of CDRs indexing by Party A name */
761 static int cdr_object_channel_hash_fn(const void *obj, const int flags)
763 const struct cdr_object *cdr = obj;
764 const char *name = (flags & OBJ_KEY) ? obj : cdr->name;
765 return ast_str_case_hash(name);
769 * \brief Comparison function for containers of CDRs indexing by Party A name
771 static int cdr_object_channel_cmp_fn(void *obj, void *arg, int flags)
773 struct cdr_object *left = obj;
774 struct cdr_object *right = arg;
775 const char *match = (flags & OBJ_KEY) ? arg : right->name;
776 return strcasecmp(left->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
780 * \brief Comparison function for containers of CDRs indexing by bridge. Note
781 * that we expect there to be collisions, as a single bridge may have multiple
782 * CDRs active at one point in time
784 static int cdr_object_bridge_cmp_fn(void *obj, void *arg, int flags)
786 struct cdr_object *left = obj;
787 struct cdr_object *it_cdr;
788 const char *match = arg;
790 for (it_cdr = left; it_cdr; it_cdr = it_cdr->next) {
791 if (!strcasecmp(it_cdr->bridge, match)) {
799 * \brief \ref cdr_object Destructor
801 static void cdr_object_dtor(void *obj)
803 struct cdr_object *cdr = obj;
804 struct ast_var_t *it_var;
810 ao2_cleanup(cdr->party_a.snapshot);
811 ao2_cleanup(cdr->party_b.snapshot);
812 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_a.variables, entries))) {
813 ast_var_delete(it_var);
815 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_b.variables, entries))) {
816 ast_var_delete(it_var);
818 ast_string_field_free_memory(cdr);
821 ao2_cleanup(cdr->next);
826 * \brief \ref cdr_object constructor
827 * \param chan The \ref ast_channel_snapshot that is the CDR's Party A
829 * This implicitly sets the state of the newly created CDR to the Single state
830 * (\ref single_state_fn_table)
832 static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan)
834 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
835 struct cdr_object *cdr;
837 ast_assert(chan != NULL);
839 cdr = ao2_alloc(sizeof(*cdr), cdr_object_dtor);
844 if (ast_string_field_init(cdr, 64)) {
847 ast_string_field_set(cdr, name, chan->name);
848 ast_string_field_set(cdr, linkedid, chan->linkedid);
849 cdr->disposition = AST_CDR_NULL;
850 cdr->sequence = ast_atomic_fetchadd_int(&global_cdr_sequence, +1);
852 cdr->party_a.snapshot = chan;
853 ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
855 CDR_DEBUG(mod_cfg, "%p - Created CDR for channel %s\n", cdr, chan->name);
857 cdr_object_transition_state(cdr, &single_state_fn_table);
863 * \brief Create a new \ref cdr_object and append it to an existing chain
864 * \param cdr The \ref cdr_object to append to
866 static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr)
868 struct cdr_object *new_cdr;
869 struct cdr_object *it_cdr;
870 struct cdr_object *cdr_last;
872 cdr_last = cdr->last;
873 new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot);
877 new_cdr->disposition = AST_CDR_NULL;
879 /* Copy over the linkedid, as it may have changed */
880 ast_string_field_set(new_cdr, linkedid, cdr_last->linkedid);
881 ast_string_field_set(new_cdr, appl, cdr_last->appl);
882 ast_string_field_set(new_cdr, data, cdr_last->data);
884 /* Copy over other Party A information */
885 cdr_object_snapshot_copy(&new_cdr->party_a, &cdr_last->party_a);
887 /* Append the CDR to the end of the list */
888 for (it_cdr = cdr; it_cdr->next; it_cdr = it_cdr->next) {
889 it_cdr->last = new_cdr;
891 it_cdr->last = new_cdr;
892 it_cdr->next = new_cdr;
898 * \brief Return whether or not a channel has changed its state in the dialplan, subject
899 * to endbeforehexten logic
901 * \param old_snapshot The previous state
902 * \param new_snapshot The new state
904 * \retval 0 if the state has not changed
905 * \retval 1 if the state changed
907 static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
908 struct ast_channel_snapshot *new_snapshot)
910 RAII_VAR(struct module_config *, mod_cfg,
911 ao2_global_obj_ref(module_configs), ao2_cleanup);
913 /* If we ignore hangup logic, don't indicate that we're executing anything new */
914 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
915 && ast_test_flag(&new_snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
919 /* When Party A is originated to an application and the application exits, the stack
920 * will attempt to clear the application and restore the dummy originate application
921 * of "AppDialX". Ignore application changes to AppDialX as a result.
923 if (strcmp(new_snapshot->appl, old_snapshot->appl) && strncasecmp(new_snapshot->appl, "appdial", 7)
924 && (strcmp(new_snapshot->context, old_snapshot->context)
925 || strcmp(new_snapshot->exten, old_snapshot->exten)
926 || new_snapshot->priority != old_snapshot->priority)) {
934 * \brief Return whether or not a \ref ast_channel_snapshot is for a channel
935 * that was created as the result of a dial operation
937 * \retval 0 the channel was not created as the result of a dial
938 * \retval 1 the channel was created as the result of a dial
940 static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
942 return (ast_test_flag(&snapshot->flags, AST_FLAG_OUTGOING)
943 && !(ast_test_flag(&snapshot->flags, AST_FLAG_ORIGINATED)));
947 * \brief Given two CDR snapshots, figure out who should be Party A for the
949 * \param left One of the snapshots
950 * \param right The other snapshot
951 * \retval The snapshot that won
953 static struct cdr_object_snapshot *cdr_object_pick_party_a(struct cdr_object_snapshot *left, struct cdr_object_snapshot *right)
955 /* Check whether or not the party is dialed. A dialed party is never the
956 * Party A with a party that was not dialed.
958 if (!snapshot_is_dialed(left->snapshot) && snapshot_is_dialed(right->snapshot)) {
960 } else if (snapshot_is_dialed(left->snapshot) && !snapshot_is_dialed(right->snapshot)) {
964 /* Try the Party A flag */
965 if (ast_test_flag(left, AST_CDR_FLAG_PARTY_A) && !ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
967 } else if (!ast_test_flag(right, AST_CDR_FLAG_PARTY_A) && ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
971 /* Neither party is dialed and neither has the Party A flag - defer to
973 if (left->snapshot->creationtime.tv_sec < right->snapshot->creationtime.tv_sec) {
975 } else if (left->snapshot->creationtime.tv_sec > right->snapshot->creationtime.tv_sec) {
977 } else if (left->snapshot->creationtime.tv_usec > right->snapshot->creationtime.tv_usec) {
980 /* Okay, fine, take the left one */
986 * Compute the duration for a \ref cdr_object
988 static long cdr_object_get_duration(struct cdr_object *cdr)
990 return (long)(ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->start) / 1000);
994 * \brief Compute the billsec for a \ref cdr_object
996 static long cdr_object_get_billsec(struct cdr_object *cdr)
998 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1001 if (ast_tvzero(cdr->answer)) {
1004 ms = ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->answer);
1005 if (ast_test_flag(&mod_cfg->general->settings, CDR_INITIATED_SECONDS)
1006 && (ms % 1000 >= 500)) {
1007 ms = (ms / 1000) + 1;
1017 * \brief Set a variable on a CDR object
1019 * \param headp The header pointer to the variable to set
1020 * \param name The name of the variable
1021 * \param value The value of the variable
1023 static void set_variable(struct varshead *headp, const char *name, const char *value)
1025 struct ast_var_t *newvariable;
1027 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1028 if (!strcasecmp(ast_var_name(newvariable), name)) {
1029 AST_LIST_REMOVE_CURRENT(entries);
1030 ast_var_delete(newvariable);
1034 AST_LIST_TRAVERSE_SAFE_END;
1036 if (value && (newvariable = ast_var_assign(name, value))) {
1037 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1042 * \brief Create a chain of \ref ast_cdr objects from a chain of \ref cdr_object
1043 * suitable for consumption by the registered CDR backends
1044 * \param cdr The \ref cdr_object to convert to a public record
1045 * \retval A chain of \ref ast_cdr objects on success
1046 * \retval NULL on failure
1048 static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr)
1050 struct ast_cdr *pub_cdr = NULL, *cdr_prev = NULL;
1051 struct cdr_object *it_cdr;
1052 struct ast_var_t *it_var, *it_copy_var;
1053 struct ast_channel_snapshot *party_a;
1054 struct ast_channel_snapshot *party_b;
1056 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1057 struct ast_cdr *cdr_copy;
1059 /* Don't create records for CDRs where the party A was a dialed channel */
1060 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
1064 cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
1070 party_a = it_cdr->party_a.snapshot;
1071 party_b = it_cdr->party_b.snapshot;
1074 ast_assert(party_a != NULL);
1075 ast_copy_string(cdr_copy->accountcode, party_a->accountcode, sizeof(cdr_copy->accountcode));
1076 cdr_copy->amaflags = party_a->amaflags;
1077 ast_copy_string(cdr_copy->channel, party_a->name, sizeof(cdr_copy->channel));
1078 ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller_name, party_a->caller_number, "");
1079 ast_copy_string(cdr_copy->src, party_a->caller_number, sizeof(cdr_copy->src));
1080 ast_copy_string(cdr_copy->uniqueid, party_a->uniqueid, sizeof(cdr_copy->uniqueid));
1081 ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
1082 ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
1083 ast_copy_string(cdr_copy->dst, party_a->exten, sizeof(cdr_copy->dst));
1084 ast_copy_string(cdr_copy->dcontext, party_a->context, sizeof(cdr_copy->dcontext));
1088 ast_copy_string(cdr_copy->dstchannel, party_b->name, sizeof(cdr_copy->dstchannel));
1089 ast_copy_string(cdr_copy->peeraccount, party_b->accountcode, sizeof(cdr_copy->peeraccount));
1090 if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
1091 snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
1094 if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) {
1095 ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield));
1098 /* Timestamps/durations */
1099 cdr_copy->start = it_cdr->start;
1100 cdr_copy->answer = it_cdr->answer;
1101 cdr_copy->end = it_cdr->end;
1102 cdr_copy->billsec = cdr_object_get_billsec(it_cdr);
1103 cdr_copy->duration = cdr_object_get_duration(it_cdr);
1106 ast_copy_flags(cdr_copy, &it_cdr->flags, AST_FLAGS_ALL);
1107 ast_copy_string(cdr_copy->linkedid, it_cdr->linkedid, sizeof(cdr_copy->linkedid));
1108 cdr_copy->disposition = it_cdr->disposition;
1109 cdr_copy->sequence = it_cdr->sequence;
1112 copy_variables(&cdr_copy->varshead, &it_cdr->party_a.variables);
1113 AST_LIST_TRAVERSE(&it_cdr->party_b.variables, it_var, entries) {
1115 struct ast_var_t *newvariable;
1116 AST_LIST_TRAVERSE(&cdr_copy->varshead, it_copy_var, entries) {
1117 if (!strcmp(ast_var_name(it_var), ast_var_name(it_copy_var))) {
1122 if (!found && (newvariable = ast_var_assign(ast_var_name(it_var), ast_var_value(it_var)))) {
1123 AST_LIST_INSERT_TAIL(&cdr_copy->varshead, newvariable, entries);
1131 cdr_prev->next = cdr_copy;
1132 cdr_prev = cdr_copy;
1140 * \brief Dispatch a CDR.
1141 * \param cdr The \ref cdr_object to dispatch
1143 * This will create a \ref ast_cdr object and publish it to the various backends
1145 static void cdr_object_dispatch(struct cdr_object *cdr)
1147 RAII_VAR(struct module_config *, mod_cfg,
1148 ao2_global_obj_ref(module_configs), ao2_cleanup);
1149 struct ast_cdr *pub_cdr;
1151 CDR_DEBUG(mod_cfg, "%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
1152 cdr->party_a.snapshot->name,
1153 cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<none>");
1154 pub_cdr = cdr_object_create_public_records(cdr);
1155 cdr_detach(pub_cdr);
1159 * \brief Set the disposition on a \ref cdr_object based on a hangupcause code
1160 * \param cdr The \ref cdr_object
1161 * \param hangupcause The Asterisk hangup cause code
1163 static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
1165 RAII_VAR(struct module_config *, mod_cfg,
1166 ao2_global_obj_ref(module_configs), ao2_cleanup);
1168 /* Change the disposition based on the hang up cause */
1169 switch (hangupcause) {
1170 case AST_CAUSE_BUSY:
1171 cdr->disposition = AST_CDR_BUSY;
1173 case AST_CAUSE_CONGESTION:
1174 if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
1175 cdr->disposition = AST_CDR_FAILED;
1177 cdr->disposition = AST_CDR_CONGESTION;
1180 case AST_CAUSE_NO_ROUTE_DESTINATION:
1181 case AST_CAUSE_UNREGISTERED:
1182 cdr->disposition = AST_CDR_FAILED;
1184 case AST_CAUSE_NORMAL_CLEARING:
1185 case AST_CAUSE_NO_ANSWER:
1186 cdr->disposition = AST_CDR_NOANSWER;
1194 * \brief Finalize a CDR.
1196 * This function is safe to call multiple times. Note that you can call this
1197 * explicitly before going to the finalized state if there's a chance the CDR
1198 * will be re-activated, in which case the \ref cdr_object's end time should be
1199 * cleared. This function is implicitly called when a CDR transitions to the
1200 * finalized state and right before it is dispatched
1202 * \param cdr_object The CDR to finalize
1204 static void cdr_object_finalize(struct cdr_object *cdr)
1206 RAII_VAR(struct module_config *, mod_cfg,
1207 ao2_global_obj_ref(module_configs), ao2_cleanup);
1209 if (!ast_tvzero(cdr->end)) {
1212 cdr->end = ast_tvnow();
1214 if (cdr->disposition == AST_CDR_NULL) {
1215 if (!ast_tvzero(cdr->answer)) {
1216 cdr->disposition = AST_CDR_ANSWERED;
1217 } else if (cdr->party_a.snapshot->hangupcause) {
1218 cdr_object_set_disposition(cdr, cdr->party_a.snapshot->hangupcause);
1219 } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangupcause) {
1220 cdr_object_set_disposition(cdr, cdr->party_b.snapshot->hangupcause);
1222 cdr->disposition = AST_CDR_FAILED;
1226 /* tv_usec is suseconds_t, which could be int or long */
1227 ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dispo %s\n",
1228 cdr->party_a.snapshot->name,
1230 (long)cdr->start.tv_usec,
1232 (long)cdr->answer.tv_usec,
1234 (long)cdr->end.tv_usec,
1235 ast_cdr_disp2str(cdr->disposition));
1239 * \brief Check to see if a CDR needs to move to the finalized state because
1240 * its Party A hungup.
1242 static void cdr_object_check_party_a_hangup(struct cdr_object *cdr)
1244 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1246 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
1247 && ast_test_flag(&cdr->party_a.snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
1248 cdr_object_finalize(cdr);
1251 if (ast_test_flag(&cdr->party_a.snapshot->flags, AST_FLAG_DEAD)
1252 && cdr->fn_table != &finalized_state_fn_table) {
1253 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1258 * \brief Check to see if a CDR needs to be answered based on its Party A.
1259 * Note that this is safe to call as much as you want - we won't answer twice
1261 static void cdr_object_check_party_a_answer(struct cdr_object *cdr) {
1262 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1264 if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
1265 cdr->answer = ast_tvnow();
1266 /* tv_usec is suseconds_t, which could be int or long */
1267 CDR_DEBUG(mod_cfg, "%p - Set answered time to %ld.%06ld\n", cdr,
1269 (long)cdr->answer.tv_usec);
1273 /* \brief Set Caller ID information on a CDR */
1274 static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
1276 if (!old_snapshot->snapshot) {
1277 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
1278 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
1279 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
1282 if (!strcmp(old_snapshot->snapshot->caller_dnid, new_snapshot->caller_dnid)) {
1283 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
1285 if (!strcmp(old_snapshot->snapshot->caller_subaddr, new_snapshot->caller_subaddr)) {
1286 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
1288 if (!strcmp(old_snapshot->snapshot->dialed_subaddr, new_snapshot->dialed_subaddr)) {
1289 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
1294 * \brief Swap an old \ref cdr_object_snapshot's \ref ast_channel_snapshot for
1295 * a new \ref ast_channel_snapshot
1296 * \param old_snapshot The old \ref cdr_object_snapshot
1297 * \param new_snapshot The new \ref ast_channel_snapshot for old_snapshot
1299 static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot,
1300 struct ast_channel_snapshot *new_snapshot)
1302 cdr_object_update_cid(old_snapshot, new_snapshot);
1303 if (old_snapshot->snapshot) {
1304 ao2_t_ref(old_snapshot->snapshot, -1, "Drop ref for swap");
1306 ao2_t_ref(new_snapshot, +1, "Bump ref for swap");
1307 old_snapshot->snapshot = new_snapshot;
1310 /* BASE METHOD IMPLEMENTATIONS */
1312 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1314 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1316 ast_assert(strcmp(snapshot->name, cdr->party_a.snapshot->name) == 0);
1317 cdr_object_swap_snapshot(&cdr->party_a, snapshot);
1319 /* When Party A is originated to an application and the application exits, the stack
1320 * will attempt to clear the application and restore the dummy originate application
1321 * of "AppDialX". Prevent that, and any other application changes we might not want
1324 if (!ast_strlen_zero(snapshot->appl)
1325 && (strncasecmp(snapshot->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))
1326 && !ast_test_flag(&cdr->flags, AST_CDR_LOCK_APP)) {
1327 ast_string_field_set(cdr, appl, snapshot->appl);
1328 ast_string_field_set(cdr, data, snapshot->data);
1331 ast_string_field_set(cdr, linkedid, snapshot->linkedid);
1332 cdr_object_check_party_a_answer(cdr);
1333 cdr_object_check_party_a_hangup(cdr);
1338 static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1340 /* In general, most things shouldn't get a bridge leave */
1345 static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1347 /* In general, most things shouldn't get a dial end. */
1352 static enum process_bridge_enter_results base_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1354 /* Base process bridge enter simply indicates that we can't handle it */
1355 return BRIDGE_ENTER_NEED_CDR;
1358 static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
1360 char park_info[128];
1362 ast_assert(!strcmp(parking_info->parkee->name, cdr->party_a.snapshot->name));
1364 /* Update Party A information regardless */
1365 cdr->fn_table->process_party_a(cdr, parking_info->parkee);
1367 /* Fake out where we're parked */
1368 ast_string_field_set(cdr, appl, "Park");
1369 snprintf(park_info, sizeof(park_info), "%s:%u", parking_info->parkinglot, parking_info->parkingspace);
1370 ast_string_field_set(cdr, data, park_info);
1372 /* Prevent any further changes to the App/Data fields for this record */
1373 ast_set_flag(&cdr->flags, AST_CDR_LOCK_APP);
1380 static void single_state_init_function(struct cdr_object *cdr) {
1381 cdr->start = ast_tvnow();
1382 cdr_object_check_party_a_answer(cdr);
1385 static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1387 /* This should never happen! */
1388 ast_assert(cdr->party_b.snapshot == NULL);
1393 static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1395 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1397 if (caller && !strcmp(cdr->party_a.snapshot->name, caller->name)) {
1398 cdr_object_swap_snapshot(&cdr->party_a, caller);
1399 CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr,
1400 cdr->party_a.snapshot->name);
1401 cdr_object_swap_snapshot(&cdr->party_b, peer);
1402 CDR_DEBUG(mod_cfg, "%p - Updated Party B %s snapshot\n", cdr,
1403 cdr->party_b.snapshot->name);
1404 } else if (!strcmp(cdr->party_a.snapshot->name, peer->name)) {
1405 /* We're the entity being dialed, i.e., outbound origination */
1406 cdr_object_swap_snapshot(&cdr->party_a, peer);
1407 CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr,
1408 cdr->party_a.snapshot->name);
1411 cdr_object_transition_state(cdr, &dial_state_fn_table);
1416 * \brief Handle a comparison between our \ref cdr_object and a \ref cdr_object
1417 * already in the bridge while in the Single state. The goal of this is to find
1418 * a Party B for our CDR.
1420 * \param cdr Our \ref cdr_object in the Single state
1421 * \param cand_cdr The \ref cdr_object already in the Bridge state
1423 * \retval 0 The cand_cdr had a Party A or Party B that we could use as our
1425 * \retval 1 No party in the cand_cdr could be used as our Party B
1427 static int single_state_bridge_enter_comparison(struct cdr_object *cdr,
1428 struct cdr_object *cand_cdr)
1430 struct cdr_object_snapshot *party_a;
1432 /* Don't match on ourselves */
1433 if (!strcmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)) {
1437 /* Try the candidate CDR's Party A first */
1438 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
1439 if (!strcmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
1440 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1441 if (!cand_cdr->party_b.snapshot) {
1442 /* We just stole them - finalize their CDR. Note that this won't
1443 * transition their state, it just sets the end time and the
1444 * disposition - if we need to re-activate them later, we can.
1446 cdr_object_finalize(cand_cdr);
1451 /* Try their Party B, unless it's us */
1452 if (!cand_cdr->party_b.snapshot || !strcmp(cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name)) {
1455 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
1456 if (!strcmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
1457 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
1464 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)
1466 struct ao2_iterator *it_cdrs;
1467 struct cdr_object *cand_cdr_master;
1468 char *bridge_id = ast_strdupa(bridge->uniqueid);
1471 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1473 /* Get parties in the bridge */
1474 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
1475 cdr_object_bridge_cmp_fn, bridge_id);
1477 /* No one in the bridge yet! */
1478 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1479 return BRIDGE_ENTER_ONLY_PARTY;
1482 while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
1483 struct cdr_object *cand_cdr;
1485 ao2_lock(cand_cdr_master);
1486 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1487 /* Skip any records that are not in a bridge or in this bridge.
1488 * I'm not sure how that would happen, but it pays to be careful. */
1489 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1490 strcmp(cdr->bridge, cand_cdr->bridge)) {
1494 if (single_state_bridge_enter_comparison(cdr, cand_cdr)) {
1497 /* We successfully got a party B - break out */
1501 ao2_unlock(cand_cdr_master);
1502 ao2_t_ref(cand_cdr_master, -1, "Drop iterator reference");
1504 ao2_iterator_destroy(it_cdrs);
1506 /* We always transition state, even if we didn't get a peer */
1507 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1509 /* Success implies that we have a Party B */
1511 return BRIDGE_ENTER_OBTAINED_PARTY_B;
1514 return BRIDGE_ENTER_NO_PARTY_B;
1517 static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1519 cdr_object_transition_state(cdr, &parked_state_fn_table);
1526 static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1528 ast_assert(snapshot != NULL);
1530 if (!cdr->party_b.snapshot || strcmp(cdr->party_b.snapshot->name, snapshot->name)) {
1533 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1535 /* If party B hangs up, finalize this CDR */
1536 if (ast_test_flag(&cdr->party_b.snapshot->flags, AST_FLAG_DEAD)) {
1537 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1541 static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1543 /* Don't process a begin dial here. A party A already in the dial state will
1544 * who receives a dial begin for something else will be handled by the
1545 * message router callback and will add a new CDR for the party A */
1549 /*! \internal \brief Convert a dial status to a CDR disposition */
1550 static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
1552 RAII_VAR(struct module_config *, mod_cfg,
1553 ao2_global_obj_ref(module_configs), ao2_cleanup);
1555 if (!strcmp(dial_status, "ANSWER")) {
1556 return AST_CDR_ANSWERED;
1557 } else if (!strcmp(dial_status, "BUSY")) {
1558 return AST_CDR_BUSY;
1559 } else if (!strcmp(dial_status, "CANCEL") || !strcmp(dial_status, "NOANSWER")) {
1560 return AST_CDR_NOANSWER;
1561 } else if (!strcmp(dial_status, "CONGESTION")) {
1562 if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
1563 return AST_CDR_FAILED;
1565 return AST_CDR_CONGESTION;
1567 } else if (!strcmp(dial_status, "FAILED")) {
1568 return AST_CDR_FAILED;
1570 return AST_CDR_FAILED;
1573 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)
1575 RAII_VAR(struct module_config *, mod_cfg,
1576 ao2_global_obj_ref(module_configs), ao2_cleanup);
1577 struct ast_channel_snapshot *party_a;
1584 ast_assert(!strcmp(cdr->party_a.snapshot->name, party_a->name));
1585 cdr_object_swap_snapshot(&cdr->party_a, party_a);
1587 if (cdr->party_b.snapshot) {
1588 if (strcmp(cdr->party_b.snapshot->name, peer->name)) {
1589 /* Not the status for this CDR - defer back to the message router */
1592 cdr_object_swap_snapshot(&cdr->party_b, peer);
1595 /* Set the disposition based on the dial string. */
1596 cdr->disposition = dial_status_to_disposition(dial_status);
1597 if (cdr->disposition == AST_CDR_ANSWERED) {
1598 /* Switch to dial pending to wait and see what the caller does */
1599 cdr_object_transition_state(cdr, &dialed_pending_state_fn_table);
1601 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1607 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)
1609 struct ao2_iterator *it_cdrs;
1610 char *bridge_id = ast_strdupa(bridge->uniqueid);
1611 struct cdr_object *cand_cdr_master;
1614 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1616 /* Get parties in the bridge */
1617 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
1618 cdr_object_bridge_cmp_fn, bridge_id);
1620 /* No one in the bridge yet! */
1621 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1622 return BRIDGE_ENTER_ONLY_PARTY;
1625 while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
1626 struct cdr_object *cand_cdr;
1628 ao2_lock(cand_cdr_master);
1629 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1630 /* Skip any records that are not in a bridge or in this bridge.
1631 * I'm not sure how that would happen, but it pays to be careful. */
1632 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1633 strcmp(cdr->bridge, cand_cdr->bridge)) {
1637 /* If we don't have a Party B (originated channel), skip it */
1638 if (!cdr->party_b.snapshot) {
1642 /* Skip any records that aren't our Party B */
1643 if (strcmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name)) {
1646 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1647 /* If they have a Party B, they joined up with someone else as their
1648 * Party A. Don't finalize them as they're active. Otherwise, we
1649 * have stolen them so they need to be finalized.
1651 if (!cand_cdr->party_b.snapshot) {
1652 cdr_object_finalize(cand_cdr);
1657 ao2_unlock(cand_cdr_master);
1658 ao2_t_ref(cand_cdr_master, -1, "Drop iterator reference");
1660 ao2_iterator_destroy(it_cdrs);
1662 /* We always transition state, even if we didn't get a peer */
1663 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1665 /* Success implies that we have a Party B */
1667 return BRIDGE_ENTER_OBTAINED_PARTY_B;
1669 return BRIDGE_ENTER_NO_PARTY_B;
1672 /* DIALED PENDING STATE */
1674 static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1676 /* If we get a CEP change, we're executing dialplan. If we have a Party B
1677 * that means we need a new CDR; otherwise, switch us over to single.
1679 if (snapshot_cep_changed(cdr->party_a.snapshot, snapshot)) {
1680 if (cdr->party_b.snapshot) {
1681 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1682 cdr->fn_table->process_party_a(cdr, snapshot);
1685 cdr_object_transition_state(cdr, &single_state_fn_table);
1686 cdr->fn_table->process_party_a(cdr, snapshot);
1690 base_process_party_a(cdr, snapshot);
1694 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)
1696 cdr_object_transition_state(cdr, &dial_state_fn_table);
1697 return cdr->fn_table->process_bridge_enter(cdr, bridge, channel);
1700 static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1702 /* We can't handle this as we have a Party B - ask for a new one */
1706 static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1708 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1710 /* Ask for a new CDR */
1716 static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1718 if (!cdr->party_b.snapshot || strcmp(cdr->party_b.snapshot->name, snapshot->name)) {
1721 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1723 /* If party B hangs up, finalize this CDR */
1724 if (ast_test_flag(&cdr->party_b.snapshot->flags, AST_FLAG_DEAD)) {
1725 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1729 static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1731 if (strcmp(cdr->bridge, bridge->uniqueid)) {
1734 if (strcmp(cdr->party_a.snapshot->name, channel->name)
1735 && cdr->party_b.snapshot
1736 && strcmp(cdr->party_b.snapshot->name, channel->name)) {
1739 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1746 static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1748 if (strcmp(cdr->party_a.snapshot->name, channel->name)) {
1751 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1756 /* FINALIZED STATE */
1758 static void finalized_state_init_function(struct cdr_object *cdr)
1760 cdr_object_finalize(cdr);
1763 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1765 RAII_VAR(struct module_config *, mod_cfg,
1766 ao2_global_obj_ref(module_configs), ao2_cleanup);
1768 /* If we ignore hangup logic, indicate that we don't need a new CDR */
1769 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
1770 && ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
1774 /* Indicate that, if possible, we should get a new CDR */
1778 /* TOPIC ROUTER CALLBACKS */
1781 * \brief Handler for Stasis-Core dial messages
1782 * \param data Passed on
1783 * \param sub The stasis subscription for this message callback
1784 * \param topic The topic this message was published for
1785 * \param message The message
1787 static void handle_dial_message(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
1789 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1790 struct cdr_object *cdr;
1791 struct ast_multi_channel_blob *payload = stasis_message_data(message);
1792 struct ast_channel_snapshot *caller;
1793 struct ast_channel_snapshot *peer;
1794 struct cdr_object *it_cdr;
1795 struct ast_json *dial_status_blob;
1796 const char *dial_status = NULL;
1799 caller = ast_multi_channel_blob_get_channel(payload, "caller");
1800 peer = ast_multi_channel_blob_get_channel(payload, "peer");
1801 if (!peer && !caller) {
1804 dial_status_blob = ast_json_object_get(ast_multi_channel_blob_get_json(payload), "dialstatus");
1805 if (dial_status_blob) {
1806 dial_status = ast_json_string_get(dial_status_blob);
1809 CDR_DEBUG(mod_cfg, "Dial %s message for %s, %s: %u.%08u\n",
1810 ast_strlen_zero(dial_status) ? "Begin" : "End",
1811 caller ? caller->name : "(none)",
1812 peer ? peer->name : "(none)",
1813 (unsigned int)stasis_message_timestamp(message)->tv_sec,
1814 (unsigned int)stasis_message_timestamp(message)->tv_usec);
1816 /* Figure out who is running this show */
1818 cdr = ao2_find(active_cdrs_by_channel, caller->name, OBJ_KEY);
1820 cdr = ao2_find(active_cdrs_by_channel, peer->name, OBJ_KEY);
1824 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1825 if (ast_strlen_zero(dial_status)) {
1826 if (!it_cdr->fn_table->process_dial_begin) {
1829 CDR_DEBUG(mod_cfg, "%p - Processing Dial Begin message for channel %s, peer %s\n",
1831 caller ? caller->name : "(none)",
1832 peer ? peer->name : "(none)");
1833 res &= it_cdr->fn_table->process_dial_begin(it_cdr,
1837 if (!it_cdr->fn_table->process_dial_end) {
1840 CDR_DEBUG(mod_cfg, "%p - Processing Dial End message for channel %s, peer %s\n",
1842 caller ? caller->name : "(none)",
1843 peer ? peer->name : "(none)");
1844 it_cdr->fn_table->process_dial_end(it_cdr,
1851 /* If no CDR handled a dial begin message, make a new one */
1852 if (res && ast_strlen_zero(dial_status)) {
1853 struct cdr_object *new_cdr;
1855 new_cdr = cdr_object_create_and_append(cdr);
1859 new_cdr->fn_table->process_dial_begin(new_cdr,
1866 static int cdr_object_finalize_party_b(void *obj, void *arg, int flags)
1868 struct cdr_object *cdr = obj;
1869 struct ast_channel_snapshot *party_b = arg;
1870 struct cdr_object *it_cdr;
1871 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1872 if (it_cdr->party_b.snapshot && !strcmp(it_cdr->party_b.snapshot->name, party_b->name)) {
1873 /* Don't transition to the finalized state - let the Party A do
1874 * that when its ready
1876 cdr_object_finalize(it_cdr);
1882 static int cdr_object_update_party_b(void *obj, void *arg, int flags)
1884 struct cdr_object *cdr = obj;
1885 struct ast_channel_snapshot *party_b = arg;
1886 struct cdr_object *it_cdr;
1887 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1888 if (!it_cdr->fn_table->process_party_b) {
1891 if (it_cdr->party_b.snapshot && !strcmp(it_cdr->party_b.snapshot->name, party_b->name)) {
1892 it_cdr->fn_table->process_party_b(it_cdr, party_b);
1898 /*! \internal \brief Filter channel snapshots by technology */
1899 static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
1901 return snapshot->tech_properties & (AST_CHAN_TP_ANNOUNCER | AST_CHAN_TP_RECORDER);
1904 /*! \internal \brief Filter a channel cache update */
1905 static int filter_channel_cache_message(struct ast_channel_snapshot *old_snapshot,
1906 struct ast_channel_snapshot *new_snapshot)
1910 /* Drop cache updates from certain channel technologies */
1912 ret |= filter_channel_snapshot(old_snapshot);
1915 ret |= filter_channel_snapshot(new_snapshot);
1921 /*! \brief Determine if we need to add a new CDR based on snapshots */
1922 static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot,
1923 struct ast_channel_snapshot *new_snapshot)
1925 RAII_VAR(struct module_config *, mod_cfg,
1926 ao2_global_obj_ref(module_configs), ao2_cleanup);
1928 if (!new_snapshot) {
1932 if (ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD)) {
1936 /* Auto-fall through will increment the priority but have no application */
1937 if (ast_strlen_zero(new_snapshot->appl)) {
1941 if (old_snapshot && !snapshot_cep_changed(old_snapshot, new_snapshot)) {
1949 * \brief Handler for Stasis-Core channel cache update messages
1950 * \param data Passed on
1951 * \param sub The stasis subscription for this message callback
1952 * \param topic The topic this message was published for
1953 * \param message The message
1955 static void handle_channel_cache_message(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
1957 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
1958 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1959 struct stasis_cache_update *update = stasis_message_data(message);
1960 struct ast_channel_snapshot *old_snapshot;
1961 struct ast_channel_snapshot *new_snapshot;
1963 struct cdr_object *it_cdr;
1965 ast_assert(update != NULL);
1966 ast_assert(ast_channel_snapshot_type() == update->type);
1968 old_snapshot = stasis_message_data(update->old_snapshot);
1969 new_snapshot = stasis_message_data(update->new_snapshot);
1970 name = new_snapshot ? new_snapshot->name : old_snapshot->name;
1972 if (filter_channel_cache_message(old_snapshot, new_snapshot)) {
1976 CDR_DEBUG(mod_cfg, "Channel Update message for %s: %u.%08u\n",
1978 (unsigned int)stasis_message_timestamp(message)->tv_sec,
1979 (unsigned int)stasis_message_timestamp(message)->tv_usec);
1981 if (new_snapshot && !old_snapshot) {
1982 cdr = cdr_object_alloc(new_snapshot);
1986 ao2_link(active_cdrs_by_channel, cdr);
1989 /* Handle Party A */
1991 cdr = ao2_find(active_cdrs_by_channel, name, OBJ_KEY);
1994 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", name);
1999 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2000 if (!it_cdr->fn_table->process_party_a) {
2003 CDR_DEBUG(mod_cfg, "%p - Processing new channel snapshot %s\n", it_cdr, new_snapshot->name);
2004 all_reject &= it_cdr->fn_table->process_party_a(it_cdr, new_snapshot);
2006 if (all_reject && check_new_cdr_needed(old_snapshot, new_snapshot)) {
2007 /* We're not hung up and we have a new snapshot - we need a new CDR */
2008 struct cdr_object *new_cdr;
2009 new_cdr = cdr_object_create_and_append(cdr);
2011 new_cdr->fn_table->process_party_a(new_cdr, new_snapshot);
2015 CDR_DEBUG(mod_cfg, "%p - Beginning finalize/dispatch for %s\n", cdr, old_snapshot->name);
2016 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2017 cdr_object_finalize(it_cdr);
2019 cdr_object_dispatch(cdr);
2020 ao2_unlink(active_cdrs_by_channel, cdr);
2025 /* Handle Party B */
2027 ao2_callback(active_cdrs_by_channel, OBJ_NODATA, cdr_object_update_party_b,
2030 ao2_callback(active_cdrs_by_channel, OBJ_NODATA, cdr_object_finalize_party_b,
2036 struct bridge_leave_data {
2037 struct ast_bridge_snapshot *bridge;
2038 struct ast_channel_snapshot *channel;
2041 /*! \brief Callback used to notify CDRs of a Party B leaving the bridge */
2042 static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, int flags)
2044 struct cdr_object *cdr = obj;
2045 struct bridge_leave_data *leave_data = arg;
2046 struct cdr_object *it_cdr;
2048 if (strcmp(cdr->bridge, leave_data->bridge->uniqueid)) {
2051 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2052 if (it_cdr->fn_table != &bridge_state_fn_table) {
2055 if (!it_cdr->party_b.snapshot) {
2058 if (strcmp(it_cdr->party_b.snapshot->name, leave_data->channel->name)) {
2061 /* It is our Party B, in our bridge. Set the end time and let the handler
2062 * transition our CDR appropriately when we leave the bridge.
2064 cdr_object_finalize(it_cdr);
2069 /*! \brief Filter bridge messages based on bridge technology */
2070 static int filter_bridge_messages(struct ast_bridge_snapshot *bridge)
2072 /* Ignore holding bridge technology messages. We treat this simply as an application
2073 * that a channel enters into.
2075 if (!strcmp(bridge->technology, "holding_bridge") && strcmp(bridge->subclass, "parking")) {
2082 * \brief Handler for when a channel leaves a bridge
2083 * \param data Passed on
2084 * \param sub The stasis subscription for this message callback
2085 * \param topic The topic this message was published for
2086 * \param message The message - hopefully a bridge one!
2088 static void handle_bridge_leave_message(void *data, struct stasis_subscription *sub,
2089 struct stasis_topic *topic, struct stasis_message *message)
2091 struct ast_bridge_blob *update = stasis_message_data(message);
2092 struct ast_bridge_snapshot *bridge = update->bridge;
2093 struct ast_channel_snapshot *channel = update->channel;
2094 RAII_VAR(struct module_config *, mod_cfg,
2095 ao2_global_obj_ref(module_configs), ao2_cleanup);
2096 RAII_VAR(struct cdr_object *, cdr,
2097 ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY),
2099 struct cdr_object *it_cdr;
2100 struct bridge_leave_data leave_data = {
2104 int left_bridge = 0;
2106 if (filter_bridge_messages(bridge)) {
2110 CDR_DEBUG(mod_cfg, "Bridge Leave message for %s: %u.%08u\n",
2112 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2113 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2116 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2122 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2123 if (!it_cdr->fn_table->process_bridge_leave) {
2126 CDR_DEBUG(mod_cfg, "%p - Processing Bridge Leave for %s\n",
2127 it_cdr, channel->name);
2128 if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
2129 ast_string_field_set(it_cdr, bridge, "");
2139 if (strcmp(bridge->subclass, "parking")) {
2141 ao2_callback(active_cdrs_by_channel, OBJ_NODATA,
2142 cdr_object_party_b_left_bridge_cb,
2147 struct bridge_candidate {
2148 struct cdr_object *cdr; /*!< The actual CDR this candidate belongs to, either as A or B */
2149 struct cdr_object_snapshot candidate; /*!< The candidate for a new pairing */
2153 * \brief Comparison function for \ref bridge_candidate objects
2155 static int bridge_candidate_cmp_fn(void *obj, void *arg, int flags)
2157 struct bridge_candidate *left = obj;
2158 struct bridge_candidate *right = arg;
2159 const char *match = (flags & OBJ_KEY) ? arg : right->candidate.snapshot->name;
2160 return strcasecmp(left->candidate.snapshot->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
2164 * \brief Hash function for \ref bridge_candidate objects
2166 static int bridge_candidate_hash_fn(const void *obj, const int flags)
2168 const struct bridge_candidate *bc = obj;
2169 const char *id = (flags & OBJ_KEY) ? obj : bc->candidate.snapshot->name;
2170 return ast_str_case_hash(id);
2173 /*! \brief \ref bridge_candidate Destructor */
2174 static void bridge_candidate_dtor(void *obj)
2176 struct bridge_candidate *bcand = obj;
2177 ao2_cleanup(bcand->cdr);
2178 ao2_cleanup(bcand->candidate.snapshot);
2179 free_variables(&bcand->candidate.variables);
2183 * \brief \ref bridge_candidate Constructor
2184 * \param cdr The \ref cdr_object that is a candidate for being compared to in
2185 * a bridge operation
2186 * \param candidate The \ref cdr_object_snapshot candidate snapshot in the CDR
2187 * that should be used during the operaton
2189 static struct bridge_candidate *bridge_candidate_alloc(struct cdr_object *cdr, struct cdr_object_snapshot *candidate)
2191 struct bridge_candidate *bcand;
2193 bcand = ao2_alloc(sizeof(*bcand), bridge_candidate_dtor);
2198 ao2_ref(bcand->cdr, +1);
2199 bcand->candidate.flags = candidate->flags;
2200 strcpy(bcand->candidate.userfield, candidate->userfield);
2201 bcand->candidate.snapshot = candidate->snapshot;
2202 ao2_ref(bcand->candidate.snapshot, +1);
2203 copy_variables(&bcand->candidate.variables, &candidate->variables);
2209 * \internal \brief Build and add bridge candidates based on a CDR
2210 * \param bridge_id The ID of the bridge we need candidates for
2211 * \param candidates The container of \ref bridge_candidate objects
2212 * \param cdr The \ref cdr_object that is our candidate
2213 * \param party_a Non-zero if we should look at the Party A channel; 0 if Party B
2215 static void add_candidate_for_bridge(const char *bridge_id,
2216 struct ao2_container *candidates,
2217 struct cdr_object *cdr,
2220 struct cdr_object *it_cdr;
2222 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2223 struct cdr_object_snapshot *party_snapshot;
2224 RAII_VAR(struct bridge_candidate *, bcand, NULL, ao2_cleanup);
2226 party_snapshot = party_a ? &it_cdr->party_a : &it_cdr->party_b;
2228 if (it_cdr->fn_table != &bridge_state_fn_table || strcmp(bridge_id, it_cdr->bridge)) {
2232 if (!party_snapshot->snapshot) {
2236 /* Don't add a party twice */
2237 bcand = ao2_find(candidates, party_snapshot->snapshot->name, OBJ_KEY);
2242 bcand = bridge_candidate_alloc(it_cdr, party_snapshot);
2244 ao2_link(candidates, bcand);
2250 * \brief Create new \ref bridge_candidate objects for each party currently
2252 * \param bridge The \param ast_bridge_snapshot for the bridge we're processing
2254 * Note that we use two passes here instead of one so that we only create a
2255 * candidate for a party B if they are never a party A in the bridge. Otherwise,
2256 * we don't care about them.
2258 static struct ao2_container *create_candidates_for_bridge(struct ast_bridge_snapshot *bridge)
2260 struct ao2_container *candidates = ao2_container_alloc(51, bridge_candidate_hash_fn, bridge_candidate_cmp_fn);
2261 char *bridge_id = ast_strdupa(bridge->uniqueid);
2262 struct ao2_iterator *it_cdrs;
2263 struct cdr_object *cand_cdr_master;
2269 /* For each CDR that has a record in the bridge, get their Party A and
2270 * make them a candidate. Note that we do this in two passes as opposed to one so
2271 * that we give preference CDRs where the channel is Party A */
2272 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
2273 cdr_object_bridge_cmp_fn, bridge_id);
2275 /* No one in the bridge yet! */
2276 ao2_cleanup(candidates);
2279 while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
2280 SCOPED_AO2LOCK(lock, cand_cdr_master);
2281 add_candidate_for_bridge(bridge->uniqueid, candidates, cand_cdr_master, 1);
2283 ao2_iterator_destroy(it_cdrs);
2284 /* For each CDR that has a record in the bridge, get their Party B and
2285 * make them a candidate. */
2286 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
2287 cdr_object_bridge_cmp_fn, bridge_id);
2289 /* Now it's just an error. */
2290 ao2_cleanup(candidates);
2293 while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
2294 SCOPED_AO2LOCK(lock, cand_cdr_master);
2295 add_candidate_for_bridge(bridge->uniqueid, candidates, cand_cdr_master, 0);
2297 ao2_iterator_destroy(it_cdrs);
2303 * \internal \brief Create a new CDR, append it to an existing CDR, and update its snapshots
2304 * \note The new CDR will be automatically transitioned to the bridge state
2306 static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
2307 const char *bridge_id,
2308 struct cdr_object_snapshot *party_b)
2310 struct cdr_object *new_cdr;
2312 new_cdr = cdr_object_create_and_append(cdr);
2316 cdr_object_snapshot_copy(&new_cdr->party_b, party_b);
2317 cdr_object_check_party_a_answer(new_cdr);
2318 ast_string_field_set(new_cdr, bridge, cdr->bridge);
2319 cdr_object_transition_state(new_cdr, &bridge_state_fn_table);
2323 * \brief Process a single \ref bridge_candidate. Note that this is called as
2324 * part of an \ref ao2_callback on an \ref ao2_container of \ref bridge_candidate
2325 * objects previously created by \ref create_candidates_for_bridge.
2327 * \param obj The \ref bridge_candidate being processed
2328 * \param arg The \ref cdr_object that is being compared against the candidates
2330 * The purpose of this function is to create the necessary CDR entries as a
2331 * result of \ref cdr_object having entered the same bridge as the CDR
2332 * represented by \ref bridge_candidate.
2334 static int bridge_candidate_process(void *obj, void *arg, int flags)
2336 struct bridge_candidate *bcand = obj;
2337 struct cdr_object *cdr = arg;
2338 struct cdr_object_snapshot *party_a;
2340 /* If the candidate is us or someone we've taken on, pass on by */
2341 if (!strcmp(cdr->party_a.snapshot->name, bcand->candidate.snapshot->name)
2342 || (cdr->party_b.snapshot && !(strcmp(cdr->party_b.snapshot->name, bcand->candidate.snapshot->name)))) {
2345 party_a = cdr_object_pick_party_a(&cdr->party_a, &bcand->candidate);
2346 /* We're party A - make a new CDR, append it to us, and set the candidate as
2348 if (!strcmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
2349 bridge_candidate_add_to_cdr(cdr, cdr->bridge, &bcand->candidate);
2353 /* We're Party B. Check if the candidate is the CDR's Party A. If so, find out if we
2354 * can add ourselves directly as the Party B, or if we need a new CDR. */
2355 if (!strcmp(bcand->cdr->party_a.snapshot->name, bcand->candidate.snapshot->name)) {
2356 if (bcand->cdr->party_b.snapshot
2357 && strcmp(bcand->cdr->party_b.snapshot->name, cdr->party_a.snapshot->name)) {
2358 bridge_candidate_add_to_cdr(bcand->cdr, cdr->bridge, &cdr->party_a);
2360 cdr_object_snapshot_copy(&bcand->cdr->party_b, &cdr->party_a);
2361 /* It's possible that this joined at one point and was never chosen
2362 * as party A. Clear their end time, as it would be set in such a
2365 memset(&bcand->cdr->end, 0, sizeof(bcand->cdr->end));
2368 /* We are Party B to a candidate CDR's Party B. Since a candidate
2369 * CDR will only have a Party B represented here if that channel
2370 * was never a Party A in the bridge, we have to go looking for
2371 * that channel's primary CDR record.
2373 struct cdr_object *b_party = ao2_find(active_cdrs_by_channel, bcand->candidate.snapshot->name, OBJ_KEY);
2375 /* Holy cow - no CDR? */
2376 b_party = cdr_object_alloc(bcand->candidate.snapshot);
2377 cdr_object_snapshot_copy(&b_party->party_a, &bcand->candidate);
2378 cdr_object_snapshot_copy(&b_party->party_b, &cdr->party_a);
2379 cdr_object_check_party_a_answer(b_party);
2380 ast_string_field_set(b_party, bridge, cdr->bridge);
2381 cdr_object_transition_state(b_party, &bridge_state_fn_table);
2382 ao2_link(active_cdrs_by_channel, b_party);
2384 bridge_candidate_add_to_cdr(b_party, cdr->bridge, &cdr->party_a);
2386 ao2_ref(b_party, -1);
2393 * \brief Handle creating bridge pairings for the \ref cdr_object that just
2395 * \param cdr The \ref cdr_object that just entered the bridge
2396 * \param bridge The \ref ast_bridge_snapshot representing the bridge it just entered
2398 static void handle_bridge_pairings(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge)
2400 RAII_VAR(struct ao2_container *, candidates,
2401 create_candidates_for_bridge(bridge),
2407 ao2_callback(candidates, OBJ_NODATA,
2408 bridge_candidate_process,
2414 /*! \brief Handle entering into a parking bridge
2415 * \param cdr The CDR to operate on
2416 * \param bridge The bridge the channel just entered
2417 * \param channel The channel snapshot
2419 static void handle_parking_bridge_enter_message(struct cdr_object *cdr,
2420 struct ast_bridge_snapshot *bridge,
2421 struct ast_channel_snapshot *channel)
2423 RAII_VAR(struct module_config *, mod_cfg,
2424 ao2_global_obj_ref(module_configs), ao2_cleanup);
2426 struct cdr_object *it_cdr;
2427 struct cdr_object *new_cdr;
2431 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2432 if (it_cdr->fn_table->process_parking_bridge_enter) {
2433 res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
2435 if (it_cdr->fn_table->process_party_a) {
2436 CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr,
2438 it_cdr->fn_table->process_party_a(it_cdr, channel);
2443 /* No one handled it - we need a new one! */
2444 new_cdr = cdr_object_create_and_append(cdr);
2446 /* Let the single state transition us to Parked */
2447 cdr_object_transition_state(new_cdr, &single_state_fn_table);
2448 new_cdr->fn_table->process_parking_bridge_enter(new_cdr, bridge, channel);
2454 /*! \brief Handle a bridge enter message for a 'normal' bridge
2455 * \param cdr The CDR to operate on
2456 * \param bridge The bridge the channel just entered
2457 * \param channel The channel snapshot
2459 static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
2460 struct ast_bridge_snapshot *bridge,
2461 struct ast_channel_snapshot *channel)
2463 RAII_VAR(struct module_config *, mod_cfg,
2464 ao2_global_obj_ref(module_configs), ao2_cleanup);
2465 enum process_bridge_enter_results result;
2466 struct cdr_object *it_cdr;
2467 struct cdr_object *new_cdr;
2468 struct cdr_object *handled_cdr = NULL;
2472 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2473 if (it_cdr->fn_table->process_party_a) {
2474 CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr,
2476 it_cdr->fn_table->process_party_a(it_cdr, channel);
2479 /* Notify all states that they have entered a bridge */
2480 if (it_cdr->fn_table->process_bridge_enter) {
2481 CDR_DEBUG(mod_cfg, "%p - Processing bridge enter for %s\n", it_cdr,
2483 result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
2485 case BRIDGE_ENTER_ONLY_PARTY:
2487 case BRIDGE_ENTER_OBTAINED_PARTY_B:
2489 handled_cdr = it_cdr;
2492 case BRIDGE_ENTER_NEED_CDR:
2495 case BRIDGE_ENTER_NO_PARTY_B:
2496 /* We didn't win on any - end this CDR. If someone else comes in later
2497 * that is Party B to this CDR, it can re-activate this CDR.
2500 handled_cdr = it_cdr;
2502 cdr_object_finalize(cdr);
2508 /* Create the new matchings, but only for either:
2509 * * The first CDR in the chain that handled it. This avoids issues with
2511 * * If no one handled it, the last CDR in the chain. This would occur if
2512 * a CDR joined a bridge and it wasn't Party A for anyone. We still need
2513 * to make pairings with everyone in the bridge.
2516 handle_bridge_pairings(handled_cdr, bridge);
2518 /* Nothing handled it - we need a new one! */
2519 new_cdr = cdr_object_create_and_append(cdr);
2521 /* This is guaranteed to succeed: the new CDR is created in the single state
2522 * and will be able to handle the bridge enter message
2524 handle_standard_bridge_enter_message(cdr, bridge, channel);
2531 * \brief Handler for Stasis-Core bridge enter messages
2532 * \param data Passed on
2533 * \param sub The stasis subscription for this message callback
2534 * \param topic The topic this message was published for
2535 * \param message The message - hopefully a bridge one!
2537 static void handle_bridge_enter_message(void *data, struct stasis_subscription *sub,
2538 struct stasis_topic *topic, struct stasis_message *message)
2540 struct ast_bridge_blob *update = stasis_message_data(message);
2541 struct ast_bridge_snapshot *bridge = update->bridge;
2542 struct ast_channel_snapshot *channel = update->channel;
2543 RAII_VAR(struct cdr_object *, cdr,
2544 ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY),
2546 RAII_VAR(struct module_config *, mod_cfg,
2547 ao2_global_obj_ref(module_configs), ao2_cleanup);
2549 if (filter_bridge_messages(bridge)) {
2553 CDR_DEBUG(mod_cfg, "Bridge Enter message for channel %s: %u.%08u\n",
2555 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2556 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2559 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2563 if (!strcmp(bridge->subclass, "parking")) {
2564 handle_parking_bridge_enter_message(cdr, bridge, channel);
2566 handle_standard_bridge_enter_message(cdr, bridge, channel);
2571 * \brief Handler for when a channel is parked
2572 * \param data Passed on
2573 * \param sub The stasis subscription for this message callback
2574 * \param topic The topic this message was published for
2575 * \param message The message about who got parked
2577 static void handle_parked_call_message(void *data, struct stasis_subscription *sub,
2578 struct stasis_topic *topic, struct stasis_message *message)
2580 struct ast_parked_call_payload *payload = stasis_message_data(message);
2581 struct ast_channel_snapshot *channel = payload->parkee;
2582 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
2583 RAII_VAR(struct module_config *, mod_cfg,
2584 ao2_global_obj_ref(module_configs), ao2_cleanup);
2585 struct cdr_object *it_cdr;
2587 /* Anything other than getting parked will be handled by other updates */
2588 if (payload->event_type != PARKED_CALL) {
2592 /* No one got parked? */
2597 CDR_DEBUG(mod_cfg, "Parked Call message for channel %s: %u.%08u\n",
2599 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2600 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2602 cdr = ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY);
2604 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2610 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2611 if (it_cdr->fn_table->process_parked_channel) {
2612 it_cdr->fn_table->process_parked_channel(it_cdr, payload);
2620 struct ast_cdr_config *ast_cdr_get_config(void)
2622 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2623 ao2_ref(mod_cfg->general, +1);
2624 return mod_cfg->general;
2627 void ast_cdr_set_config(struct ast_cdr_config *config)
2629 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2630 ao2_cleanup(mod_cfg->general);
2631 mod_cfg->general = config;
2632 ao2_ref(mod_cfg->general, +1);
2635 int ast_cdr_is_enabled(void)
2637 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2638 return ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED);
2641 int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
2643 struct cdr_beitem *i = NULL;
2649 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
2653 AST_RWLIST_WRLOCK(&be_list);
2654 AST_RWLIST_TRAVERSE(&be_list, i, list) {
2655 if (!strcasecmp(name, i->name)) {
2656 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
2657 AST_RWLIST_UNLOCK(&be_list);
2662 if (!(i = ast_calloc(1, sizeof(*i))))
2666 ast_copy_string(i->name, name, sizeof(i->name));
2667 ast_copy_string(i->desc, desc, sizeof(i->desc));
2669 AST_RWLIST_INSERT_HEAD(&be_list, i, list);
2670 AST_RWLIST_UNLOCK(&be_list);
2675 void ast_cdr_unregister(const char *name)
2677 struct cdr_beitem *i = NULL;
2679 AST_RWLIST_WRLOCK(&be_list);
2680 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) {
2681 if (!strcasecmp(name, i->name)) {
2682 AST_RWLIST_REMOVE_CURRENT(list);
2686 AST_RWLIST_TRAVERSE_SAFE_END;
2687 AST_RWLIST_UNLOCK(&be_list);
2690 ast_verb(2, "Unregistered '%s' CDR backend\n", name);
2695 struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
2697 struct ast_cdr *newcdr;
2702 newcdr = ast_cdr_alloc();
2707 memcpy(newcdr, cdr, sizeof(*newcdr));
2708 memset(&newcdr->varshead, 0, sizeof(newcdr->varshead));
2709 copy_variables(&newcdr->varshead, &cdr->varshead);
2710 newcdr->next = NULL;
2715 static const char *cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
2717 struct ast_var_t *variables;
2718 struct varshead *headp = &cdr->varshead;
2720 if (ast_strlen_zero(name)) {
2724 AST_LIST_TRAVERSE(headp, variables, entries) {
2725 if (!strcasecmp(name, ast_var_name(variables))) {
2726 return ast_var_value(variables);
2733 static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
2735 if (fmt == NULL) { /* raw mode */
2736 snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec);
2741 ast_localtime(&when, &tm, NULL);
2742 ast_strftime(buf, bufsize, fmt, &tm);
2747 void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
2749 const char *fmt = "%Y-%m-%d %T";
2758 if (!strcasecmp(name, "clid")) {
2759 ast_copy_string(workspace, cdr->clid, workspacelen);
2760 } else if (!strcasecmp(name, "src")) {
2761 ast_copy_string(workspace, cdr->src, workspacelen);
2762 } else if (!strcasecmp(name, "dst")) {
2763 ast_copy_string(workspace, cdr->dst, workspacelen);
2764 } else if (!strcasecmp(name, "dcontext")) {
2765 ast_copy_string(workspace, cdr->dcontext, workspacelen);
2766 } else if (!strcasecmp(name, "channel")) {
2767 ast_copy_string(workspace, cdr->channel, workspacelen);
2768 } else if (!strcasecmp(name, "dstchannel")) {
2769 ast_copy_string(workspace, cdr->dstchannel, workspacelen);
2770 } else if (!strcasecmp(name, "lastapp")) {
2771 ast_copy_string(workspace, cdr->lastapp, workspacelen);
2772 } else if (!strcasecmp(name, "lastdata")) {
2773 ast_copy_string(workspace, cdr->lastdata, workspacelen);
2774 } else if (!strcasecmp(name, "start")) {
2775 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
2776 } else if (!strcasecmp(name, "answer")) {
2777 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
2778 } else if (!strcasecmp(name, "end")) {
2779 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
2780 } else if (!strcasecmp(name, "duration")) {
2781 snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
2782 } else if (!strcasecmp(name, "billsec")) {
2783 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);
2784 } else if (!strcasecmp(name, "disposition")) {
2786 snprintf(workspace, workspacelen, "%ld", cdr->disposition);
2788 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
2790 } else if (!strcasecmp(name, "amaflags")) {
2792 snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
2794 ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
2796 } else if (!strcasecmp(name, "accountcode")) {
2797 ast_copy_string(workspace, cdr->accountcode, workspacelen);
2798 } else if (!strcasecmp(name, "peeraccount")) {
2799 ast_copy_string(workspace, cdr->peeraccount, workspacelen);
2800 } else if (!strcasecmp(name, "uniqueid")) {
2801 ast_copy_string(workspace, cdr->uniqueid, workspacelen);
2802 } else if (!strcasecmp(name, "linkedid")) {
2803 ast_copy_string(workspace, cdr->linkedid, workspacelen);
2804 } else if (!strcasecmp(name, "userfield")) {
2805 ast_copy_string(workspace, cdr->userfield, workspacelen);
2806 } else if (!strcasecmp(name, "sequence")) {
2807 snprintf(workspace, workspacelen, "%d", cdr->sequence);
2808 } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
2809 ast_copy_string(workspace, varbuf, workspacelen);
2811 workspace[0] = '\0';
2814 if (!ast_strlen_zero(workspace)) {
2821 * \brief Callback that finds all CDRs that reference a particular channel
2823 static int cdr_object_select_all_by_channel_cb(void *obj, void *arg, int flags)
2825 struct cdr_object *cdr = obj;
2826 const char *name = arg;
2828 if (!strcasecmp(cdr->party_a.snapshot->name, name) ||
2829 (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->name, name))) {
2835 /* Read Only CDR variables */
2836 static const char * const cdr_readonly_vars[] = { "clid", "src", "dst", "dcontext",
2837 "channel", "dstchannel", "lastapp", "lastdata", "start", "answer", "end", "duration",
2838 "billsec", "disposition", "amaflags", "accountcode", "uniqueid", "linkedid",
2839 "userfield", "sequence", "total_duration", "total_billsec", "first_start",
2840 "first_answer", NULL };
2842 int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
2844 struct cdr_object *cdr;
2845 struct cdr_object *it_cdr;
2846 struct ao2_iterator *it_cdrs;
2847 char *arg = ast_strdupa(channel_name);
2850 for (x = 0; cdr_readonly_vars[x]; x++) {
2851 if (!strcasecmp(name, cdr_readonly_vars[x])) {
2852 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
2857 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE, cdr_object_select_all_by_channel_cb, arg);
2859 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
2863 while ((cdr = ao2_iterator_next(it_cdrs))) {
2865 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2866 struct varshead *headp = NULL;
2867 if (it_cdr->fn_table == &finalized_state_fn_table) {
2870 if (!strcmp(channel_name, it_cdr->party_a.snapshot->name)) {
2871 headp = &it_cdr->party_a.variables;
2872 } else if (it_cdr->party_b.snapshot && !strcmp(channel_name, it_cdr->party_b.snapshot->name)) {
2873 headp = &it_cdr->party_b.variables;
2876 set_variable(headp, name, value);
2882 ao2_iterator_destroy(it_cdrs);
2888 * \brief Format a variable on a \ref cdr_object
2890 static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
2892 struct ast_var_t *variable;
2894 AST_LIST_TRAVERSE(&cdr->party_a.variables, variable, entries) {
2895 if (!strcasecmp(name, ast_var_name(variable))) {
2896 ast_copy_string(value, ast_var_value(variable), length);
2905 * \brief Format one of the standard properties on a \ref cdr_object
2907 static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
2909 struct ast_channel_snapshot *party_a = cdr_obj->party_a.snapshot;
2910 struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;
2912 if (!strcasecmp(name, "clid")) {
2913 ast_callerid_merge(value, length, party_a->caller_name, party_a->caller_number, "");
2914 } else if (!strcasecmp(name, "src")) {
2915 ast_copy_string(value, party_a->caller_number, length);
2916 } else if (!strcasecmp(name, "dst")) {
2917 ast_copy_string(value, party_a->exten, length);
2918 } else if (!strcasecmp(name, "dcontext")) {
2919 ast_copy_string(value, party_a->context, length);
2920 } else if (!strcasecmp(name, "channel")) {
2921 ast_copy_string(value, party_a->name, length);
2922 } else if (!strcasecmp(name, "dstchannel")) {
2924 ast_copy_string(value, party_b->name, length);
2926 ast_copy_string(value, "", length);
2928 } else if (!strcasecmp(name, "lastapp")) {
2929 ast_copy_string(value, party_a->appl, length);
2930 } else if (!strcasecmp(name, "lastdata")) {
2931 ast_copy_string(value, party_a->data, length);
2932 } else if (!strcasecmp(name, "start")) {
2933 cdr_get_tv(cdr_obj->start, NULL, value, length);
2934 } else if (!strcasecmp(name, "answer")) {
2935 cdr_get_tv(cdr_obj->answer, NULL, value, length);
2936 } else if (!strcasecmp(name, "end")) {
2937 cdr_get_tv(cdr_obj->end, NULL, value, length);
2938 } else if (!strcasecmp(name, "duration")) {
2939 snprintf(value, length, "%ld", cdr_object_get_duration(cdr_obj));
2940 } else if (!strcasecmp(name, "billsec")) {
2941 snprintf(value, length, "%ld", cdr_object_get_billsec(cdr_obj));
2942 } else if (!strcasecmp(name, "disposition")) {
2943 snprintf(value, length, "%d", cdr_obj->disposition);
2944 } else if (!strcasecmp(name, "amaflags")) {
2945 snprintf(value, length, "%d", party_a->amaflags);
2946 } else if (!strcasecmp(name, "accountcode")) {
2947 ast_copy_string(value, party_a->accountcode, length);
2948 } else if (!strcasecmp(name, "peeraccount")) {
2950 ast_copy_string(value, party_b->accountcode, length);
2952 ast_copy_string(value, "", length);
2954 } else if (!strcasecmp(name, "uniqueid")) {
2955 ast_copy_string(value, party_a->uniqueid, length);
2956 } else if (!strcasecmp(name, "linkedid")) {
2957 ast_copy_string(value, cdr_obj->linkedid, length);
2958 } else if (!strcasecmp(name, "userfield")) {
2959 ast_copy_string(value, cdr_obj->party_a.userfield, length);
2960 } else if (!strcasecmp(name, "sequence")) {
2961 snprintf(value, length, "%d", cdr_obj->sequence);
2969 int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
2971 RAII_VAR(struct cdr_object *, cdr,
2972 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
2974 struct cdr_object *cdr_obj;
2977 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
2981 if (ast_strlen_zero(name)) {
2987 cdr_obj = cdr->last;
2988 if (cdr_object_format_property(cdr_obj, name, value, length)) {
2989 /* Property failed; attempt variable */
2990 cdr_object_format_var_internal(cdr_obj, name, value, length);
2998 int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
3000 RAII_VAR(struct cdr_object *, cdr,
3001 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3003 struct cdr_object *it_cdr;
3004 struct ast_var_t *variable;
3006 RAII_VAR(char *, workspace, ast_malloc(256), ast_free);
3007 int total = 0, x = 0, i;
3014 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3018 ast_str_reset(*buf);
3021 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3023 ast_str_append(buf, 0, "\n");
3025 AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
3026 if (!(var = ast_var_name(variable))) {
3030 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
3031 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3038 for (i = 0; cdr_readonly_vars[i]; i++) {
3039 /* null out the workspace, because the cdr_get_tv() won't write anything if time is NULL, so you get old vals */
3041 cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace));
3043 if (!ast_strlen_zero(workspace)
3044 && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
3045 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3055 void ast_cdr_free(struct ast_cdr *cdr)
3058 struct ast_cdr *next = cdr->next;
3060 free_variables(&cdr->varshead);
3066 struct ast_cdr *ast_cdr_alloc(void)
3070 x = ast_calloc(1, sizeof(*x));
3074 const char *ast_cdr_disp2str(int disposition)
3076 switch (disposition) {
3078 return "NO ANSWER"; /* by default, for backward compatibility */
3079 case AST_CDR_NOANSWER:
3081 case AST_CDR_FAILED:
3085 case AST_CDR_ANSWERED:
3087 case AST_CDR_CONGESTION:
3088 return "CONGESTION";
3093 struct party_b_userfield_update {
3094 const char *channel_name;
3095 const char *userfield;
3098 /*! \brief Callback used to update the userfield on Party B on all CDRs */
3099 static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, int flags)
3101 struct cdr_object *cdr = obj;
3102 struct party_b_userfield_update *info = arg;
3103 struct cdr_object *it_cdr;
3104 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3105 if (it_cdr->fn_table == &finalized_state_fn_table) {
3108 if (it_cdr->party_b.snapshot
3109 && !strcmp(it_cdr->party_b.snapshot->name, info->channel_name)) {
3110 strcpy(it_cdr->party_b.userfield, info->userfield);
3116 void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
3118 RAII_VAR(struct cdr_object *, cdr,
3119 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3121 struct party_b_userfield_update party_b_info = {
3122 .channel_name = channel_name,
3123 .userfield = userfield,
3125 struct cdr_object *it_cdr;
3127 /* Handle Party A */
3130 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3131 if (it_cdr->fn_table == &finalized_state_fn_table) {
3134 strcpy(it_cdr->party_a.userfield, userfield);
3139 /* Handle Party B */
3140 ao2_callback(active_cdrs_by_channel, OBJ_NODATA,
3141 cdr_object_update_party_b_userfield_cb,
3146 static void post_cdr(struct ast_cdr *cdr)
3148 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3149 struct cdr_beitem *i;
3151 for (; cdr ; cdr = cdr->next) {
3152 /* For people, who don't want to see unanswered single-channel events */
3153 if (!ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) &&
3154 cdr->disposition < AST_CDR_ANSWERED &&
3155 (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) {
3156 ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel);
3160 if (ast_test_flag(cdr, AST_CDR_FLAG_DISABLE)) {
3163 AST_RWLIST_RDLOCK(&be_list);
3164 AST_RWLIST_TRAVERSE(&be_list, i, list) {
3167 AST_RWLIST_UNLOCK(&be_list);
3171 int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
3173 RAII_VAR(struct cdr_object *, cdr,
3174 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3176 struct cdr_object *it_cdr;
3183 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3184 if (it_cdr->fn_table == &finalized_state_fn_table) {
3187 /* Note: in general, set the flags on both the CDR record as well as the
3188 * Party A. Sometimes all we have is the Party A to look at.
3190 ast_set_flag(&it_cdr->flags, option);
3191 ast_set_flag(&it_cdr->party_a, option);
3198 int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
3200 RAII_VAR(struct cdr_object *, cdr,
3201 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3203 struct cdr_object *it_cdr;
3210 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3211 if (it_cdr->fn_table == &finalized_state_fn_table) {
3214 ast_clear_flag(&it_cdr->flags, option);
3221 int ast_cdr_reset(const char *channel_name, struct ast_flags *options)
3223 RAII_VAR(struct cdr_object *, cdr,
3224 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3226 struct ast_var_t *vardata;
3227 struct cdr_object *it_cdr;
3234 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3235 /* clear variables */
3236 if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3237 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
3238 ast_var_delete(vardata);
3240 if (cdr->party_b.snapshot) {
3241 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
3242 ast_var_delete(vardata);
3247 /* Reset to initial state */
3248 memset(&it_cdr->start, 0, sizeof(it_cdr->start));
3249 memset(&it_cdr->end, 0, sizeof(it_cdr->end));
3250 memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
3251 it_cdr->start = ast_tvnow();
3252 cdr_object_check_party_a_answer(it_cdr);
3259 int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
3261 RAII_VAR(struct cdr_object *, cdr,
3262 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3264 struct cdr_object *new_cdr;
3265 struct cdr_object *it_cdr;
3266 struct cdr_object *cdr_obj;
3273 SCOPED_AO2LOCK(lock, cdr);
3274 cdr_obj = cdr->last;
3275 if (cdr_obj->fn_table == &finalized_state_fn_table) {
3276 /* If the last CDR in the chain is finalized, don't allow a fork -
3277 * things are already dying at this point
3282 /* Copy over the basic CDR information. The Party A information is
3283 * copied over automatically as part of the append
3285 ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->name);
3286 new_cdr = cdr_object_create_and_append(cdr);
3290 new_cdr->fn_table = cdr_obj->fn_table;
3291 ast_string_field_set(new_cdr, bridge, cdr->bridge);
3292 new_cdr->flags = cdr->flags;
3294 /* If there's a Party B, copy it over as well */
3295 if (cdr_obj->party_b.snapshot) {
3296 new_cdr->party_b.snapshot = cdr_obj->party_b.snapshot;
3297 ao2_ref(new_cdr->party_b.snapshot, +1);
3298 strcpy(new_cdr->party_b.userfield, cdr_obj->party_b.userfield);
3299 new_cdr->party_b.flags = cdr_obj->party_b.flags;
3300 if (ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3301 copy_variables(&new_cdr->party_b.variables, &cdr_obj->party_b.variables);
3304 new_cdr->start = cdr_obj->start;
3305 new_cdr->answer = cdr_obj->answer;
3307 /* Modify the times based on the flags passed in */
3308 if (ast_test_flag(options, AST_CDR_FLAG_SET_ANSWER)
3309 && new_cdr->party_a.snapshot->state == AST_STATE_UP) {
3310 new_cdr->answer = ast_tvnow();
3312 if (ast_test_flag(options, AST_CDR_FLAG_RESET)) {
3313 new_cdr->answer = ast_tvnow();
3314 new_cdr->start = ast_tvnow();
3317 /* Create and append, by default, copies over the variables */
3318 if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3319 free_variables(&new_cdr->party_a.variables);
3322 /* Finalize any current CDRs */
3323 if (ast_test_flag(options, AST_CDR_FLAG_FINALIZE)) {
3324 for (it_cdr = cdr; it_cdr != new_cdr; it_cdr = it_cdr->next) {
3325 if (it_cdr->fn_table == &finalized_state_fn_table) {
3328 /* Force finalization on the CDR. This will bypass any checks for
3329 * end before 'h' extension.
3331 cdr_object_finalize(it_cdr);
3332 cdr_object_transition_state(it_cdr, &finalized_state_fn_table);
3340 /*! \note Don't call without cdr_batch_lock */
3341 static void reset_batch(void)
3348 /*! \note Don't call without cdr_batch_lock */
3349 static int init_batch(void)
3351 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
3352 if (!(batch = ast_malloc(sizeof(*batch))))
3360 static void *do_batch_backend_process(void *data)
3362 struct cdr_batch_item *processeditem;
3363 struct cdr_batch_item *batchitem = data;
3365 /* Push each CDR into storage mechanism(s) and free all the memory */
3367 post_cdr(batchitem->cdr);
3368 ast_cdr_free(batchitem->cdr);
3369 processeditem = batchitem;
3370 batchitem = batchitem->next;
3371 ast_free(processeditem);
3377 static void cdr_submit_batch(int do_shutdown)
3379 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3380 struct cdr_batch_item *oldbatchitems = NULL;
3381 pthread_t batch_post_thread = AST_PTHREADT_NULL;
3383 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
3384 if (!batch || !batch->head) {
3388 /* move the old CDRs aside, and prepare a new CDR batch */
3389 ast_mutex_lock(&cdr_batch_lock);
3390 oldbatchitems = batch->head;
3392 ast_mutex_unlock(&cdr_batch_lock);
3394 /* if configured, spawn a new thread to post these CDRs,
3395 also try to save as much as possible if we are shutting down safely */
3396 if (ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SCHEDULER_ONLY) || do_shutdown) {
3397 ast_debug(1, "CDR single-threaded batch processing begins now\n");
3398 do_batch_backend_process(oldbatchitems);
3400 if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
3401 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
3402 do_batch_backend_process(oldbatchitems);
3404 ast_debug(1, "CDR multi-threaded batch processing begins now\n");
3409 static int submit_scheduled_batch(const void *data)
3411 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3412 cdr_submit_batch(0);
3413 /* manually reschedule from this point in time */
3415 ast_mutex_lock(&cdr_sched_lock);
3416 cdr_sched = ast_sched_add(sched, mod_cfg->general->batch_settings.size * 1000, submit_scheduled_batch, NULL);
3417 ast_mutex_unlock(&cdr_sched_lock);
3418 /* returning zero so the scheduler does not automatically reschedule */
3422 /*! Do not hold the batch lock while calling this function */
3423 static void submit_unscheduled_batch(void)
3425 /* Prevent two deletes from happening at the same time */
3426 ast_mutex_lock(&cdr_sched_lock);
3427 /* this is okay since we are not being called from within the scheduler */
3428 AST_SCHED_DEL(sched, cdr_sched);
3429 /* schedule the submission to occur ASAP (1 ms) */
3430 cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
3431 ast_mutex_unlock(&cdr_sched_lock);
3433 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
3434 ast_mutex_lock(&cdr_pending_lock);
3435 ast_cond_signal(&cdr_pending_cond);
3436 ast_mutex_unlock(&cdr_pending_lock);
3439 static void cdr_detach(struct ast_cdr *cdr)
3441 struct cdr_batch_item *newtail;
3443 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3444 int submit_batch = 0;
3450 /* maybe they disabled CDR stuff completely, so just drop it */
3451 if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
3452 ast_debug(1, "Dropping CDR !\n");
3457 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
3458 if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
3464 /* otherwise, each CDR gets put into a batch list (at the end) */
3465 ast_debug(1, "CDR detaching from this thread\n");
3467 /* we'll need a new tail for every CDR */
3468 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
3474 /* don't traverse a whole list (just keep track of the tail) */
3475 ast_mutex_lock(&cdr_batch_lock);
3479 /* new batch is empty, so point the head at the new tail */
3480 batch->head = newtail;
3482 /* already got a batch with something in it, so just append a new tail */
3483 batch->tail->next = newtail;
3486 batch->tail = newtail;
3487 curr = batch->size++;
3489 /* if we have enough stuff to post, then do it */
3490 if (curr >= (mod_cfg->general->batch_settings.size - 1)) {
3493 ast_mutex_unlock(&cdr_batch_lock);
3495 /* Don't call submit_unscheduled_batch with the cdr_batch_lock held */
3497 submit_unscheduled_batch();
3501 static void *do_cdr(void *data)
3503 struct timespec timeout;
3509 schedms = ast_sched_wait(sched);
3510 /* this shouldn't happen, but provide a 1 second default just in case */
3513 now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
3514 timeout.tv_sec = now.tv_sec;
3515 timeout.tv_nsec = now.tv_usec * 1000;
3516 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
3517 ast_mutex_lock(&cdr_pending_lock);
3518 ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
3519 numevents = ast_sched_runq(sched);
3520 ast_mutex_unlock(&cdr_pending_lock);
3521 ast_debug(2, "Processed %d scheduled CDR batches from the run queue\n", numevents);
3527 static char *handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3529 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3533 e->command = "cdr set debug [on|off]";
3534 e->usage = "Enable or disable extra debugging in the CDR Engine. Note\n"
3535 "that this will dump debug information to the VERBOSE setting\n"
3536 "and should only be used when debugging information from the\n"
3537 "CDR engine is needed.\n";
3544 return CLI_SHOWUSAGE;
3547 if (!strcmp(a->argv[3], "on") && !ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3548 ast_set_flag(&mod_cfg->general->settings, CDR_DEBUG);
3549 ast_cli(a->fd, "CDR debugging enabled\n");
3550 } else if (!strcmp(a->argv[3], "off") && ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3551 ast_clear_flag(&mod_cfg->general->settings, CDR_DEBUG);
3552 ast_cli(a->fd, "CDR debugging disabled\n");
3558 /*! \brief Complete user input for 'cdr show' */
3559 static char *cli_complete_show(struct ast_cli_args *a)
3561 char *result = NULL;
3562 int wordlen = strlen(a->word);
3564 struct ao2_iterator it_cdrs;
3565 struct cdr_object *cdr;
3567 it_cdrs = ao2_iterator_init(active_cdrs_by_channel, 0);
3568 while ((cdr = ao2_iterator_next(&it_cdrs))) {
3569 if (!strncasecmp(a->word, cdr->party_a.snapshot->name, wordlen) &&
3571 result = ast_strdup(cdr->party_a.snapshot->name);
3579 ao2_iterator_destroy(&it_cdrs);
3583 static void cli_show_channels(struct ast_cli_args *a)
3585 struct ao2_iterator it_cdrs;
3586 struct cdr_object *cdr;
3587 char start_time_buffer[64];
3588 char answer_time_buffer[64] = "\0";
3589 char end_time_buffer[64];
3591 #define TITLE_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
3592 #define FORMAT_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
3594 ast_cli(a->fd, "\n");
3595 ast_cli(a->fd, "Channels with Call Detail Record (CDR) Information\n");
3596 ast_cli(a->fd, "--------------------------------------------------\n");
3597 ast_cli(a->fd, TITLE_STRING, "Channel", "Dst. Channel", "LastApp", "Start", "Answer", "End", "Billsec", "Duration");
3599 it_cdrs = ao2_iterator_init(active_cdrs_by_channel, 0);
3600 while ((cdr = ao2_iterator_next(&it_cdrs))) {
3601 struct cdr_object *it_cdr;
3602 struct timeval start_time = { 0, };
3603 struct timeval answer_time = { 0, };
3604 struct timeval end_time = { 0, };
3606 SCOPED_AO2LOCK(lock, cdr);
3608 /* Calculate the start, end, answer, billsec, and duration over the
3609 * life of all of the CDR entries
3611 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3612 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
3615 if (ast_tvzero(start_time)) {
3616 start_time = it_cdr->start;
3618 if (!ast_tvzero(it_cdr->answer) && ast_tvzero(answer_time)) {
3619 answer_time = it_cdr->answer;
3623 /* If there was no start time, then all CDRs were for a dialed channel; skip */
3624 if (ast_tvzero(start_time)) {
3630 end_time = ast_tvzero(it_cdr->end) ? ast_tvnow() : it_cdr->end;
3631 cdr_get_tv(start_time, "%T", start_time_buffer, sizeof(start_time_buffer));
3632 cdr_get_tv(answer_time, "%T", answer_time_buffer, sizeof(answer_time_buffer));
3633 cdr_get_tv(end_time, "%T", end_time_buffer, sizeof(end_time_buffer));
3634 ast_cli(a->fd, FORMAT_STRING, it_cdr->party_a.snapshot->name,
3635 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",
3640 ast_tvzero(answer_time) ? 0 : (long)ast_tvdiff_ms(end_time, answer_time) / 1000,
3641 (long)ast_tvdiff_ms(end_time, start_time) / 1000);
3644 ao2_iterator_destroy(&it_cdrs);
3645 #undef FORMAT_STRING
3649 static void cli_show_channel(struct ast_cli_args *a)
3651 struct cdr_object *it_cdr;
3653 char start_time_buffer[64];
3654 char answer_time_buffer[64] = "\0";
3655 char end_time_buffer[64] = "\0";
3656 const char *channel_name = a->argv[3];
3657 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
3659 #define TITLE_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
3660 #define FORMAT_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
3662 cdr = ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY);
3664 ast_cli(a->fd, "Unknown channel: %s\n", channel_name);
3668 ast_cli(a->fd, "\n");
3669 ast_cli(a->fd, "Call Detail Record (CDR) Information for %s\n", channel_name);
3670 ast_cli(a->fd, "--------------------------------------------------\n");
3671 ast_cli(a->fd, TITLE_STRING, "AccountCode", "CallerID", "Dst. Channel", "LastApp", "Data", "Start", "Answer", "End", "Billsec", "Duration");
3674 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3676 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
3679 ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller_name, it_cdr->party_a.snapshot->caller_number, "");
3680 if (ast_tvzero(it_cdr->end)) {
3685 cdr_get_tv(it_cdr->start, "%T", start_time_buffer, sizeof(start_time_buffer));
3686 cdr_get_tv(it_cdr->answer, "%T", answer_time_buffer, sizeof(answer_time_buffer));
3687 cdr_get_tv(end, "%T", end_time_buffer, sizeof(end_time_buffer));
3688 ast_cli(a->fd, FORMAT_STRING,
3689 it_cdr->party_a.snapshot->accountcode,
3691 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",
3697 (long)ast_tvdiff_ms(end, it_cdr->answer) / 1000,
3698 (long)ast_tvdiff_ms(end, it_cdr->start) / 1000);
3701 #undef FORMAT_STRING
3705 static char *handle_cli_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3709 e->command = "cdr show active";
3711 "Usage: cdr show active [channel]\n"
3712 " Displays a summary of all Call Detail Records when [channel]\n"
3713 " is omitted; displays all of the Call Detail Records\n"
3714 " currently in flight for a given [channel] when [channel] is\n"
3716 " Note that this will not display Call Detail Records that\n"
3717 " have already been dispatched to a backend storage, nor for\n"
3718 " channels that are no longer active.\n";
3721 return cli_complete_show(a);
3725 return CLI_SHOWUSAGE;
3726 } else if (a->argc < 4) {
3727 cli_show_channels(a);
3729 cli_show_channel(a);
3735 static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3737 struct cdr_beitem *beitem = NULL;
3738 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3740 long nextbatchtime = 0;
3744 e->command = "cdr show status";
3746 "Usage: cdr show status\n"
3747 " Displays the Call Detail Record engine system status.\n";
3754 return CLI_SHOWUSAGE;
3757 ast_cli(a->fd, "\n");
3758 ast_cli(a->fd, "Call Detail Record (CDR) settings\n");
3759 ast_cli(a->fd, "----------------------------------\n");