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;
696 struct ast_var_t *newvariable;
701 AST_LIST_TRAVERSE(from_list, variables, entries) {
702 var = ast_var_name(variables);
703 if (ast_strlen_zero(var)) {
706 val = ast_var_value(variables);
707 if (ast_strlen_zero(val)) {
710 newvariable = ast_var_assign(var, val);
712 AST_LIST_INSERT_HEAD(to_list, newvariable, entries);
721 * \brief Delete all variables from a variable list
722 * \param headp The head pointer to the variable list to delete
724 static void free_variables(struct varshead *headp)
726 struct ast_var_t *vardata;
728 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
729 ast_var_delete(vardata);
734 * \brief Copy a snapshot and its details
735 * \param dst The destination
736 * \param src The source
738 static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
741 ao2_t_ref(dst->snapshot, -1, "release old snapshot during copy");
743 dst->snapshot = src->snapshot;
744 ao2_t_ref(dst->snapshot, +1, "bump new snapshot during copy");
745 strcpy(dst->userfield, src->userfield);
746 dst->flags = src->flags;
747 copy_variables(&dst->variables, &src->variables);
751 * \brief Transition a \ref cdr_object to a new state
752 * \param cdr The \ref cdr_object to transition
753 * \param fn_table The \ref cdr_object_fn_table state to go to
755 static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
757 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
759 CDR_DEBUG(mod_cfg, "%p - Transitioning CDR for %s from state %s to %s\n",
760 cdr, cdr->party_a.snapshot->name,
761 cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
762 cdr->fn_table = fn_table;
763 if (cdr->fn_table->init_function) {
764 cdr->fn_table->init_function(cdr);
768 * \brief Hash function for containers of CDRs indexing by Party A name */
769 static int cdr_object_channel_hash_fn(const void *obj, const int flags)
771 const struct cdr_object *cdr = obj;
772 const char *name = (flags & OBJ_KEY) ? obj : cdr->name;
773 return ast_str_case_hash(name);
777 * \brief Comparison function for containers of CDRs indexing by Party A name
779 static int cdr_object_channel_cmp_fn(void *obj, void *arg, int flags)
781 struct cdr_object *left = obj;
782 struct cdr_object *right = arg;
783 const char *match = (flags & OBJ_KEY) ? arg : right->name;
784 return strcasecmp(left->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
788 * \brief Comparison function for containers of CDRs indexing by bridge. Note
789 * that we expect there to be collisions, as a single bridge may have multiple
790 * CDRs active at one point in time
792 static int cdr_object_bridge_cmp_fn(void *obj, void *arg, int flags)
794 struct cdr_object *left = obj;
795 struct cdr_object *it_cdr;
796 const char *match = arg;
798 for (it_cdr = left; it_cdr; it_cdr = it_cdr->next) {
799 if (!strcasecmp(it_cdr->bridge, match)) {
807 * \brief \ref cdr_object Destructor
809 static void cdr_object_dtor(void *obj)
811 struct cdr_object *cdr = obj;
812 struct ast_var_t *it_var;
818 ao2_cleanup(cdr->party_a.snapshot);
819 ao2_cleanup(cdr->party_b.snapshot);
820 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_a.variables, entries))) {
821 ast_var_delete(it_var);
823 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_b.variables, entries))) {
824 ast_var_delete(it_var);
826 ast_string_field_free_memory(cdr);
829 ao2_cleanup(cdr->next);
834 * \brief \ref cdr_object constructor
835 * \param chan The \ref ast_channel_snapshot that is the CDR's Party A
837 * This implicitly sets the state of the newly created CDR to the Single state
838 * (\ref single_state_fn_table)
840 static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan)
842 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
843 struct cdr_object *cdr;
845 ast_assert(chan != NULL);
847 cdr = ao2_alloc(sizeof(*cdr), cdr_object_dtor);
852 if (ast_string_field_init(cdr, 64)) {
855 ast_string_field_set(cdr, name, chan->name);
856 ast_string_field_set(cdr, linkedid, chan->linkedid);
857 cdr->disposition = AST_CDR_NULL;
858 cdr->sequence = ast_atomic_fetchadd_int(&global_cdr_sequence, +1);
860 cdr->party_a.snapshot = chan;
861 ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
863 CDR_DEBUG(mod_cfg, "%p - Created CDR for channel %s\n", cdr, chan->name);
865 cdr_object_transition_state(cdr, &single_state_fn_table);
871 * \brief Create a new \ref cdr_object and append it to an existing chain
872 * \param cdr The \ref cdr_object to append to
874 static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr)
876 struct cdr_object *new_cdr;
877 struct cdr_object *it_cdr;
878 struct cdr_object *cdr_last;
880 cdr_last = cdr->last;
881 new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot);
885 new_cdr->disposition = AST_CDR_NULL;
887 /* Copy over the linkedid, as it may have changed */
888 ast_string_field_set(new_cdr, linkedid, cdr_last->linkedid);
889 ast_string_field_set(new_cdr, appl, cdr_last->appl);
890 ast_string_field_set(new_cdr, data, cdr_last->data);
892 /* Copy over other Party A information */
893 cdr_object_snapshot_copy(&new_cdr->party_a, &cdr_last->party_a);
895 /* Append the CDR to the end of the list */
896 for (it_cdr = cdr; it_cdr->next; it_cdr = it_cdr->next) {
897 it_cdr->last = new_cdr;
899 it_cdr->last = new_cdr;
900 it_cdr->next = new_cdr;
906 * \brief Return whether or not a channel has changed its state in the dialplan, subject
907 * to endbeforehexten logic
909 * \param old_snapshot The previous state
910 * \param new_snapshot The new state
912 * \retval 0 if the state has not changed
913 * \retval 1 if the state changed
915 static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
916 struct ast_channel_snapshot *new_snapshot)
918 RAII_VAR(struct module_config *, mod_cfg,
919 ao2_global_obj_ref(module_configs), ao2_cleanup);
921 /* If we ignore hangup logic, don't indicate that we're executing anything new */
922 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
923 && ast_test_flag(&new_snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
927 /* When Party A is originated to an application and the application exits, the stack
928 * will attempt to clear the application and restore the dummy originate application
929 * of "AppDialX". Ignore application changes to AppDialX as a result.
931 if (strcmp(new_snapshot->appl, old_snapshot->appl) && strncasecmp(new_snapshot->appl, "appdial", 7)
932 && (strcmp(new_snapshot->context, old_snapshot->context)
933 || strcmp(new_snapshot->exten, old_snapshot->exten)
934 || new_snapshot->priority != old_snapshot->priority)) {
942 * \brief Return whether or not a \ref ast_channel_snapshot is for a channel
943 * that was created as the result of a dial operation
945 * \retval 0 the channel was not created as the result of a dial
946 * \retval 1 the channel was created as the result of a dial
948 static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
950 return (ast_test_flag(&snapshot->flags, AST_FLAG_OUTGOING)
951 && !(ast_test_flag(&snapshot->flags, AST_FLAG_ORIGINATED)));
955 * \brief Given two CDR snapshots, figure out who should be Party A for the
957 * \param left One of the snapshots
958 * \param right The other snapshot
959 * \retval The snapshot that won
961 static struct cdr_object_snapshot *cdr_object_pick_party_a(struct cdr_object_snapshot *left, struct cdr_object_snapshot *right)
963 /* Check whether or not the party is dialed. A dialed party is never the
964 * Party A with a party that was not dialed.
966 if (!snapshot_is_dialed(left->snapshot) && snapshot_is_dialed(right->snapshot)) {
968 } else if (snapshot_is_dialed(left->snapshot) && !snapshot_is_dialed(right->snapshot)) {
972 /* Try the Party A flag */
973 if (ast_test_flag(left, AST_CDR_FLAG_PARTY_A) && !ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
975 } else if (!ast_test_flag(right, AST_CDR_FLAG_PARTY_A) && ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
979 /* Neither party is dialed and neither has the Party A flag - defer to
981 if (left->snapshot->creationtime.tv_sec < right->snapshot->creationtime.tv_sec) {
983 } else if (left->snapshot->creationtime.tv_sec > right->snapshot->creationtime.tv_sec) {
985 } else if (left->snapshot->creationtime.tv_usec > right->snapshot->creationtime.tv_usec) {
988 /* Okay, fine, take the left one */
994 * Compute the duration for a \ref cdr_object
996 static long cdr_object_get_duration(struct cdr_object *cdr)
998 return (long)(ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->start) / 1000);
1002 * \brief Compute the billsec for a \ref cdr_object
1004 static long cdr_object_get_billsec(struct cdr_object *cdr)
1006 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1009 if (ast_tvzero(cdr->answer)) {
1012 ms = ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->answer);
1013 if (ast_test_flag(&mod_cfg->general->settings, CDR_INITIATED_SECONDS)
1014 && (ms % 1000 >= 500)) {
1015 ms = (ms / 1000) + 1;
1025 * \brief Set a variable on a CDR object
1027 * \param headp The header pointer to the variable to set
1028 * \param name The name of the variable
1029 * \param value The value of the variable
1031 static void set_variable(struct varshead *headp, const char *name, const char *value)
1033 struct ast_var_t *newvariable;
1035 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1036 if (!strcasecmp(ast_var_name(newvariable), name)) {
1037 AST_LIST_REMOVE_CURRENT(entries);
1038 ast_var_delete(newvariable);
1042 AST_LIST_TRAVERSE_SAFE_END;
1044 if (value && (newvariable = ast_var_assign(name, value))) {
1045 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1050 * \brief Create a chain of \ref ast_cdr objects from a chain of \ref cdr_object
1051 * suitable for consumption by the registered CDR backends
1052 * \param cdr The \ref cdr_object to convert to a public record
1053 * \retval A chain of \ref ast_cdr objects on success
1054 * \retval NULL on failure
1056 static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr)
1058 struct ast_cdr *pub_cdr = NULL, *cdr_prev = NULL;
1059 struct cdr_object *it_cdr;
1060 struct ast_var_t *it_var, *it_copy_var;
1061 struct ast_channel_snapshot *party_a;
1062 struct ast_channel_snapshot *party_b;
1064 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1065 struct ast_cdr *cdr_copy;
1067 /* Don't create records for CDRs where the party A was a dialed channel */
1068 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
1072 cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
1078 party_a = it_cdr->party_a.snapshot;
1079 party_b = it_cdr->party_b.snapshot;
1082 ast_assert(party_a != NULL);
1083 ast_copy_string(cdr_copy->accountcode, party_a->accountcode, sizeof(cdr_copy->accountcode));
1084 cdr_copy->amaflags = party_a->amaflags;
1085 ast_copy_string(cdr_copy->channel, party_a->name, sizeof(cdr_copy->channel));
1086 ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller_name, party_a->caller_number, "");
1087 ast_copy_string(cdr_copy->src, party_a->caller_number, sizeof(cdr_copy->src));
1088 ast_copy_string(cdr_copy->uniqueid, party_a->uniqueid, sizeof(cdr_copy->uniqueid));
1089 ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
1090 ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
1091 ast_copy_string(cdr_copy->dst, party_a->exten, sizeof(cdr_copy->dst));
1092 ast_copy_string(cdr_copy->dcontext, party_a->context, sizeof(cdr_copy->dcontext));
1096 ast_copy_string(cdr_copy->dstchannel, party_b->name, sizeof(cdr_copy->dstchannel));
1097 ast_copy_string(cdr_copy->peeraccount, party_b->accountcode, sizeof(cdr_copy->peeraccount));
1098 if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
1099 snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
1102 if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) {
1103 ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield));
1106 /* Timestamps/durations */
1107 cdr_copy->start = it_cdr->start;
1108 cdr_copy->answer = it_cdr->answer;
1109 cdr_copy->end = it_cdr->end;
1110 cdr_copy->billsec = cdr_object_get_billsec(it_cdr);
1111 cdr_copy->duration = cdr_object_get_duration(it_cdr);
1114 ast_copy_flags(cdr_copy, &it_cdr->flags, AST_FLAGS_ALL);
1115 ast_copy_string(cdr_copy->linkedid, it_cdr->linkedid, sizeof(cdr_copy->linkedid));
1116 cdr_copy->disposition = it_cdr->disposition;
1117 cdr_copy->sequence = it_cdr->sequence;
1120 copy_variables(&cdr_copy->varshead, &it_cdr->party_a.variables);
1121 AST_LIST_TRAVERSE(&it_cdr->party_b.variables, it_var, entries) {
1123 struct ast_var_t *newvariable;
1124 AST_LIST_TRAVERSE(&cdr_copy->varshead, it_copy_var, entries) {
1125 if (!strcmp(ast_var_name(it_var), ast_var_name(it_copy_var))) {
1130 if (!found && (newvariable = ast_var_assign(ast_var_name(it_var), ast_var_value(it_var)))) {
1131 AST_LIST_INSERT_TAIL(&cdr_copy->varshead, newvariable, entries);
1139 cdr_prev->next = cdr_copy;
1140 cdr_prev = cdr_copy;
1148 * \brief Dispatch a CDR.
1149 * \param cdr The \ref cdr_object to dispatch
1151 * This will create a \ref ast_cdr object and publish it to the various backends
1153 static void cdr_object_dispatch(struct cdr_object *cdr)
1155 RAII_VAR(struct module_config *, mod_cfg,
1156 ao2_global_obj_ref(module_configs), ao2_cleanup);
1157 struct ast_cdr *pub_cdr;
1159 CDR_DEBUG(mod_cfg, "%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
1160 cdr->party_a.snapshot->name,
1161 cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<none>");
1162 pub_cdr = cdr_object_create_public_records(cdr);
1163 cdr_detach(pub_cdr);
1167 * \brief Set the disposition on a \ref cdr_object based on a hangupcause code
1168 * \param cdr The \ref cdr_object
1169 * \param hangupcause The Asterisk hangup cause code
1171 static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
1173 RAII_VAR(struct module_config *, mod_cfg,
1174 ao2_global_obj_ref(module_configs), ao2_cleanup);
1176 /* Change the disposition based on the hang up cause */
1177 switch (hangupcause) {
1178 case AST_CAUSE_BUSY:
1179 cdr->disposition = AST_CDR_BUSY;
1181 case AST_CAUSE_CONGESTION:
1182 if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
1183 cdr->disposition = AST_CDR_FAILED;
1185 cdr->disposition = AST_CDR_CONGESTION;
1188 case AST_CAUSE_NO_ROUTE_DESTINATION:
1189 case AST_CAUSE_UNREGISTERED:
1190 cdr->disposition = AST_CDR_FAILED;
1192 case AST_CAUSE_NORMAL_CLEARING:
1193 case AST_CAUSE_NO_ANSWER:
1194 cdr->disposition = AST_CDR_NOANSWER;
1202 * \brief Finalize a CDR.
1204 * This function is safe to call multiple times. Note that you can call this
1205 * explicitly before going to the finalized state if there's a chance the CDR
1206 * will be re-activated, in which case the \ref cdr_object's end time should be
1207 * cleared. This function is implicitly called when a CDR transitions to the
1208 * finalized state and right before it is dispatched
1210 * \param cdr_object The CDR to finalize
1212 static void cdr_object_finalize(struct cdr_object *cdr)
1214 RAII_VAR(struct module_config *, mod_cfg,
1215 ao2_global_obj_ref(module_configs), ao2_cleanup);
1217 if (!ast_tvzero(cdr->end)) {
1220 cdr->end = ast_tvnow();
1222 if (cdr->disposition == AST_CDR_NULL) {
1223 if (!ast_tvzero(cdr->answer)) {
1224 cdr->disposition = AST_CDR_ANSWERED;
1225 } else if (cdr->party_a.snapshot->hangupcause) {
1226 cdr_object_set_disposition(cdr, cdr->party_a.snapshot->hangupcause);
1227 } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangupcause) {
1228 cdr_object_set_disposition(cdr, cdr->party_b.snapshot->hangupcause);
1230 cdr->disposition = AST_CDR_FAILED;
1234 /* tv_usec is suseconds_t, which could be int or long */
1235 ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dispo %s\n",
1236 cdr->party_a.snapshot->name,
1238 (long)cdr->start.tv_usec,
1240 (long)cdr->answer.tv_usec,
1242 (long)cdr->end.tv_usec,
1243 ast_cdr_disp2str(cdr->disposition));
1247 * \brief Check to see if a CDR needs to move to the finalized state because
1248 * its Party A hungup.
1250 static void cdr_object_check_party_a_hangup(struct cdr_object *cdr)
1252 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1254 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
1255 && ast_test_flag(&cdr->party_a.snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
1256 cdr_object_finalize(cdr);
1259 if (ast_test_flag(&cdr->party_a.snapshot->flags, AST_FLAG_DEAD)
1260 && cdr->fn_table != &finalized_state_fn_table) {
1261 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1266 * \brief Check to see if a CDR needs to be answered based on its Party A.
1267 * Note that this is safe to call as much as you want - we won't answer twice
1269 static void cdr_object_check_party_a_answer(struct cdr_object *cdr) {
1270 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1272 if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
1273 cdr->answer = ast_tvnow();
1274 /* tv_usec is suseconds_t, which could be int or long */
1275 CDR_DEBUG(mod_cfg, "%p - Set answered time to %ld.%06ld\n", cdr,
1277 (long)cdr->answer.tv_usec);
1281 /* \brief Set Caller ID information on a CDR */
1282 static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
1284 if (!old_snapshot->snapshot) {
1285 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
1286 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
1287 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
1290 if (!strcmp(old_snapshot->snapshot->caller_dnid, new_snapshot->caller_dnid)) {
1291 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
1293 if (!strcmp(old_snapshot->snapshot->caller_subaddr, new_snapshot->caller_subaddr)) {
1294 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
1296 if (!strcmp(old_snapshot->snapshot->dialed_subaddr, new_snapshot->dialed_subaddr)) {
1297 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
1302 * \brief Swap an old \ref cdr_object_snapshot's \ref ast_channel_snapshot for
1303 * a new \ref ast_channel_snapshot
1304 * \param old_snapshot The old \ref cdr_object_snapshot
1305 * \param new_snapshot The new \ref ast_channel_snapshot for old_snapshot
1307 static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot,
1308 struct ast_channel_snapshot *new_snapshot)
1310 cdr_object_update_cid(old_snapshot, new_snapshot);
1311 if (old_snapshot->snapshot) {
1312 ao2_t_ref(old_snapshot->snapshot, -1, "Drop ref for swap");
1314 ao2_t_ref(new_snapshot, +1, "Bump ref for swap");
1315 old_snapshot->snapshot = new_snapshot;
1318 /* BASE METHOD IMPLEMENTATIONS */
1320 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1322 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1324 ast_assert(strcmp(snapshot->name, cdr->party_a.snapshot->name) == 0);
1325 cdr_object_swap_snapshot(&cdr->party_a, snapshot);
1327 /* When Party A is originated to an application and the application exits, the stack
1328 * will attempt to clear the application and restore the dummy originate application
1329 * of "AppDialX". Prevent that, and any other application changes we might not want
1332 if (!ast_strlen_zero(snapshot->appl)
1333 && (strncasecmp(snapshot->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))
1334 && !ast_test_flag(&cdr->flags, AST_CDR_LOCK_APP)) {
1335 ast_string_field_set(cdr, appl, snapshot->appl);
1336 ast_string_field_set(cdr, data, snapshot->data);
1339 ast_string_field_set(cdr, linkedid, snapshot->linkedid);
1340 cdr_object_check_party_a_answer(cdr);
1341 cdr_object_check_party_a_hangup(cdr);
1346 static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1348 /* In general, most things shouldn't get a bridge leave */
1353 static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1355 /* In general, most things shouldn't get a dial end. */
1360 static enum process_bridge_enter_results base_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1362 /* Base process bridge enter simply indicates that we can't handle it */
1363 return BRIDGE_ENTER_NEED_CDR;
1366 static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
1368 char park_info[128];
1370 ast_assert(!strcmp(parking_info->parkee->name, cdr->party_a.snapshot->name));
1372 /* Update Party A information regardless */
1373 cdr->fn_table->process_party_a(cdr, parking_info->parkee);
1375 /* Fake out where we're parked */
1376 ast_string_field_set(cdr, appl, "Park");
1377 snprintf(park_info, sizeof(park_info), "%s:%u", parking_info->parkinglot, parking_info->parkingspace);
1378 ast_string_field_set(cdr, data, park_info);
1380 /* Prevent any further changes to the App/Data fields for this record */
1381 ast_set_flag(&cdr->flags, AST_CDR_LOCK_APP);
1388 static void single_state_init_function(struct cdr_object *cdr) {
1389 cdr->start = ast_tvnow();
1390 cdr_object_check_party_a_answer(cdr);
1393 static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1395 /* This should never happen! */
1396 ast_assert(cdr->party_b.snapshot == NULL);
1401 static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1403 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1405 if (caller && !strcmp(cdr->party_a.snapshot->name, caller->name)) {
1406 cdr_object_swap_snapshot(&cdr->party_a, caller);
1407 CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr,
1408 cdr->party_a.snapshot->name);
1409 cdr_object_swap_snapshot(&cdr->party_b, peer);
1410 CDR_DEBUG(mod_cfg, "%p - Updated Party B %s snapshot\n", cdr,
1411 cdr->party_b.snapshot->name);
1412 } else if (!strcmp(cdr->party_a.snapshot->name, peer->name)) {
1413 /* We're the entity being dialed, i.e., outbound origination */
1414 cdr_object_swap_snapshot(&cdr->party_a, peer);
1415 CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr,
1416 cdr->party_a.snapshot->name);
1419 cdr_object_transition_state(cdr, &dial_state_fn_table);
1424 * \brief Handle a comparison between our \ref cdr_object and a \ref cdr_object
1425 * already in the bridge while in the Single state. The goal of this is to find
1426 * a Party B for our CDR.
1428 * \param cdr Our \ref cdr_object in the Single state
1429 * \param cand_cdr The \ref cdr_object already in the Bridge state
1431 * \retval 0 The cand_cdr had a Party A or Party B that we could use as our
1433 * \retval 1 No party in the cand_cdr could be used as our Party B
1435 static int single_state_bridge_enter_comparison(struct cdr_object *cdr,
1436 struct cdr_object *cand_cdr)
1438 struct cdr_object_snapshot *party_a;
1440 /* Don't match on ourselves */
1441 if (!strcmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)) {
1445 /* Try the candidate CDR's Party A first */
1446 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
1447 if (!strcmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
1448 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1449 if (!cand_cdr->party_b.snapshot) {
1450 /* We just stole them - finalize their CDR. Note that this won't
1451 * transition their state, it just sets the end time and the
1452 * disposition - if we need to re-activate them later, we can.
1454 cdr_object_finalize(cand_cdr);
1459 /* Try their Party B, unless it's us */
1460 if (!cand_cdr->party_b.snapshot || !strcmp(cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name)) {
1463 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
1464 if (!strcmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
1465 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
1472 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)
1474 struct ao2_iterator *it_cdrs;
1475 struct cdr_object *cand_cdr_master;
1476 char *bridge_id = ast_strdupa(bridge->uniqueid);
1479 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1481 /* Get parties in the bridge */
1482 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
1483 cdr_object_bridge_cmp_fn, bridge_id);
1485 /* No one in the bridge yet! */
1486 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1487 return BRIDGE_ENTER_ONLY_PARTY;
1490 while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
1491 struct cdr_object *cand_cdr;
1492 RAII_VAR(struct cdr_object *, cdr_cleanup, cand_cdr_master, ao2_cleanup);
1493 SCOPED_AO2LOCK(lock, cand_cdr_master);
1495 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1496 /* Skip any records that are not in a bridge or in this bridge.
1497 * I'm not sure how that would happen, but it pays to be careful. */
1498 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1499 strcmp(cdr->bridge, cand_cdr->bridge)) {
1503 if (single_state_bridge_enter_comparison(cdr, cand_cdr)) {
1506 /* We successfully got a party B - break out */
1511 ao2_iterator_destroy(it_cdrs);
1513 /* We always transition state, even if we didn't get a peer */
1514 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1516 /* Success implies that we have a Party B */
1518 return BRIDGE_ENTER_OBTAINED_PARTY_B;
1521 return BRIDGE_ENTER_NO_PARTY_B;
1524 static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1526 cdr_object_transition_state(cdr, &parked_state_fn_table);
1533 static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1535 ast_assert(snapshot != NULL);
1537 if (!cdr->party_b.snapshot || strcmp(cdr->party_b.snapshot->name, snapshot->name)) {
1540 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1542 /* If party B hangs up, finalize this CDR */
1543 if (ast_test_flag(&cdr->party_b.snapshot->flags, AST_FLAG_DEAD)) {
1544 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1548 static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1550 /* Don't process a begin dial here. A party A already in the dial state will
1551 * who receives a dial begin for something else will be handled by the
1552 * message router callback and will add a new CDR for the party A */
1558 * \brief Convert a dial status to a CDR disposition
1560 static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
1562 RAII_VAR(struct module_config *, mod_cfg,
1563 ao2_global_obj_ref(module_configs), ao2_cleanup);
1565 if (!strcmp(dial_status, "ANSWER")) {
1566 return AST_CDR_ANSWERED;
1567 } else if (!strcmp(dial_status, "BUSY")) {
1568 return AST_CDR_BUSY;
1569 } else if (!strcmp(dial_status, "CANCEL") || !strcmp(dial_status, "NOANSWER")) {
1570 return AST_CDR_NOANSWER;
1571 } else if (!strcmp(dial_status, "CONGESTION")) {
1572 if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
1573 return AST_CDR_FAILED;
1575 return AST_CDR_CONGESTION;
1577 } else if (!strcmp(dial_status, "FAILED")) {
1578 return AST_CDR_FAILED;
1580 return AST_CDR_FAILED;
1583 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)
1585 RAII_VAR(struct module_config *, mod_cfg,
1586 ao2_global_obj_ref(module_configs), ao2_cleanup);
1587 struct ast_channel_snapshot *party_a;
1594 ast_assert(!strcmp(cdr->party_a.snapshot->name, party_a->name));
1595 cdr_object_swap_snapshot(&cdr->party_a, party_a);
1597 if (cdr->party_b.snapshot) {
1598 if (strcmp(cdr->party_b.snapshot->name, peer->name)) {
1599 /* Not the status for this CDR - defer back to the message router */
1602 cdr_object_swap_snapshot(&cdr->party_b, peer);
1605 /* Set the disposition based on the dial string. */
1606 cdr->disposition = dial_status_to_disposition(dial_status);
1607 if (cdr->disposition == AST_CDR_ANSWERED) {
1608 /* Switch to dial pending to wait and see what the caller does */
1609 cdr_object_transition_state(cdr, &dialed_pending_state_fn_table);
1611 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1617 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)
1619 struct ao2_iterator *it_cdrs;
1620 char *bridge_id = ast_strdupa(bridge->uniqueid);
1621 struct cdr_object *cand_cdr_master;
1624 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1626 /* Get parties in the bridge */
1627 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
1628 cdr_object_bridge_cmp_fn, bridge_id);
1630 /* No one in the bridge yet! */
1631 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1632 return BRIDGE_ENTER_ONLY_PARTY;
1635 while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
1636 struct cdr_object *cand_cdr;
1637 RAII_VAR(struct cdr_object *, cdr_cleanup, cand_cdr_master, ao2_cleanup);
1638 SCOPED_AO2LOCK(lock, cand_cdr_master);
1640 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1641 /* Skip any records that are not in a bridge or in this bridge.
1642 * I'm not sure how that would happen, but it pays to be careful. */
1643 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1644 strcmp(cdr->bridge, cand_cdr->bridge)) {
1648 /* If we don't have a Party B (originated channel), skip it */
1649 if (!cdr->party_b.snapshot) {
1653 /* Skip any records that aren't our Party B */
1654 if (strcmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name)) {
1657 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1658 /* If they have a Party B, they joined up with someone else as their
1659 * Party A. Don't finalize them as they're active. Otherwise, we
1660 * have stolen them so they need to be finalized.
1662 if (!cand_cdr->party_b.snapshot) {
1663 cdr_object_finalize(cand_cdr);
1669 ao2_iterator_destroy(it_cdrs);
1671 /* We always transition state, even if we didn't get a peer */
1672 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1674 /* Success implies that we have a Party B */
1676 return BRIDGE_ENTER_OBTAINED_PARTY_B;
1678 return BRIDGE_ENTER_NO_PARTY_B;
1681 /* DIALED PENDING STATE */
1683 static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1685 /* If we get a CEP change, we're executing dialplan. If we have a Party B
1686 * that means we need a new CDR; otherwise, switch us over to single.
1688 if (snapshot_cep_changed(cdr->party_a.snapshot, snapshot)) {
1689 if (cdr->party_b.snapshot) {
1690 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1691 cdr->fn_table->process_party_a(cdr, snapshot);
1694 cdr_object_transition_state(cdr, &single_state_fn_table);
1695 cdr->fn_table->process_party_a(cdr, snapshot);
1699 base_process_party_a(cdr, snapshot);
1703 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)
1705 cdr_object_transition_state(cdr, &dial_state_fn_table);
1706 return cdr->fn_table->process_bridge_enter(cdr, bridge, channel);
1709 static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1711 /* We can't handle this as we have a Party B - ask for a new one */
1715 static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1717 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1719 /* Ask for a new CDR */
1725 static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1727 if (!cdr->party_b.snapshot || strcmp(cdr->party_b.snapshot->name, snapshot->name)) {
1730 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1732 /* If party B hangs up, finalize this CDR */
1733 if (ast_test_flag(&cdr->party_b.snapshot->flags, AST_FLAG_DEAD)) {
1734 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1738 static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1740 if (strcmp(cdr->bridge, bridge->uniqueid)) {
1743 if (strcmp(cdr->party_a.snapshot->name, channel->name)
1744 && cdr->party_b.snapshot
1745 && strcmp(cdr->party_b.snapshot->name, channel->name)) {
1748 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1755 static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1757 if (strcmp(cdr->party_a.snapshot->name, channel->name)) {
1760 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1765 /* FINALIZED STATE */
1767 static void finalized_state_init_function(struct cdr_object *cdr)
1769 cdr_object_finalize(cdr);
1772 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1774 RAII_VAR(struct module_config *, mod_cfg,
1775 ao2_global_obj_ref(module_configs), ao2_cleanup);
1777 /* If we ignore hangup logic, indicate that we don't need a new CDR */
1778 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
1779 && ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
1783 /* Indicate that, if possible, we should get a new CDR */
1787 /* TOPIC ROUTER CALLBACKS */
1790 * \brief Handler for Stasis-Core dial messages
1791 * \param data Passed on
1792 * \param sub The stasis subscription for this message callback
1793 * \param topic The topic this message was published for
1794 * \param message The message
1796 static void handle_dial_message(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
1798 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1799 struct cdr_object *cdr;
1800 struct ast_multi_channel_blob *payload = stasis_message_data(message);
1801 struct ast_channel_snapshot *caller;
1802 struct ast_channel_snapshot *peer;
1803 struct cdr_object *it_cdr;
1804 struct ast_json *dial_status_blob;
1805 const char *dial_status = NULL;
1808 caller = ast_multi_channel_blob_get_channel(payload, "caller");
1809 peer = ast_multi_channel_blob_get_channel(payload, "peer");
1810 if (!peer && !caller) {
1813 dial_status_blob = ast_json_object_get(ast_multi_channel_blob_get_json(payload), "dialstatus");
1814 if (dial_status_blob) {
1815 dial_status = ast_json_string_get(dial_status_blob);
1818 CDR_DEBUG(mod_cfg, "Dial %s message for %s, %s: %u.%08u\n",
1819 ast_strlen_zero(dial_status) ? "Begin" : "End",
1820 caller ? caller->name : "(none)",
1821 peer ? peer->name : "(none)",
1822 (unsigned int)stasis_message_timestamp(message)->tv_sec,
1823 (unsigned int)stasis_message_timestamp(message)->tv_usec);
1825 /* Figure out who is running this show */
1827 cdr = ao2_find(active_cdrs_by_channel, caller->name, OBJ_KEY);
1829 cdr = ao2_find(active_cdrs_by_channel, peer->name, OBJ_KEY);
1833 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->name : peer->name);
1838 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1839 if (ast_strlen_zero(dial_status)) {
1840 if (!it_cdr->fn_table->process_dial_begin) {
1843 CDR_DEBUG(mod_cfg, "%p - Processing Dial Begin message for channel %s, peer %s\n",
1845 caller ? caller->name : "(none)",
1846 peer ? peer->name : "(none)");
1847 res &= it_cdr->fn_table->process_dial_begin(it_cdr,
1851 if (!it_cdr->fn_table->process_dial_end) {
1854 CDR_DEBUG(mod_cfg, "%p - Processing Dial End message for channel %s, peer %s\n",
1856 caller ? caller->name : "(none)",
1857 peer ? peer->name : "(none)");
1858 it_cdr->fn_table->process_dial_end(it_cdr,
1865 /* If no CDR handled a dial begin message, make a new one */
1866 if (res && ast_strlen_zero(dial_status)) {
1867 struct cdr_object *new_cdr;
1869 new_cdr = cdr_object_create_and_append(cdr);
1873 new_cdr->fn_table->process_dial_begin(new_cdr,
1880 static int cdr_object_finalize_party_b(void *obj, void *arg, int flags)
1882 struct cdr_object *cdr = obj;
1883 struct ast_channel_snapshot *party_b = arg;
1884 struct cdr_object *it_cdr;
1885 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1886 if (it_cdr->party_b.snapshot && !strcmp(it_cdr->party_b.snapshot->name, party_b->name)) {
1887 /* Don't transition to the finalized state - let the Party A do
1888 * that when its ready
1890 cdr_object_finalize(it_cdr);
1896 static int cdr_object_update_party_b(void *obj, void *arg, int flags)
1898 struct cdr_object *cdr = obj;
1899 struct ast_channel_snapshot *party_b = arg;
1900 struct cdr_object *it_cdr;
1901 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1902 if (!it_cdr->fn_table->process_party_b) {
1905 if (it_cdr->party_b.snapshot && !strcmp(it_cdr->party_b.snapshot->name, party_b->name)) {
1906 it_cdr->fn_table->process_party_b(it_cdr, party_b);
1914 * \brief Filter channel snapshots by technology
1916 static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
1918 return snapshot->tech_properties & AST_CHAN_TP_INTERNAL;
1923 * \brief Filter a channel cache update
1925 static int filter_channel_cache_message(struct ast_channel_snapshot *old_snapshot,
1926 struct ast_channel_snapshot *new_snapshot)
1930 /* Drop cache updates from certain channel technologies */
1932 ret |= filter_channel_snapshot(old_snapshot);
1935 ret |= filter_channel_snapshot(new_snapshot);
1941 /*! \brief Determine if we need to add a new CDR based on snapshots */
1942 static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot,
1943 struct ast_channel_snapshot *new_snapshot)
1945 RAII_VAR(struct module_config *, mod_cfg,
1946 ao2_global_obj_ref(module_configs), ao2_cleanup);
1948 if (!new_snapshot) {
1952 if (ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD)) {
1956 /* Auto-fall through will increment the priority but have no application */
1957 if (ast_strlen_zero(new_snapshot->appl)) {
1961 if (old_snapshot && !snapshot_cep_changed(old_snapshot, new_snapshot)) {
1969 * \brief Handler for Stasis-Core channel cache update messages
1970 * \param data Passed on
1971 * \param sub The stasis subscription for this message callback
1972 * \param topic The topic this message was published for
1973 * \param message The message
1975 static void handle_channel_cache_message(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
1977 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
1978 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1979 struct stasis_cache_update *update = stasis_message_data(message);
1980 struct ast_channel_snapshot *old_snapshot;
1981 struct ast_channel_snapshot *new_snapshot;
1983 struct cdr_object *it_cdr;
1985 ast_assert(update != NULL);
1986 ast_assert(ast_channel_snapshot_type() == update->type);
1988 old_snapshot = stasis_message_data(update->old_snapshot);
1989 new_snapshot = stasis_message_data(update->new_snapshot);
1990 name = new_snapshot ? new_snapshot->name : old_snapshot->name;
1992 if (filter_channel_cache_message(old_snapshot, new_snapshot)) {
1996 CDR_DEBUG(mod_cfg, "Channel Update message for %s: %u.%08u\n",
1998 (unsigned int)stasis_message_timestamp(message)->tv_sec,
1999 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2001 if (new_snapshot && !old_snapshot) {
2002 cdr = cdr_object_alloc(new_snapshot);
2006 ao2_link(active_cdrs_by_channel, cdr);
2009 /* Handle Party A */
2011 cdr = ao2_find(active_cdrs_by_channel, name, OBJ_KEY);
2014 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", name);
2019 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2020 if (!it_cdr->fn_table->process_party_a) {
2023 CDR_DEBUG(mod_cfg, "%p - Processing new channel snapshot %s\n", it_cdr, new_snapshot->name);
2024 all_reject &= it_cdr->fn_table->process_party_a(it_cdr, new_snapshot);
2026 if (all_reject && check_new_cdr_needed(old_snapshot, new_snapshot)) {
2027 /* We're not hung up and we have a new snapshot - we need a new CDR */
2028 struct cdr_object *new_cdr;
2029 new_cdr = cdr_object_create_and_append(cdr);
2031 new_cdr->fn_table->process_party_a(new_cdr, new_snapshot);
2035 CDR_DEBUG(mod_cfg, "%p - Beginning finalize/dispatch for %s\n", cdr, old_snapshot->name);
2036 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2037 cdr_object_finalize(it_cdr);
2039 cdr_object_dispatch(cdr);
2040 ao2_unlink(active_cdrs_by_channel, cdr);
2045 /* Handle Party B */
2047 ao2_callback(active_cdrs_by_channel, OBJ_NODATA, cdr_object_update_party_b,
2050 ao2_callback(active_cdrs_by_channel, OBJ_NODATA, cdr_object_finalize_party_b,
2056 struct bridge_leave_data {
2057 struct ast_bridge_snapshot *bridge;
2058 struct ast_channel_snapshot *channel;
2061 /*! \brief Callback used to notify CDRs of a Party B leaving the bridge */
2062 static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, int flags)
2064 struct cdr_object *cdr = obj;
2065 struct bridge_leave_data *leave_data = arg;
2066 struct cdr_object *it_cdr;
2068 if (strcmp(cdr->bridge, leave_data->bridge->uniqueid)) {
2071 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2072 if (it_cdr->fn_table != &bridge_state_fn_table) {
2075 if (!it_cdr->party_b.snapshot) {
2078 if (strcmp(it_cdr->party_b.snapshot->name, leave_data->channel->name)) {
2081 /* It is our Party B, in our bridge. Set the end time and let the handler
2082 * transition our CDR appropriately when we leave the bridge.
2084 cdr_object_finalize(it_cdr);
2089 /*! \brief Filter bridge messages based on bridge technology */
2090 static int filter_bridge_messages(struct ast_bridge_snapshot *bridge)
2092 /* Ignore holding bridge technology messages. We treat this simply as an application
2093 * that a channel enters into.
2095 if (!strcmp(bridge->technology, "holding_bridge") && strcmp(bridge->subclass, "parking")) {
2102 * \brief Handler for when a channel leaves a bridge
2103 * \param data Passed on
2104 * \param sub The stasis subscription for this message callback
2105 * \param topic The topic this message was published for
2106 * \param message The message - hopefully a bridge one!
2108 static void handle_bridge_leave_message(void *data, struct stasis_subscription *sub,
2109 struct stasis_topic *topic, struct stasis_message *message)
2111 struct ast_bridge_blob *update = stasis_message_data(message);
2112 struct ast_bridge_snapshot *bridge = update->bridge;
2113 struct ast_channel_snapshot *channel = update->channel;
2114 RAII_VAR(struct module_config *, mod_cfg,
2115 ao2_global_obj_ref(module_configs), ao2_cleanup);
2116 RAII_VAR(struct cdr_object *, cdr,
2117 ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY),
2119 struct cdr_object *it_cdr;
2120 struct bridge_leave_data leave_data = {
2124 int left_bridge = 0;
2126 if (filter_bridge_messages(bridge)) {
2130 CDR_DEBUG(mod_cfg, "Bridge Leave message for %s: %u.%08u\n",
2132 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2133 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2136 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2142 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2143 if (!it_cdr->fn_table->process_bridge_leave) {
2146 CDR_DEBUG(mod_cfg, "%p - Processing Bridge Leave for %s\n",
2147 it_cdr, channel->name);
2148 if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
2149 ast_string_field_set(it_cdr, bridge, "");
2159 if (strcmp(bridge->subclass, "parking")) {
2161 ao2_callback(active_cdrs_by_channel, OBJ_NODATA,
2162 cdr_object_party_b_left_bridge_cb,
2167 struct bridge_candidate {
2168 struct cdr_object *cdr; /*!< The actual CDR this candidate belongs to, either as A or B */
2169 struct cdr_object_snapshot candidate; /*!< The candidate for a new pairing */
2173 * \brief Comparison function for \ref bridge_candidate objects
2175 static int bridge_candidate_cmp_fn(void *obj, void *arg, int flags)
2177 struct bridge_candidate *left = obj;
2178 struct bridge_candidate *right = arg;
2179 const char *match = (flags & OBJ_KEY) ? arg : right->candidate.snapshot->name;
2180 return strcasecmp(left->candidate.snapshot->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
2184 * \brief Hash function for \ref bridge_candidate objects
2186 static int bridge_candidate_hash_fn(const void *obj, const int flags)
2188 const struct bridge_candidate *bc = obj;
2189 const char *id = (flags & OBJ_KEY) ? obj : bc->candidate.snapshot->name;
2190 return ast_str_case_hash(id);
2193 /*! \brief \ref bridge_candidate Destructor */
2194 static void bridge_candidate_dtor(void *obj)
2196 struct bridge_candidate *bcand = obj;
2197 ao2_cleanup(bcand->cdr);
2198 ao2_cleanup(bcand->candidate.snapshot);
2199 free_variables(&bcand->candidate.variables);
2203 * \brief \ref bridge_candidate Constructor
2204 * \param cdr The \ref cdr_object that is a candidate for being compared to in
2205 * a bridge operation
2206 * \param candidate The \ref cdr_object_snapshot candidate snapshot in the CDR
2207 * that should be used during the operaton
2209 static struct bridge_candidate *bridge_candidate_alloc(struct cdr_object *cdr, struct cdr_object_snapshot *candidate)
2211 struct bridge_candidate *bcand;
2213 bcand = ao2_alloc(sizeof(*bcand), bridge_candidate_dtor);
2218 ao2_ref(bcand->cdr, +1);
2219 bcand->candidate.flags = candidate->flags;
2220 strcpy(bcand->candidate.userfield, candidate->userfield);
2221 bcand->candidate.snapshot = candidate->snapshot;
2222 ao2_ref(bcand->candidate.snapshot, +1);
2223 copy_variables(&bcand->candidate.variables, &candidate->variables);
2230 * \brief Build and add bridge candidates based on a CDR
2232 * \param bridge_id The ID of the bridge we need candidates for
2233 * \param candidates The container of \ref bridge_candidate objects
2234 * \param cdr The \ref cdr_object that is our candidate
2235 * \param party_a Non-zero if we should look at the Party A channel; 0 if Party B
2237 static void add_candidate_for_bridge(const char *bridge_id,
2238 struct ao2_container *candidates,
2239 struct cdr_object *cdr,
2242 struct cdr_object *it_cdr;
2244 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2245 struct cdr_object_snapshot *party_snapshot;
2246 RAII_VAR(struct bridge_candidate *, bcand, NULL, ao2_cleanup);
2248 party_snapshot = party_a ? &it_cdr->party_a : &it_cdr->party_b;
2250 if (it_cdr->fn_table != &bridge_state_fn_table || strcmp(bridge_id, it_cdr->bridge)) {
2254 if (!party_snapshot->snapshot) {
2258 /* Don't add a party twice */
2259 bcand = ao2_find(candidates, party_snapshot->snapshot->name, OBJ_KEY);
2264 bcand = bridge_candidate_alloc(it_cdr, party_snapshot);
2266 ao2_link(candidates, bcand);
2272 * \brief Create new \ref bridge_candidate objects for each party currently
2274 * \param bridge The \param ast_bridge_snapshot for the bridge we're processing
2276 * Note that we use two passes here instead of one so that we only create a
2277 * candidate for a party B if they are never a party A in the bridge. Otherwise,
2278 * we don't care about them.
2280 static struct ao2_container *create_candidates_for_bridge(struct ast_bridge_snapshot *bridge)
2282 struct ao2_container *candidates = ao2_container_alloc(51, bridge_candidate_hash_fn, bridge_candidate_cmp_fn);
2283 char *bridge_id = ast_strdupa(bridge->uniqueid);
2284 struct ao2_iterator *it_cdrs;
2285 struct cdr_object *cand_cdr_master;
2291 /* For each CDR that has a record in the bridge, get their Party A and
2292 * make them a candidate. Note that we do this in two passes as opposed to one so
2293 * that we give preference CDRs where the channel is Party A */
2294 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
2295 cdr_object_bridge_cmp_fn, bridge_id);
2297 /* No one in the bridge yet! */
2298 ao2_cleanup(candidates);
2301 for (; (cand_cdr_master = ao2_iterator_next(it_cdrs)); ao2_cleanup(cand_cdr_master)) {
2302 SCOPED_AO2LOCK(lock, cand_cdr_master);
2303 add_candidate_for_bridge(bridge->uniqueid, candidates, cand_cdr_master, 1);
2305 ao2_iterator_destroy(it_cdrs);
2306 /* For each CDR that has a record in the bridge, get their Party B and
2307 * make them a candidate. */
2308 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
2309 cdr_object_bridge_cmp_fn, bridge_id);
2311 /* Now it's just an error. */
2312 ao2_cleanup(candidates);
2315 for (; (cand_cdr_master = ao2_iterator_next(it_cdrs)); ao2_cleanup(cand_cdr_master)) {
2316 SCOPED_AO2LOCK(lock, cand_cdr_master);
2317 add_candidate_for_bridge(bridge->uniqueid, candidates, cand_cdr_master, 0);
2319 ao2_iterator_destroy(it_cdrs);
2326 * \brief Create a new CDR, append it to an existing CDR, and update its snapshots
2328 * \note The new CDR will be automatically transitioned to the bridge state
2330 static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
2331 const char *bridge_id,
2332 struct cdr_object_snapshot *party_b)
2334 struct cdr_object *new_cdr;
2336 new_cdr = cdr_object_create_and_append(cdr);
2340 cdr_object_snapshot_copy(&new_cdr->party_b, party_b);
2341 cdr_object_check_party_a_answer(new_cdr);
2342 ast_string_field_set(new_cdr, bridge, cdr->bridge);
2343 cdr_object_transition_state(new_cdr, &bridge_state_fn_table);
2347 * \brief Process a single \ref bridge_candidate. Note that this is called as
2348 * part of an \ref ao2_callback on an \ref ao2_container of \ref bridge_candidate
2349 * objects previously created by \ref create_candidates_for_bridge.
2351 * \param obj The \ref bridge_candidate being processed
2352 * \param arg The \ref cdr_object that is being compared against the candidates
2354 * The purpose of this function is to create the necessary CDR entries as a
2355 * result of \ref cdr_object having entered the same bridge as the CDR
2356 * represented by \ref bridge_candidate.
2358 static int bridge_candidate_process(void *obj, void *arg, int flags)
2360 struct bridge_candidate *bcand = obj;
2361 struct cdr_object *cdr = arg;
2362 struct cdr_object_snapshot *party_a;
2364 /* If the candidate is us or someone we've taken on, pass on by */
2365 if (!strcmp(cdr->party_a.snapshot->name, bcand->candidate.snapshot->name)
2366 || (cdr->party_b.snapshot && !(strcmp(cdr->party_b.snapshot->name, bcand->candidate.snapshot->name)))) {
2369 party_a = cdr_object_pick_party_a(&cdr->party_a, &bcand->candidate);
2370 /* We're party A - make a new CDR, append it to us, and set the candidate as
2372 if (!strcmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
2373 bridge_candidate_add_to_cdr(cdr, cdr->bridge, &bcand->candidate);
2377 /* We're Party B. Check if the candidate is the CDR's Party A. If so, find out if we
2378 * can add ourselves directly as the Party B, or if we need a new CDR. */
2379 if (!strcmp(bcand->cdr->party_a.snapshot->name, bcand->candidate.snapshot->name)) {
2380 if (bcand->cdr->party_b.snapshot
2381 && strcmp(bcand->cdr->party_b.snapshot->name, cdr->party_a.snapshot->name)) {
2382 bridge_candidate_add_to_cdr(bcand->cdr, cdr->bridge, &cdr->party_a);
2384 cdr_object_snapshot_copy(&bcand->cdr->party_b, &cdr->party_a);
2385 /* It's possible that this joined at one point and was never chosen
2386 * as party A. Clear their end time, as it would be set in such a
2389 memset(&bcand->cdr->end, 0, sizeof(bcand->cdr->end));
2392 /* We are Party B to a candidate CDR's Party B. Since a candidate
2393 * CDR will only have a Party B represented here if that channel
2394 * was never a Party A in the bridge, we have to go looking for
2395 * that channel's primary CDR record.
2397 struct cdr_object *b_party = ao2_find(active_cdrs_by_channel, bcand->candidate.snapshot->name, OBJ_KEY);
2399 /* Holy cow - no CDR? */
2400 b_party = cdr_object_alloc(bcand->candidate.snapshot);
2401 cdr_object_snapshot_copy(&b_party->party_a, &bcand->candidate);
2402 cdr_object_snapshot_copy(&b_party->party_b, &cdr->party_a);
2403 cdr_object_check_party_a_answer(b_party);
2404 ast_string_field_set(b_party, bridge, cdr->bridge);
2405 cdr_object_transition_state(b_party, &bridge_state_fn_table);
2406 ao2_link(active_cdrs_by_channel, b_party);
2408 bridge_candidate_add_to_cdr(b_party, cdr->bridge, &cdr->party_a);
2410 ao2_ref(b_party, -1);
2417 * \brief Handle creating bridge pairings for the \ref cdr_object that just
2419 * \param cdr The \ref cdr_object that just entered the bridge
2420 * \param bridge The \ref ast_bridge_snapshot representing the bridge it just entered
2422 static void handle_bridge_pairings(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge)
2424 RAII_VAR(struct ao2_container *, candidates,
2425 create_candidates_for_bridge(bridge),
2431 ao2_callback(candidates, OBJ_NODATA,
2432 bridge_candidate_process,
2438 /*! \brief Handle entering into a parking bridge
2439 * \param cdr The CDR to operate on
2440 * \param bridge The bridge the channel just entered
2441 * \param channel The channel snapshot
2443 static void handle_parking_bridge_enter_message(struct cdr_object *cdr,
2444 struct ast_bridge_snapshot *bridge,
2445 struct ast_channel_snapshot *channel)
2447 RAII_VAR(struct module_config *, mod_cfg,
2448 ao2_global_obj_ref(module_configs), ao2_cleanup);
2450 struct cdr_object *it_cdr;
2451 struct cdr_object *new_cdr;
2455 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2456 if (it_cdr->fn_table->process_parking_bridge_enter) {
2457 res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
2459 if (it_cdr->fn_table->process_party_a) {
2460 CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr,
2462 it_cdr->fn_table->process_party_a(it_cdr, channel);
2467 /* No one handled it - we need a new one! */
2468 new_cdr = cdr_object_create_and_append(cdr);
2470 /* Let the single state transition us to Parked */
2471 cdr_object_transition_state(new_cdr, &single_state_fn_table);
2472 new_cdr->fn_table->process_parking_bridge_enter(new_cdr, bridge, channel);
2478 /*! \brief Handle a bridge enter message for a 'normal' bridge
2479 * \param cdr The CDR to operate on
2480 * \param bridge The bridge the channel just entered
2481 * \param channel The channel snapshot
2483 static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
2484 struct ast_bridge_snapshot *bridge,
2485 struct ast_channel_snapshot *channel)
2487 RAII_VAR(struct module_config *, mod_cfg,
2488 ao2_global_obj_ref(module_configs), ao2_cleanup);
2489 enum process_bridge_enter_results result;
2490 struct cdr_object *it_cdr;
2491 struct cdr_object *new_cdr;
2492 struct cdr_object *handled_cdr = NULL;
2496 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2497 if (it_cdr->fn_table->process_party_a) {
2498 CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr,
2500 it_cdr->fn_table->process_party_a(it_cdr, channel);
2503 /* Notify all states that they have entered a bridge */
2504 if (it_cdr->fn_table->process_bridge_enter) {
2505 CDR_DEBUG(mod_cfg, "%p - Processing bridge enter for %s\n", it_cdr,
2507 result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
2509 case BRIDGE_ENTER_ONLY_PARTY:
2511 case BRIDGE_ENTER_OBTAINED_PARTY_B:
2513 handled_cdr = it_cdr;
2516 case BRIDGE_ENTER_NEED_CDR:
2519 case BRIDGE_ENTER_NO_PARTY_B:
2520 /* We didn't win on any - end this CDR. If someone else comes in later
2521 * that is Party B to this CDR, it can re-activate this CDR.
2524 handled_cdr = it_cdr;
2526 cdr_object_finalize(cdr);
2532 /* Create the new matchings, but only for either:
2533 * * The first CDR in the chain that handled it. This avoids issues with
2535 * * If no one handled it, the last CDR in the chain. This would occur if
2536 * a CDR joined a bridge and it wasn't Party A for anyone. We still need
2537 * to make pairings with everyone in the bridge.
2540 handle_bridge_pairings(handled_cdr, bridge);
2542 /* Nothing handled it - we need a new one! */
2543 new_cdr = cdr_object_create_and_append(cdr);
2545 /* This is guaranteed to succeed: the new CDR is created in the single state
2546 * and will be able to handle the bridge enter message
2548 handle_standard_bridge_enter_message(cdr, bridge, channel);
2555 * \brief Handler for Stasis-Core bridge enter messages
2556 * \param data Passed on
2557 * \param sub The stasis subscription for this message callback
2558 * \param topic The topic this message was published for
2559 * \param message The message - hopefully a bridge one!
2561 static void handle_bridge_enter_message(void *data, struct stasis_subscription *sub,
2562 struct stasis_topic *topic, struct stasis_message *message)
2564 struct ast_bridge_blob *update = stasis_message_data(message);
2565 struct ast_bridge_snapshot *bridge = update->bridge;
2566 struct ast_channel_snapshot *channel = update->channel;
2567 RAII_VAR(struct cdr_object *, cdr,
2568 ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY),
2570 RAII_VAR(struct module_config *, mod_cfg,
2571 ao2_global_obj_ref(module_configs), ao2_cleanup);
2573 if (filter_bridge_messages(bridge)) {
2577 CDR_DEBUG(mod_cfg, "Bridge Enter message for channel %s: %u.%08u\n",
2579 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2580 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2583 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2587 if (!strcmp(bridge->subclass, "parking")) {
2588 handle_parking_bridge_enter_message(cdr, bridge, channel);
2590 handle_standard_bridge_enter_message(cdr, bridge, channel);
2595 * \brief Handler for when a channel is parked
2596 * \param data Passed on
2597 * \param sub The stasis subscription for this message callback
2598 * \param topic The topic this message was published for
2599 * \param message The message about who got parked
2601 static void handle_parked_call_message(void *data, struct stasis_subscription *sub,
2602 struct stasis_topic *topic, struct stasis_message *message)
2604 struct ast_parked_call_payload *payload = stasis_message_data(message);
2605 struct ast_channel_snapshot *channel = payload->parkee;
2606 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
2607 RAII_VAR(struct module_config *, mod_cfg,
2608 ao2_global_obj_ref(module_configs), ao2_cleanup);
2609 struct cdr_object *it_cdr;
2611 /* Anything other than getting parked will be handled by other updates */
2612 if (payload->event_type != PARKED_CALL) {
2616 /* No one got parked? */
2621 CDR_DEBUG(mod_cfg, "Parked Call message for channel %s: %u.%08u\n",
2623 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2624 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2626 cdr = ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY);
2628 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2634 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2635 if (it_cdr->fn_table->process_parked_channel) {
2636 it_cdr->fn_table->process_parked_channel(it_cdr, payload);
2644 struct ast_cdr_config *ast_cdr_get_config(void)
2646 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2647 ao2_ref(mod_cfg->general, +1);
2648 return mod_cfg->general;
2651 void ast_cdr_set_config(struct ast_cdr_config *config)
2653 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2654 ao2_cleanup(mod_cfg->general);
2655 mod_cfg->general = config;
2656 ao2_ref(mod_cfg->general, +1);
2659 int ast_cdr_is_enabled(void)
2661 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2662 return ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED);
2665 int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
2667 struct cdr_beitem *i = NULL;
2673 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
2677 AST_RWLIST_WRLOCK(&be_list);
2678 AST_RWLIST_TRAVERSE(&be_list, i, list) {
2679 if (!strcasecmp(name, i->name)) {
2680 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
2681 AST_RWLIST_UNLOCK(&be_list);
2686 if (!(i = ast_calloc(1, sizeof(*i))))
2690 ast_copy_string(i->name, name, sizeof(i->name));
2691 ast_copy_string(i->desc, desc, sizeof(i->desc));
2693 AST_RWLIST_INSERT_HEAD(&be_list, i, list);
2694 AST_RWLIST_UNLOCK(&be_list);
2699 void ast_cdr_unregister(const char *name)
2701 struct cdr_beitem *i = NULL;
2703 AST_RWLIST_WRLOCK(&be_list);
2704 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) {
2705 if (!strcasecmp(name, i->name)) {
2706 AST_RWLIST_REMOVE_CURRENT(list);
2710 AST_RWLIST_TRAVERSE_SAFE_END;
2711 AST_RWLIST_UNLOCK(&be_list);
2714 ast_verb(2, "Unregistered '%s' CDR backend\n", name);
2719 struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
2721 struct ast_cdr *newcdr;
2726 newcdr = ast_cdr_alloc();
2732 AST_LIST_HEAD_INIT_NOLOCK(&newcdr->varshead);
2733 copy_variables(&newcdr->varshead, &cdr->varshead);
2734 newcdr->next = NULL;
2739 static const char *cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
2741 struct ast_var_t *variables;
2743 if (ast_strlen_zero(name)) {
2747 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
2748 if (!strcasecmp(name, ast_var_name(variables))) {
2749 return ast_var_value(variables);
2756 static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
2758 if (fmt == NULL) { /* raw mode */
2759 snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec);
2764 ast_localtime(&when, &tm, NULL);
2765 ast_strftime(buf, bufsize, fmt, &tm);
2770 void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
2772 const char *fmt = "%Y-%m-%d %T";
2781 if (!strcasecmp(name, "clid")) {
2782 ast_copy_string(workspace, cdr->clid, workspacelen);
2783 } else if (!strcasecmp(name, "src")) {
2784 ast_copy_string(workspace, cdr->src, workspacelen);
2785 } else if (!strcasecmp(name, "dst")) {
2786 ast_copy_string(workspace, cdr->dst, workspacelen);
2787 } else if (!strcasecmp(name, "dcontext")) {
2788 ast_copy_string(workspace, cdr->dcontext, workspacelen);
2789 } else if (!strcasecmp(name, "channel")) {
2790 ast_copy_string(workspace, cdr->channel, workspacelen);
2791 } else if (!strcasecmp(name, "dstchannel")) {
2792 ast_copy_string(workspace, cdr->dstchannel, workspacelen);
2793 } else if (!strcasecmp(name, "lastapp")) {
2794 ast_copy_string(workspace, cdr->lastapp, workspacelen);
2795 } else if (!strcasecmp(name, "lastdata")) {
2796 ast_copy_string(workspace, cdr->lastdata, workspacelen);
2797 } else if (!strcasecmp(name, "start")) {
2798 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
2799 } else if (!strcasecmp(name, "answer")) {
2800 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
2801 } else if (!strcasecmp(name, "end")) {
2802 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
2803 } else if (!strcasecmp(name, "duration")) {
2804 snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
2805 } else if (!strcasecmp(name, "billsec")) {
2806 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);
2807 } else if (!strcasecmp(name, "disposition")) {
2809 snprintf(workspace, workspacelen, "%ld", cdr->disposition);
2811 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
2813 } else if (!strcasecmp(name, "amaflags")) {
2815 snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
2817 ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
2819 } else if (!strcasecmp(name, "accountcode")) {
2820 ast_copy_string(workspace, cdr->accountcode, workspacelen);
2821 } else if (!strcasecmp(name, "peeraccount")) {
2822 ast_copy_string(workspace, cdr->peeraccount, workspacelen);
2823 } else if (!strcasecmp(name, "uniqueid")) {
2824 ast_copy_string(workspace, cdr->uniqueid, workspacelen);
2825 } else if (!strcasecmp(name, "linkedid")) {
2826 ast_copy_string(workspace, cdr->linkedid, workspacelen);
2827 } else if (!strcasecmp(name, "userfield")) {
2828 ast_copy_string(workspace, cdr->userfield, workspacelen);
2829 } else if (!strcasecmp(name, "sequence")) {
2830 snprintf(workspace, workspacelen, "%d", cdr->sequence);
2831 } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
2832 ast_copy_string(workspace, varbuf, workspacelen);
2834 workspace[0] = '\0';
2837 if (!ast_strlen_zero(workspace)) {
2844 * \brief Callback that finds all CDRs that reference a particular channel
2846 static int cdr_object_select_all_by_channel_cb(void *obj, void *arg, int flags)
2848 struct cdr_object *cdr = obj;
2849 const char *name = arg;
2851 if (!strcasecmp(cdr->party_a.snapshot->name, name) ||
2852 (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->name, name))) {
2858 /* Read Only CDR variables */
2859 static const char * const cdr_readonly_vars[] = { "clid", "src", "dst", "dcontext",
2860 "channel", "dstchannel", "lastapp", "lastdata", "start", "answer", "end", "duration",
2861 "billsec", "disposition", "amaflags", "accountcode", "uniqueid", "linkedid",
2862 "userfield", "sequence", "total_duration", "total_billsec", "first_start",
2863 "first_answer", NULL };
2865 int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
2867 struct cdr_object *cdr;
2868 struct cdr_object *it_cdr;
2869 struct ao2_iterator *it_cdrs;
2870 char *arg = ast_strdupa(channel_name);
2873 for (x = 0; cdr_readonly_vars[x]; x++) {
2874 if (!strcasecmp(name, cdr_readonly_vars[x])) {
2875 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
2880 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE, cdr_object_select_all_by_channel_cb, arg);
2882 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
2886 for (; (cdr = ao2_iterator_next(it_cdrs)); ao2_unlock(cdr), ao2_cleanup(cdr)) {
2888 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2889 struct varshead *headp = NULL;
2891 if (it_cdr->fn_table == &finalized_state_fn_table) {
2894 if (!strcmp(channel_name, it_cdr->party_a.snapshot->name)) {
2895 headp = &it_cdr->party_a.variables;
2896 } else if (it_cdr->party_b.snapshot && !strcmp(channel_name, it_cdr->party_b.snapshot->name)) {
2897 headp = &it_cdr->party_b.variables;
2900 set_variable(headp, name, value);
2904 ao2_iterator_destroy(it_cdrs);
2910 * \brief Format a variable on a \ref cdr_object
2912 static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
2914 struct ast_var_t *variable;
2916 AST_LIST_TRAVERSE(&cdr->party_a.variables, variable, entries) {
2917 if (!strcasecmp(name, ast_var_name(variable))) {
2918 ast_copy_string(value, ast_var_value(variable), length);
2927 * \brief Format one of the standard properties on a \ref cdr_object
2929 static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
2931 struct ast_channel_snapshot *party_a = cdr_obj->party_a.snapshot;
2932 struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;
2934 if (!strcasecmp(name, "clid")) {
2935 ast_callerid_merge(value, length, party_a->caller_name, party_a->caller_number, "");
2936 } else if (!strcasecmp(name, "src")) {
2937 ast_copy_string(value, party_a->caller_number, length);
2938 } else if (!strcasecmp(name, "dst")) {
2939 ast_copy_string(value, party_a->exten, length);
2940 } else if (!strcasecmp(name, "dcontext")) {
2941 ast_copy_string(value, party_a->context, length);
2942 } else if (!strcasecmp(name, "channel")) {
2943 ast_copy_string(value, party_a->name, length);
2944 } else if (!strcasecmp(name, "dstchannel")) {
2946 ast_copy_string(value, party_b->name, length);
2948 ast_copy_string(value, "", length);
2950 } else if (!strcasecmp(name, "lastapp")) {
2951 ast_copy_string(value, party_a->appl, length);
2952 } else if (!strcasecmp(name, "lastdata")) {
2953 ast_copy_string(value, party_a->data, length);
2954 } else if (!strcasecmp(name, "start")) {
2955 cdr_get_tv(cdr_obj->start, NULL, value, length);
2956 } else if (!strcasecmp(name, "answer")) {
2957 cdr_get_tv(cdr_obj->answer, NULL, value, length);
2958 } else if (!strcasecmp(name, "end")) {
2959 cdr_get_tv(cdr_obj->end, NULL, value, length);
2960 } else if (!strcasecmp(name, "duration")) {
2961 snprintf(value, length, "%ld", cdr_object_get_duration(cdr_obj));
2962 } else if (!strcasecmp(name, "billsec")) {
2963 snprintf(value, length, "%ld", cdr_object_get_billsec(cdr_obj));
2964 } else if (!strcasecmp(name, "disposition")) {
2965 snprintf(value, length, "%d", cdr_obj->disposition);
2966 } else if (!strcasecmp(name, "amaflags")) {
2967 snprintf(value, length, "%d", party_a->amaflags);
2968 } else if (!strcasecmp(name, "accountcode")) {
2969 ast_copy_string(value, party_a->accountcode, length);
2970 } else if (!strcasecmp(name, "peeraccount")) {
2972 ast_copy_string(value, party_b->accountcode, length);
2974 ast_copy_string(value, "", length);
2976 } else if (!strcasecmp(name, "uniqueid")) {
2977 ast_copy_string(value, party_a->uniqueid, length);
2978 } else if (!strcasecmp(name, "linkedid")) {
2979 ast_copy_string(value, cdr_obj->linkedid, length);
2980 } else if (!strcasecmp(name, "userfield")) {
2981 ast_copy_string(value, cdr_obj->party_a.userfield, length);
2982 } else if (!strcasecmp(name, "sequence")) {
2983 snprintf(value, length, "%d", cdr_obj->sequence);
2991 int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
2993 RAII_VAR(struct cdr_object *, cdr,
2994 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
2996 struct cdr_object *cdr_obj;
2999 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3003 if (ast_strlen_zero(name)) {
3009 cdr_obj = cdr->last;
3010 if (cdr_object_format_property(cdr_obj, name, value, length)) {
3011 /* Property failed; attempt variable */
3012 cdr_object_format_var_internal(cdr_obj, name, value, length);
3020 int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
3022 RAII_VAR(struct cdr_object *, cdr,
3023 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3025 struct cdr_object *it_cdr;
3026 struct ast_var_t *variable;
3028 RAII_VAR(char *, workspace, ast_malloc(256), ast_free);
3029 int total = 0, x = 0, i;
3036 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3040 ast_str_reset(*buf);
3043 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3045 ast_str_append(buf, 0, "\n");
3047 AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
3048 if (!(var = ast_var_name(variable))) {
3052 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
3053 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3060 for (i = 0; cdr_readonly_vars[i]; i++) {
3061 /* null out the workspace, because the cdr_get_tv() won't write anything if time is NULL, so you get old vals */
3063 cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace));
3065 if (!ast_strlen_zero(workspace)
3066 && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
3067 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3077 void ast_cdr_free(struct ast_cdr *cdr)
3080 struct ast_cdr *next = cdr->next;
3082 free_variables(&cdr->varshead);
3088 struct ast_cdr *ast_cdr_alloc(void)
3092 x = ast_calloc(1, sizeof(*x));
3096 const char *ast_cdr_disp2str(int disposition)
3098 switch (disposition) {
3100 return "NO ANSWER"; /* by default, for backward compatibility */
3101 case AST_CDR_NOANSWER:
3103 case AST_CDR_FAILED:
3107 case AST_CDR_ANSWERED:
3109 case AST_CDR_CONGESTION:
3110 return "CONGESTION";
3115 struct party_b_userfield_update {
3116 const char *channel_name;
3117 const char *userfield;
3120 /*! \brief Callback used to update the userfield on Party B on all CDRs */
3121 static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, int flags)
3123 struct cdr_object *cdr = obj;
3124 struct party_b_userfield_update *info = arg;
3125 struct cdr_object *it_cdr;
3126 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3127 if (it_cdr->fn_table == &finalized_state_fn_table) {
3130 if (it_cdr->party_b.snapshot
3131 && !strcmp(it_cdr->party_b.snapshot->name, info->channel_name)) {
3132 strcpy(it_cdr->party_b.userfield, info->userfield);
3138 void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
3140 RAII_VAR(struct cdr_object *, cdr,
3141 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3143 struct party_b_userfield_update party_b_info = {
3144 .channel_name = channel_name,
3145 .userfield = userfield,
3147 struct cdr_object *it_cdr;
3149 /* Handle Party A */
3152 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3153 if (it_cdr->fn_table == &finalized_state_fn_table) {
3156 strcpy(it_cdr->party_a.userfield, userfield);
3161 /* Handle Party B */
3162 ao2_callback(active_cdrs_by_channel, OBJ_NODATA,
3163 cdr_object_update_party_b_userfield_cb,
3168 static void post_cdr(struct ast_cdr *cdr)
3170 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3171 struct cdr_beitem *i;
3173 for (; cdr ; cdr = cdr->next) {
3174 /* For people, who don't want to see unanswered single-channel events */
3175 if (!ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) &&
3176 cdr->disposition < AST_CDR_ANSWERED &&
3177 (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) {
3178 ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel);
3182 if (ast_test_flag(cdr, AST_CDR_FLAG_DISABLE)) {
3185 AST_RWLIST_RDLOCK(&be_list);
3186 AST_RWLIST_TRAVERSE(&be_list, i, list) {
3189 AST_RWLIST_UNLOCK(&be_list);
3193 int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
3195 RAII_VAR(struct cdr_object *, cdr,
3196 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3198 struct cdr_object *it_cdr;
3205 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3206 if (it_cdr->fn_table == &finalized_state_fn_table) {
3209 /* Note: in general, set the flags on both the CDR record as well as the
3210 * Party A. Sometimes all we have is the Party A to look at.
3212 ast_set_flag(&it_cdr->flags, option);
3213 ast_set_flag(&it_cdr->party_a, option);
3220 int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
3222 RAII_VAR(struct cdr_object *, cdr,
3223 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3225 struct cdr_object *it_cdr;
3232 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3233 if (it_cdr->fn_table == &finalized_state_fn_table) {
3236 ast_clear_flag(&it_cdr->flags, option);
3243 int ast_cdr_reset(const char *channel_name, struct ast_flags *options)
3245 RAII_VAR(struct cdr_object *, cdr,
3246 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3248 struct ast_var_t *vardata;
3249 struct cdr_object *it_cdr;
3256 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3257 /* clear variables */
3258 if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3259 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
3260 ast_var_delete(vardata);
3262 if (cdr->party_b.snapshot) {
3263 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
3264 ast_var_delete(vardata);
3269 /* Reset to initial state */
3270 memset(&it_cdr->start, 0, sizeof(it_cdr->start));
3271 memset(&it_cdr->end, 0, sizeof(it_cdr->end));
3272 memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
3273 it_cdr->start = ast_tvnow();
3274 cdr_object_check_party_a_answer(it_cdr);
3281 int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
3283 RAII_VAR(struct cdr_object *, cdr,
3284 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3286 struct cdr_object *new_cdr;
3287 struct cdr_object *it_cdr;
3288 struct cdr_object *cdr_obj;
3295 SCOPED_AO2LOCK(lock, cdr);
3296 cdr_obj = cdr->last;
3297 if (cdr_obj->fn_table == &finalized_state_fn_table) {
3298 /* If the last CDR in the chain is finalized, don't allow a fork -
3299 * things are already dying at this point
3304 /* Copy over the basic CDR information. The Party A information is
3305 * copied over automatically as part of the append
3307 ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->name);
3308 new_cdr = cdr_object_create_and_append(cdr);
3312 new_cdr->fn_table = cdr_obj->fn_table;
3313 ast_string_field_set(new_cdr, bridge, cdr->bridge);
3314 new_cdr->flags = cdr->flags;
3316 /* If there's a Party B, copy it over as well */
3317 if (cdr_obj->party_b.snapshot) {
3318 new_cdr->party_b.snapshot = cdr_obj->party_b.snapshot;
3319 ao2_ref(new_cdr->party_b.snapshot, +1);
3320 strcpy(new_cdr->party_b.userfield, cdr_obj->party_b.userfield);
3321 new_cdr->party_b.flags = cdr_obj->party_b.flags;
3322 if (ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3323 copy_variables(&new_cdr->party_b.variables, &cdr_obj->party_b.variables);
3326 new_cdr->start = cdr_obj->start;
3327 new_cdr->answer = cdr_obj->answer;
3329 /* Modify the times based on the flags passed in */
3330 if (ast_test_flag(options, AST_CDR_FLAG_SET_ANSWER)
3331 && new_cdr->party_a.snapshot->state == AST_STATE_UP) {
3332 new_cdr->answer = ast_tvnow();
3334 if (ast_test_flag(options, AST_CDR_FLAG_RESET)) {
3335 new_cdr->answer = ast_tvnow();
3336 new_cdr->start = ast_tvnow();
3339 /* Create and append, by default, copies over the variables */
3340 if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3341 free_variables(&new_cdr->party_a.variables);
3344 /* Finalize any current CDRs */
3345 if (ast_test_flag(options, AST_CDR_FLAG_FINALIZE)) {
3346 for (it_cdr = cdr; it_cdr != new_cdr; it_cdr = it_cdr->next) {
3347 if (it_cdr->fn_table == &finalized_state_fn_table) {
3350 /* Force finalization on the CDR. This will bypass any checks for
3351 * end before 'h' extension.
3353 cdr_object_finalize(it_cdr);
3354 cdr_object_transition_state(it_cdr, &finalized_state_fn_table);
3362 /*! \note Don't call without cdr_batch_lock */
3363 static void reset_batch(void)
3370 /*! \note Don't call without cdr_batch_lock */
3371 static int init_batch(void)
3373 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
3374 if (!(batch = ast_malloc(sizeof(*batch))))
3382 static void *do_batch_backend_process(void *data)
3384 struct cdr_batch_item *processeditem;
3385 struct cdr_batch_item *batchitem = data;
3387 /* Push each CDR into storage mechanism(s) and free all the memory */
3389 post_cdr(batchitem->cdr);
3390 ast_cdr_free(batchitem->cdr);
3391 processeditem = batchitem;
3392 batchitem = batchitem->next;
3393 ast_free(processeditem);
3399 static void cdr_submit_batch(int do_shutdown)
3401 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3402 struct cdr_batch_item *oldbatchitems = NULL;
3403 pthread_t batch_post_thread = AST_PTHREADT_NULL;
3405 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
3406 if (!batch || !batch->head) {
3410 /* move the old CDRs aside, and prepare a new CDR batch */
3411 ast_mutex_lock(&cdr_batch_lock);
3412 oldbatchitems = batch->head;
3414 ast_mutex_unlock(&cdr_batch_lock);
3416 /* if configured, spawn a new thread to post these CDRs,
3417 also try to save as much as possible if we are shutting down safely */
3418 if (ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SCHEDULER_ONLY) || do_shutdown) {
3419 ast_debug(1, "CDR single-threaded batch processing begins now\n");
3420 do_batch_backend_process(oldbatchitems);
3422 if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
3423 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
3424 do_batch_backend_process(oldbatchitems);
3426 ast_debug(1, "CDR multi-threaded batch processing begins now\n");
3431 static int submit_scheduled_batch(const void *data)
3433 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3434 cdr_submit_batch(0);
3435 /* manually reschedule from this point in time */
3437 ast_mutex_lock(&cdr_sched_lock);
3438 cdr_sched = ast_sched_add(sched, mod_cfg->general->batch_settings.size * 1000, submit_scheduled_batch, NULL);
3439 ast_mutex_unlock(&cdr_sched_lock);
3440 /* returning zero so the scheduler does not automatically reschedule */
3444 /*! Do not hold the batch lock while calling this function */
3445 static void submit_unscheduled_batch(void)
3447 /* Prevent two deletes from happening at the same time */
3448 ast_mutex_lock(&cdr_sched_lock);
3449 /* this is okay since we are not being called from within the scheduler */
3450 AST_SCHED_DEL(sched, cdr_sched);
3451 /* schedule the submission to occur ASAP (1 ms) */
3452 cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
3453 ast_mutex_unlock(&cdr_sched_lock);
3455 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
3456 ast_mutex_lock(&cdr_pending_lock);
3457 ast_cond_signal(&cdr_pending_cond);
3458 ast_mutex_unlock(&cdr_pending_lock);
3461 static void cdr_detach(struct ast_cdr *cdr)
3463 struct cdr_batch_item *newtail;
3465 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3466 int submit_batch = 0;
3472 /* maybe they disabled CDR stuff completely, so just drop it */
3473 if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
3474 ast_debug(1, "Dropping CDR !\n");
3479 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
3480 if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
3486 /* otherwise, each CDR gets put into a batch list (at the end) */
3487 ast_debug(1, "CDR detaching from this thread\n");
3489 /* we'll need a new tail for every CDR */
3490 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
3496 /* don't traverse a whole list (just keep track of the tail) */
3497 ast_mutex_lock(&cdr_batch_lock);
3501 /* new batch is empty, so point the head at the new tail */
3502 batch->head = newtail;
3504 /* already got a batch with something in it, so just append a new tail */
3505 batch->tail->next = newtail;
3508 batch->tail = newtail;
3509 curr = batch->size++;
3511 /* if we have enough stuff to post, then do it */
3512 if (curr >= (mod_cfg->general->batch_settings.size - 1)) {
3515 ast_mutex_unlock(&cdr_batch_lock);
3517 /* Don't call submit_unscheduled_batch with the cdr_batch_lock held */
3519 submit_unscheduled_batch();
3523 static void *do_cdr(void *data)
3525 struct timespec timeout;
3531 schedms = ast_sched_wait(sched);
3532 /* this shouldn't happen, but provide a 1 second default just in case */
3535 now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
3536 timeout.tv_sec = now.tv_sec;
3537 timeout.tv_nsec = now.tv_usec * 1000;
3538 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
3539 ast_mutex_lock(&cdr_pending_lock);
3540 ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
3541 numevents = ast_sched_runq(sched);
3542 ast_mutex_unlock(&cdr_pending_lock);
3543 ast_debug(2, "Processed %d scheduled CDR batches from the run queue\n", numevents);
3549 static char *handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3551 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3555 e->command = "cdr set debug [on|off]";
3556 e->usage = "Enable or disable extra debugging in the CDR Engine. Note\n"
3557 "that this will dump debug information to the VERBOSE setting\n"
3558 "and should only be used when debugging information from the\n"
3559 "CDR engine is needed.\n";
3566 return CLI_SHOWUSAGE;
3569 if (!strcmp(a->argv[3], "on") && !ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3570 ast_set_flag(&mod_cfg->general->settings, CDR_DEBUG);
3571 ast_cli(a->fd, "CDR debugging enabled\n");
3572 } else if (!strcmp(a->argv[3], "off") && ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3573 ast_clear_flag(&mod_cfg->general->settings, CDR_DEBUG);
3574 ast_cli(a->fd, "CDR debugging disabled\n");
3580 /*! \brief Complete user input for 'cdr show' */
3581 static char *cli_complete_show(struct ast_cli_args *a)
3583 char *result = NULL;
3584 int wordlen = strlen(a->word);
3586 struct ao2_iterator it_cdrs;
3587 struct cdr_object *cdr;
3589 it_cdrs = ao2_iterator_init(active_cdrs_by_channel, 0);
3590 while ((cdr = ao2_iterator_next(&it_cdrs))) {
3591 if (!strncasecmp(a->word, cdr->party_a.snapshot->name, wordlen) &&
3593 result = ast_strdup(cdr->party_a.snapshot->name);
3601 ao2_iterator_destroy(&it_cdrs);
3605 static void cli_show_channels(struct ast_cli_args *a)
3607 struct ao2_iterator it_cdrs;
3608 struct cdr_object *cdr;
3609 char start_time_buffer[64];
3610 char answer_time_buffer[64] = "\0";
3611 char end_time_buffer[64];
3613 #define TITLE_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
3614 #define FORMAT_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
3616 ast_cli(a->fd, "\n");
3617 ast_cli(a->fd, "Channels with Call Detail Record (CDR) Information\n");
3618 ast_cli(a->fd, "--------------------------------------------------\n");
3619 ast_cli(a->fd, TITLE_STRING, "Channel", "Dst. Channel", "LastApp", "Start", "Answer", "End", "Billsec", "Duration");
3621 it_cdrs = ao2_iterator_init(active_cdrs_by_channel, 0);
3622 for (; (cdr = ao2_iterator_next(&it_cdrs)); ao2_cleanup(cdr)) {
3623 struct cdr_object *it_cdr;
3624 struct timeval start_time = { 0, };
3625 struct timeval answer_time = { 0, };
3626 struct timeval end_time = { 0, };
3628 SCOPED_AO2LOCK(lock, cdr);
3630 /* Calculate the start, end, answer, billsec, and duration over the
3631 * life of all of the CDR entries
3633 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3634 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
3637 if (ast_tvzero(start_time)) {
3638 start_time = it_cdr->start;
3640 if (!ast_tvzero(it_cdr->answer) && ast_tvzero(answer_time)) {
3641 answer_time = it_cdr->answer;
3645 /* If there was no start time, then all CDRs were for a dialed channel; skip */
3646 if (ast_tvzero(start_time)) {
3651 end_time = ast_tvzero(it_cdr->end) ? ast_tvnow() : it_cdr->end;
3652 cdr_get_tv(start_time, "%T", start_time_buffer, sizeof(start_time_buffer));
3653 cdr_get_tv(answer_time, "%T", answer_time_buffer, sizeof(answer_time_buffer));
3654 cdr_get_tv(end_time, "%T", end_time_buffer, sizeof(end_time_buffer));
3655 ast_cli(a->fd, FORMAT_STRING, it_cdr->party_a.snapshot->name,
3656 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",
3661 ast_tvzero(answer_time) ? 0 : (long)ast_tvdiff_ms(end_time, answer_time) / 1000,
3662 (long)ast_tvdiff_ms(end_time, start_time) / 1000);
3664 ao2_iterator_destroy(&it_cdrs);
3665 #undef FORMAT_STRING
3669 static void cli_show_channel(struct ast_cli_args *a)
3671 struct cdr_object *it_cdr;
3673 char start_time_buffer[64];
3674 char answer_time_buffer[64] = "\0";
3675 char end_time_buffer[64] = "\0";
3676 const char *channel_name = a->argv[3];
3677 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
3679 #define TITLE_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
3680 #define FORMAT_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
3682 cdr = ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY);
3684 ast_cli(a->fd, "Unknown channel: %s\n", channel_name);
3688 ast_cli(a->fd, "\n");
3689 ast_cli(a->fd, "Call Detail Record (CDR) Information for %s\n", channel_name);
3690 ast_cli(a->fd, "--------------------------------------------------\n");
3691 ast_cli(a->fd, TITLE_STRING, "AccountCode", "CallerID", "Dst. Channel", "LastApp", "Data", "Start", "Answer", "End", "Billsec", "Duration");
3694 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3696 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
3699 ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller_name, it_cdr->party_a.snapshot->caller_number, "");
3700 if (ast_tvzero(it_cdr->end)) {
3705 cdr_get_tv(it_cdr->start, "%T", start_time_buffer, sizeof(start_time_buffer));
3706 cdr_get_tv(it_cdr->answer, "%T", answer_time_buffer, sizeof(answer_time_buffer));
3707 cdr_get_tv(end, "%T", end_time_buffer, sizeof(end_time_buffer));
3708 ast_cli(a->fd, FORMAT_STRING,
3709 it_cdr->party_a.snapshot->accountcode,
3711 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",
3717 (long)ast_tvdiff_ms(end, it_cdr->answer) / 1000,
3718 (long)ast_tvdiff_ms(end, it_cdr->start) / 1000);
3721 #undef FORMAT_STRING
3725 static char *handle_cli_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3729 e->command = "cdr show active";
3731 "Usage: cdr show active [channel]\n"
3732 " Displays a summary of all Call Detail Records when [channel]\n"
3733 " is omitted; displays all of the Call Detail Records\n"
3734 " currently in flight for a given [channel] when [channel] is\n"
3736 " Note that this will not display Call Detail Records that\n"
3737 " have already been dispatched to a backend storage, nor for\n"
3738 " channels that are no longer active.\n";
3741 return cli_complete_show(a);
3745 return CLI_SHOWUSAGE;
3746 } else if (a->argc < 4) {
3747 cli_show_channels(a);
3749 cli_show_channel(a);
3755 static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3757 struct cdr_beitem *beitem = NULL;
3758 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3760 long nextbatchtime = 0;
3764 e->command = "cdr show status";
3766 "Usage: cdr show status\n"
3767 " Displays the Call Detail Record engine system status.\n";
3774 return CLI_SHOWUSAGE;
3777 ast_cli(a->fd, "\n");
3778 ast_cli(a->fd, "Call Detail Record (CDR) settings\n");
3779 ast_cli(a->fd, "----------------------------------\n");
3780 ast_cli(a->fd, " Logging: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED) ? "Enabled" : "Disabled");
3781 ast_cli(a->fd, " Mode: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE) ? "Batch" : "Simple");