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 /* The prime here should be similar in size to the channel container. */
197 #define NUM_CDR_BUCKETS 61
199 #define NUM_CDR_BUCKETS 769
202 #define DEFAULT_ENABLED "1"
203 #define DEFAULT_BATCHMODE "0"
204 #define DEFAULT_UNANSWERED "0"
205 #define DEFAULT_CONGESTION "0"
206 #define DEFAULT_END_BEFORE_H_EXTEN "0"
207 #define DEFAULT_INITIATED_SECONDS "0"
209 #define DEFAULT_BATCH_SIZE "100"
210 #define MAX_BATCH_SIZE 1000
211 #define DEFAULT_BATCH_TIME "300"
212 #define MAX_BATCH_TIME 86400
213 #define DEFAULT_BATCH_SCHEDULER_ONLY "0"
214 #define DEFAULT_BATCH_SAFE_SHUTDOWN "1"
216 #define CDR_DEBUG(mod_cfg, fmt, ...) \
218 if (ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG)) { \
219 ast_verb(1, (fmt), ##__VA_ARGS__); \
222 static void cdr_detach(struct ast_cdr *cdr);
223 static void cdr_submit_batch(int shutdown);
224 static int cdr_toggle_runtime_options(void);
226 /*! \brief The configuration settings for this module */
227 struct module_config {
228 struct ast_cdr_config *general; /*< CDR global settings */
231 /*! \brief The container for the module configuration */
232 static AO2_GLOBAL_OBJ_STATIC(module_configs);
234 /*! \brief The type definition for general options */
235 static struct aco_type general_option = {
238 .item_offset = offsetof(struct module_config, general),
239 .category = "^general$",
240 .category_match = ACO_WHITELIST,
243 static void *module_config_alloc(void);
244 static void module_config_destructor(void *obj);
246 /*! \brief The file definition */
247 static struct aco_file module_file_conf = {
248 .filename = "cdr.conf",
249 .skip_category = "(^csv$|^custom$|^manager$|^odbc$|^pgsql$|^radius$|^sqlite$|^tds$|^mysql$)",
250 .types = ACO_TYPES(&general_option),
253 CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc,
254 .files = ACO_FILES(&module_file_conf),
257 static struct aco_type *general_options[] = ACO_TYPES(&general_option);
259 /*! \brief Dispose of a module config object */
260 static void module_config_destructor(void *obj)
262 struct module_config *cfg = obj;
267 ao2_ref(cfg->general, -1);
270 /*! \brief Create a new module config object */
271 static void *module_config_alloc(void)
273 struct module_config *mod_cfg;
274 struct ast_cdr_config *cdr_config;
276 mod_cfg = ao2_alloc(sizeof(*mod_cfg), module_config_destructor);
281 cdr_config = ao2_alloc(sizeof(*cdr_config), NULL);
283 ao2_ref(cdr_config, -1);
286 mod_cfg->general = cdr_config;
291 /*! \brief Registration object for CDR backends */
296 AST_RWLIST_ENTRY(cdr_beitem) list;
300 /*! \brief List of registered backends */
301 static AST_RWLIST_HEAD_STATIC(be_list, cdr_beitem);
303 /*! \brief Queued CDR waiting to be batched */
304 struct cdr_batch_item {
306 struct cdr_batch_item *next;
309 /*! \brief The actual batch queue */
310 static struct cdr_batch {
312 struct cdr_batch_item *head;
313 struct cdr_batch_item *tail;
316 /*! \brief The global sequence counter used for CDRs */
317 static int global_cdr_sequence = 0;
319 /*! \brief Scheduler items */
320 static struct ast_sched_context *sched;
321 static int cdr_sched = -1;
322 AST_MUTEX_DEFINE_STATIC(cdr_sched_lock);
323 static pthread_t cdr_thread = AST_PTHREADT_NULL;
325 /*! \brief Lock protecting modifications to the batch queue */
326 AST_MUTEX_DEFINE_STATIC(cdr_batch_lock);
328 /*! \brief These are used to wake up the CDR thread when there's work to do */
329 AST_MUTEX_DEFINE_STATIC(cdr_pending_lock);
330 static ast_cond_t cdr_pending_cond;
332 /*! \brief A container of the active CDRs indexed by Party A channel id */
333 static struct ao2_container *active_cdrs_by_channel;
335 /*! \brief Message router for stasis messages regarding channel state */
336 static struct stasis_message_router *stasis_router;
338 /*! \brief Our subscription for bridges */
339 static struct stasis_forward *bridge_subscription;
341 /*! \brief Our subscription for channels */
342 static struct stasis_forward *channel_subscription;
344 /*! \brief Our subscription for parking */
345 static struct stasis_forward *parking_subscription;
347 /*! \brief The parent topic for all topics we want to aggregate for CDRs */
348 static struct stasis_topic *cdr_topic;
352 /*! \brief Return types for \ref process_bridge_enter functions */
353 enum process_bridge_enter_results {
355 * The CDR was the only party in the bridge.
357 BRIDGE_ENTER_ONLY_PARTY,
359 * The CDR was able to obtain a Party B from some other party already in the bridge
361 BRIDGE_ENTER_OBTAINED_PARTY_B,
363 * The CDR was not able to obtain a Party B
365 BRIDGE_ENTER_NO_PARTY_B,
367 * This CDR can't handle a bridge enter message and a new CDR needs to be created
369 BRIDGE_ENTER_NEED_CDR,
373 * \brief A virtual table used for \ref cdr_object.
375 * Note that all functions are optional - if a subclass does not need an
376 * implementation, it is safe to leave it NULL.
378 struct cdr_object_fn_table {
379 /*! \brief Name of the subclass */
383 * \brief An initialization function. This will be called automatically
384 * when a \ref cdr_object is switched to this type in
385 * \ref cdr_object_transition_state
387 * \param cdr The \ref cdr_object that was just transitioned
389 void (* const init_function)(struct cdr_object *cdr);
392 * \brief Process a Party A update for the \ref cdr_object
394 * \param cdr The \ref cdr_object to process the update
395 * \param snapshot The snapshot for the CDR's Party A
396 * \retval 0 the CDR handled the update or ignored it
397 * \retval 1 the CDR is finalized and a new one should be made to handle it
399 int (* const process_party_a)(struct cdr_object *cdr,
400 struct ast_channel_snapshot *snapshot);
403 * \brief Process a Party B update for the \ref cdr_object
405 * \param cdr The \ref cdr_object to process the update
406 * \param snapshot The snapshot for the CDR's Party B
408 void (* const process_party_b)(struct cdr_object *cdr,
409 struct ast_channel_snapshot *snapshot);
412 * \brief Process the beginning of a dial. A dial message implies one of two
414 * The \ref cdr_object's Party A has been originated
415 * The \ref cdr_object's Party A is dialing its Party B
417 * \param cdr The \ref cdr_object
418 * \param caller The originator of the dial attempt
419 * \param peer The destination of the dial attempt
421 * \retval 0 if the parties in the dial were handled by this CDR
422 * \retval 1 if the parties could not be handled by this CDR
424 int (* const process_dial_begin)(struct cdr_object *cdr,
425 struct ast_channel_snapshot *caller,
426 struct ast_channel_snapshot *peer);
429 * \brief Process the end of a dial. At the end of a dial, a CDR can be
430 * transitioned into one of two states - DialedPending
431 * (\ref dialed_pending_state_fn_table) or Finalized
432 * (\ref finalized_state_fn_table).
434 * \param cdr The \ref cdr_object
435 * \param caller The originator of the dial attempt
436 * \param peer the Destination of the dial attempt
437 * \param dial_status What happened
439 * \retval 0 if the parties in the dial were handled by this CDR
440 * \retval 1 if the parties could not be handled by this CDR
442 int (* const process_dial_end)(struct cdr_object *cdr,
443 struct ast_channel_snapshot *caller,
444 struct ast_channel_snapshot *peer,
445 const char *dial_status);
448 * \brief Process the entering of a bridge by this CDR. The purpose of this
449 * callback is to have the CDR prepare itself for the bridge and attempt to
450 * find a valid Party B. The act of creating new CDRs based on the entering
451 * of this channel into the bridge is handled by the higher level message
454 * Note that this handler is for when a channel enters into a "normal"
455 * bridge, where people actually talk to each other. Parking is its own
458 * \param cdr The \ref cdr_object
459 * \param bridge The bridge that the Party A just entered into
460 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
462 * \retval process_bridge_enter_results Defines whether or not this CDR was able
463 * to fully handle the bridge enter message.
465 enum process_bridge_enter_results (* const process_bridge_enter)(
466 struct cdr_object *cdr,
467 struct ast_bridge_snapshot *bridge,
468 struct ast_channel_snapshot *channel);
471 * \brief Process entering into a parking bridge.
473 * \param cdr The \ref cdr_object
474 * \param bridge The parking bridge that Party A just entered into
475 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
477 * \retval 0 This CDR successfully transitioned itself into the parked state
478 * \retval 1 This CDR couldn't handle the parking transition and we need a
481 int (* const process_parking_bridge_enter)(struct cdr_object *cdr,
482 struct ast_bridge_snapshot *bridge,
483 struct ast_channel_snapshot *channel);
486 * \brief Process the leaving of a bridge by this CDR.
488 * \param cdr The \ref cdr_object
489 * \param bridge The bridge that the Party A just left
490 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
492 * \retval 0 This CDR left successfully
495 int (* const process_bridge_leave)(struct cdr_object *cdr,
496 struct ast_bridge_snapshot *bridge,
497 struct ast_channel_snapshot *channel);
500 * \brief Process an update informing us that the channel got itself parked
502 * \param cdr The \ref cdr_object
503 * \param channel The parking information for this CDR's party A
505 * \retval 0 This CDR successfully parked itself
506 * \retval 1 This CDR couldn't handle the park
508 int (* const process_parked_channel)(struct cdr_object *cdr,
509 struct ast_parked_call_payload *parking_info);
512 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
513 static enum process_bridge_enter_results base_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
514 static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
515 static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
516 static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info);
518 static void single_state_init_function(struct cdr_object *cdr);
519 static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
520 static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
521 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);
522 static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
525 * \brief The virtual table for the Single state.
527 * A \ref cdr_object starts off in this state. This represents a channel that
528 * has no Party B information itself.
530 * A \ref cdr_object from this state can go into any of the following states:
531 * * \ref dial_state_fn_table
532 * * \ref bridge_state_fn_table
533 * * \ref finalized_state_fn_table
535 struct cdr_object_fn_table single_state_fn_table = {
537 .init_function = single_state_init_function,
538 .process_party_a = base_process_party_a,
539 .process_party_b = single_state_process_party_b,
540 .process_dial_begin = single_state_process_dial_begin,
541 .process_dial_end = base_process_dial_end,
542 .process_bridge_enter = single_state_process_bridge_enter,
543 .process_parking_bridge_enter = single_state_process_parking_bridge_enter,
544 .process_bridge_leave = base_process_bridge_leave,
545 .process_parked_channel = base_process_parked_channel,
548 static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
549 static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
550 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);
551 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);
554 * \brief The virtual table for the Dial state.
556 * A \ref cdr_object that has begun a dial operation. This state is entered when
557 * the Party A for a CDR is determined to be dialing out to a Party B or when
558 * a CDR is for an originated channel (in which case the Party A information is
559 * the originated channel, and there is no Party B).
561 * A \ref cdr_object from this state can go in any of the following states:
562 * * \ref dialed_pending_state_fn_table
563 * * \ref bridge_state_fn_table
564 * * \ref finalized_state_fn_table
566 struct cdr_object_fn_table dial_state_fn_table = {
568 .process_party_a = base_process_party_a,
569 .process_party_b = dial_state_process_party_b,
570 .process_dial_begin = dial_state_process_dial_begin,
571 .process_dial_end = dial_state_process_dial_end,
572 .process_bridge_enter = dial_state_process_bridge_enter,
573 .process_bridge_leave = base_process_bridge_leave,
576 static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
577 static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
578 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);
579 static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
582 * \brief The virtual table for the Dialed Pending state.
584 * A \ref cdr_object that has successfully finished a dial operation, but we
585 * don't know what they're going to do yet. It's theoretically possible to dial
586 * a party and then have that party not be bridged with the caller; likewise,
587 * an origination can complete and the channel go off and execute dialplan. The
588 * pending state acts as a bridge between either:
589 * * Entering a bridge
590 * * Getting a new CDR for new dialplan execution
591 * * Switching from being originated to executing dialplan
593 * A \ref cdr_object from this state can go in any of the following states:
594 * * \ref single_state_fn_table
595 * * \ref dialed_pending_state_fn_table
596 * * \ref bridge_state_fn_table
597 * * \ref finalized_state_fn_table
599 struct cdr_object_fn_table dialed_pending_state_fn_table = {
600 .name = "DialedPending",
601 .process_party_a = dialed_pending_state_process_party_a,
602 .process_dial_begin = dialed_pending_state_process_dial_begin,
603 .process_bridge_enter = dialed_pending_state_process_bridge_enter,
604 .process_parking_bridge_enter = dialed_pending_state_process_parking_bridge_enter,
605 .process_bridge_leave = base_process_bridge_leave,
606 .process_parked_channel = base_process_parked_channel,
609 static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
610 static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
613 * \brief The virtual table for the Bridged state
615 * A \ref cdr_object enters this state when it receives notification that the
616 * channel has entered a bridge.
618 * A \ref cdr_object from this state can go to:
619 * * \ref finalized_state_fn_table
621 struct cdr_object_fn_table bridge_state_fn_table = {
623 .process_party_a = base_process_party_a,
624 .process_party_b = bridge_state_process_party_b,
625 .process_bridge_leave = bridge_state_process_bridge_leave,
626 .process_parked_channel = base_process_parked_channel,
629 static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
632 * \brief The virtual table for the Parked state
634 * Parking is weird. Unlike typical bridges, it has to be treated somewhat
635 * uniquely - a channel in a parking bridge (which is a subclass of a holding
636 * bridge) has to be handled as if the channel went into an application.
637 * However, when the channel comes out, we need a new CDR - unlike the Single
640 struct cdr_object_fn_table parked_state_fn_table = {
642 .process_party_a = base_process_party_a,
643 .process_bridge_leave = parked_state_process_bridge_leave,
644 .process_parked_channel = base_process_parked_channel,
647 static void finalized_state_init_function(struct cdr_object *cdr);
648 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
651 * \brief The virtual table for the finalized state.
653 * Once in the finalized state, the CDR is done. No modifications can be made
656 struct cdr_object_fn_table finalized_state_fn_table = {
658 .init_function = finalized_state_init_function,
659 .process_party_a = finalized_state_process_party_a,
660 .process_bridge_enter = base_process_bridge_enter,
663 /*! \brief A wrapper object around a snapshot.
664 * Fields that are mutable by the CDR engine are replicated here.
666 struct cdr_object_snapshot {
667 struct ast_channel_snapshot *snapshot; /*!< The channel snapshot */
668 char userfield[AST_MAX_USER_FIELD]; /*!< Userfield for the channel */
669 unsigned int flags; /*!< Specific flags for this party */
670 struct varshead variables; /*!< CDR variables for the channel */
673 /*! \brief An in-memory representation of an active CDR */
675 struct cdr_object_snapshot party_a; /*!< The Party A information */
676 struct cdr_object_snapshot party_b; /*!< The Party B information */
677 struct cdr_object_fn_table *fn_table; /*!< The current virtual table */
679 enum ast_cdr_disposition disposition; /*!< The disposition of the CDR */
680 struct timeval start; /*!< When this CDR was created */
681 struct timeval answer; /*!< Either when the channel was answered, or when the path between channels was established */
682 struct timeval end; /*!< When this CDR was finalized */
683 unsigned int sequence; /*!< A monotonically increasing number for each CDR */
684 struct ast_flags flags; /*!< Flags on the CDR */
685 AST_DECLARE_STRING_FIELDS(
686 AST_STRING_FIELD(linkedid); /*!< Linked ID. Cached here as it may change out from party A, which must be immutable */
687 AST_STRING_FIELD(uniqueid); /*!< Unique id of party A. Cached here as it is the primary key of this CDR */
688 AST_STRING_FIELD(name); /*!< Channel name of party A. Cached here as the party A address may change */
689 AST_STRING_FIELD(bridge); /*!< The bridge the party A happens to be in. */
690 AST_STRING_FIELD(appl); /*!< The last accepted application party A was in */
691 AST_STRING_FIELD(data); /*!< The data for the last accepted application party A was in */
693 struct cdr_object *next; /*!< The next CDR object in the chain */
694 struct cdr_object *last; /*!< The last CDR object in the chain */
698 * \brief Copy variables from one list to another
699 * \param to_list destination
700 * \param from_list source
701 * \retval The number of copied variables
703 static int copy_variables(struct varshead *to_list, struct varshead *from_list)
705 struct ast_var_t *variables;
706 struct ast_var_t *newvariable;
711 AST_LIST_TRAVERSE(from_list, variables, entries) {
712 var = ast_var_name(variables);
713 if (ast_strlen_zero(var)) {
716 val = ast_var_value(variables);
717 if (ast_strlen_zero(val)) {
720 newvariable = ast_var_assign(var, val);
722 AST_LIST_INSERT_HEAD(to_list, newvariable, entries);
731 * \brief Delete all variables from a variable list
732 * \param headp The head pointer to the variable list to delete
734 static void free_variables(struct varshead *headp)
736 struct ast_var_t *vardata;
738 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
739 ast_var_delete(vardata);
744 * \brief Copy a snapshot and its details
745 * \param dst The destination
746 * \param src The source
748 static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
751 ao2_t_ref(dst->snapshot, -1, "release old snapshot during copy");
753 dst->snapshot = src->snapshot;
754 ao2_t_ref(dst->snapshot, +1, "bump new snapshot during copy");
755 strcpy(dst->userfield, src->userfield);
756 dst->flags = src->flags;
757 copy_variables(&dst->variables, &src->variables);
761 * \brief Transition a \ref cdr_object to a new state
762 * \param cdr The \ref cdr_object to transition
763 * \param fn_table The \ref cdr_object_fn_table state to go to
765 static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
767 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
769 CDR_DEBUG(mod_cfg, "%p - Transitioning CDR for %s from state %s to %s\n",
770 cdr, cdr->party_a.snapshot->name,
771 cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
772 cdr->fn_table = fn_table;
773 if (cdr->fn_table->init_function) {
774 cdr->fn_table->init_function(cdr);
778 * \brief Hash function for containers of CDRs indexing by Party A uniqueid */
779 static int cdr_object_channel_hash_fn(const void *obj, const int flags)
781 const struct cdr_object *cdr;
784 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
796 return ast_str_case_hash(key);
800 * \brief Comparison function for containers of CDRs indexing by Party A uniqueid
802 static int cdr_object_channel_cmp_fn(void *obj, void *arg, int flags)
804 struct cdr_object *left = obj;
805 struct cdr_object *right = arg;
806 const char *right_key = arg;
809 switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
811 right_key = right->uniqueid;
814 cmp = strcmp(left->uniqueid, right_key);
816 case OBJ_PARTIAL_KEY:
818 * We could also use a partial key struct containing a length
819 * so strlen() does not get called for every comparison instead.
821 cmp = strncmp(left->uniqueid, right_key, strlen(right_key));
824 /* Sort can only work on something with a full or partial key. */
829 return cmp ? 0 : CMP_MATCH;
833 * \brief \ref cdr_object Destructor
835 static void cdr_object_dtor(void *obj)
837 struct cdr_object *cdr = obj;
838 struct ast_var_t *it_var;
840 ao2_cleanup(cdr->party_a.snapshot);
841 ao2_cleanup(cdr->party_b.snapshot);
842 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_a.variables, entries))) {
843 ast_var_delete(it_var);
845 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_b.variables, entries))) {
846 ast_var_delete(it_var);
848 ast_string_field_free_memory(cdr);
850 ao2_cleanup(cdr->next);
854 * \brief \ref cdr_object constructor
855 * \param chan The \ref ast_channel_snapshot that is the CDR's Party A
857 * This implicitly sets the state of the newly created CDR to the Single state
858 * (\ref single_state_fn_table)
860 static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan)
862 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
863 struct cdr_object *cdr;
865 ast_assert(chan != NULL);
867 cdr = ao2_alloc(sizeof(*cdr), cdr_object_dtor);
872 if (ast_string_field_init(cdr, 64)) {
876 ast_string_field_set(cdr, uniqueid, chan->uniqueid);
877 ast_string_field_set(cdr, name, chan->name);
878 ast_string_field_set(cdr, linkedid, chan->linkedid);
879 cdr->disposition = AST_CDR_NULL;
880 cdr->sequence = ast_atomic_fetchadd_int(&global_cdr_sequence, +1);
882 cdr->party_a.snapshot = chan;
883 ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
885 CDR_DEBUG(mod_cfg, "%p - Created CDR for channel %s\n", cdr, chan->name);
887 cdr_object_transition_state(cdr, &single_state_fn_table);
893 * \brief Create a new \ref cdr_object and append it to an existing chain
894 * \param cdr The \ref cdr_object to append to
896 static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr)
898 struct cdr_object *new_cdr;
899 struct cdr_object *it_cdr;
900 struct cdr_object *cdr_last;
902 cdr_last = cdr->last;
903 new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot);
907 new_cdr->disposition = AST_CDR_NULL;
909 /* Copy over the linkedid, as it may have changed */
910 ast_string_field_set(new_cdr, linkedid, cdr_last->linkedid);
911 ast_string_field_set(new_cdr, appl, cdr_last->appl);
912 ast_string_field_set(new_cdr, data, cdr_last->data);
914 /* Copy over other Party A information */
915 cdr_object_snapshot_copy(&new_cdr->party_a, &cdr_last->party_a);
917 /* Append the CDR to the end of the list */
918 for (it_cdr = cdr; it_cdr->next; it_cdr = it_cdr->next) {
919 it_cdr->last = new_cdr;
921 it_cdr->last = new_cdr;
922 it_cdr->next = new_cdr;
928 * \brief Return whether or not a channel has changed its state in the dialplan, subject
929 * to endbeforehexten logic
931 * \param old_snapshot The previous state
932 * \param new_snapshot The new state
934 * \retval 0 if the state has not changed
935 * \retval 1 if the state changed
937 static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
938 struct ast_channel_snapshot *new_snapshot)
940 RAII_VAR(struct module_config *, mod_cfg,
941 ao2_global_obj_ref(module_configs), ao2_cleanup);
943 /* If we ignore hangup logic, don't indicate that we're executing anything new */
944 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
945 && ast_test_flag(&new_snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
949 /* When Party A is originated to an application and the application exits, the stack
950 * will attempt to clear the application and restore the dummy originate application
951 * of "AppDialX". Ignore application changes to AppDialX as a result.
953 if (strcmp(new_snapshot->appl, old_snapshot->appl) && strncasecmp(new_snapshot->appl, "appdial", 7)
954 && (strcmp(new_snapshot->context, old_snapshot->context)
955 || strcmp(new_snapshot->exten, old_snapshot->exten)
956 || new_snapshot->priority != old_snapshot->priority)) {
964 * \brief Return whether or not a \ref ast_channel_snapshot is for a channel
965 * that was created as the result of a dial operation
967 * \retval 0 the channel was not created as the result of a dial
968 * \retval 1 the channel was created as the result of a dial
970 static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
972 return (ast_test_flag(&snapshot->flags, AST_FLAG_OUTGOING)
973 && !(ast_test_flag(&snapshot->flags, AST_FLAG_ORIGINATED)));
977 * \brief Given two CDR snapshots, figure out who should be Party A for the
979 * \param left One of the snapshots
980 * \param right The other snapshot
981 * \retval The snapshot that won
983 static struct cdr_object_snapshot *cdr_object_pick_party_a(struct cdr_object_snapshot *left, struct cdr_object_snapshot *right)
985 /* Check whether or not the party is dialed. A dialed party is never the
986 * Party A with a party that was not dialed.
988 if (!snapshot_is_dialed(left->snapshot) && snapshot_is_dialed(right->snapshot)) {
990 } else if (snapshot_is_dialed(left->snapshot) && !snapshot_is_dialed(right->snapshot)) {
994 /* Try the Party A flag */
995 if (ast_test_flag(left, AST_CDR_FLAG_PARTY_A) && !ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
997 } else if (!ast_test_flag(right, AST_CDR_FLAG_PARTY_A) && ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
1001 /* Neither party is dialed and neither has the Party A flag - defer to
1003 if (left->snapshot->creationtime.tv_sec < right->snapshot->creationtime.tv_sec) {
1005 } else if (left->snapshot->creationtime.tv_sec > right->snapshot->creationtime.tv_sec) {
1007 } else if (left->snapshot->creationtime.tv_usec > right->snapshot->creationtime.tv_usec) {
1010 /* Okay, fine, take the left one */
1016 * Compute the duration for a \ref cdr_object
1018 static long cdr_object_get_duration(struct cdr_object *cdr)
1020 return (long)(ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->start) / 1000);
1024 * \brief Compute the billsec for a \ref cdr_object
1026 static long cdr_object_get_billsec(struct cdr_object *cdr)
1028 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1031 if (ast_tvzero(cdr->answer)) {
1034 ms = ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->answer);
1035 if (ast_test_flag(&mod_cfg->general->settings, CDR_INITIATED_SECONDS)
1036 && (ms % 1000 >= 500)) {
1037 ms = (ms / 1000) + 1;
1047 * \brief Set a variable on a CDR object
1049 * \param headp The header pointer to the variable to set
1050 * \param name The name of the variable
1051 * \param value The value of the variable
1053 static void set_variable(struct varshead *headp, const char *name, const char *value)
1055 struct ast_var_t *newvariable;
1057 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1058 if (!strcasecmp(ast_var_name(newvariable), name)) {
1059 AST_LIST_REMOVE_CURRENT(entries);
1060 ast_var_delete(newvariable);
1064 AST_LIST_TRAVERSE_SAFE_END;
1066 if (value && (newvariable = ast_var_assign(name, value))) {
1067 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1072 * \brief Create a chain of \ref ast_cdr objects from a chain of \ref cdr_object
1073 * suitable for consumption by the registered CDR backends
1074 * \param cdr The \ref cdr_object to convert to a public record
1075 * \retval A chain of \ref ast_cdr objects on success
1076 * \retval NULL on failure
1078 static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr)
1080 struct ast_cdr *pub_cdr = NULL, *cdr_prev = NULL;
1081 struct cdr_object *it_cdr;
1082 struct ast_var_t *it_var, *it_copy_var;
1083 struct ast_channel_snapshot *party_a;
1084 struct ast_channel_snapshot *party_b;
1085 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1087 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1088 struct ast_cdr *cdr_copy;
1090 /* Don't create records for CDRs where the party A was a dialed channel */
1091 if (snapshot_is_dialed(it_cdr->party_a.snapshot) && !it_cdr->party_b.snapshot) {
1092 CDR_DEBUG(mod_cfg, "%p - %s is dialed and has no Party B; discarding\n", it_cdr,
1093 it_cdr->party_a.snapshot->name);
1097 cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
1103 party_a = it_cdr->party_a.snapshot;
1104 party_b = it_cdr->party_b.snapshot;
1107 ast_assert(party_a != NULL);
1108 ast_copy_string(cdr_copy->accountcode, party_a->accountcode, sizeof(cdr_copy->accountcode));
1109 cdr_copy->amaflags = party_a->amaflags;
1110 ast_copy_string(cdr_copy->channel, party_a->name, sizeof(cdr_copy->channel));
1111 ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller_name, party_a->caller_number, "");
1112 ast_copy_string(cdr_copy->src, party_a->caller_number, sizeof(cdr_copy->src));
1113 ast_copy_string(cdr_copy->uniqueid, party_a->uniqueid, sizeof(cdr_copy->uniqueid));
1114 ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
1115 ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
1116 ast_copy_string(cdr_copy->dst, party_a->exten, sizeof(cdr_copy->dst));
1117 ast_copy_string(cdr_copy->dcontext, party_a->context, sizeof(cdr_copy->dcontext));
1121 ast_copy_string(cdr_copy->dstchannel, party_b->name, sizeof(cdr_copy->dstchannel));
1122 ast_copy_string(cdr_copy->peeraccount, party_b->accountcode, sizeof(cdr_copy->peeraccount));
1123 if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
1124 snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
1127 if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) {
1128 ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield));
1131 /* Timestamps/durations */
1132 cdr_copy->start = it_cdr->start;
1133 cdr_copy->answer = it_cdr->answer;
1134 cdr_copy->end = it_cdr->end;
1135 cdr_copy->billsec = cdr_object_get_billsec(it_cdr);
1136 cdr_copy->duration = cdr_object_get_duration(it_cdr);
1139 ast_copy_flags(cdr_copy, &it_cdr->flags, AST_FLAGS_ALL);
1140 ast_copy_string(cdr_copy->linkedid, it_cdr->linkedid, sizeof(cdr_copy->linkedid));
1141 cdr_copy->disposition = it_cdr->disposition;
1142 cdr_copy->sequence = it_cdr->sequence;
1145 copy_variables(&cdr_copy->varshead, &it_cdr->party_a.variables);
1146 AST_LIST_TRAVERSE(&it_cdr->party_b.variables, it_var, entries) {
1148 struct ast_var_t *newvariable;
1149 AST_LIST_TRAVERSE(&cdr_copy->varshead, it_copy_var, entries) {
1150 if (!strcasecmp(ast_var_name(it_var), ast_var_name(it_copy_var))) {
1155 if (!found && (newvariable = ast_var_assign(ast_var_name(it_var), ast_var_value(it_var)))) {
1156 AST_LIST_INSERT_TAIL(&cdr_copy->varshead, newvariable, entries);
1164 cdr_prev->next = cdr_copy;
1165 cdr_prev = cdr_copy;
1173 * \brief Dispatch a CDR.
1174 * \param cdr The \ref cdr_object to dispatch
1176 * This will create a \ref ast_cdr object and publish it to the various backends
1178 static void cdr_object_dispatch(struct cdr_object *cdr)
1180 RAII_VAR(struct module_config *, mod_cfg,
1181 ao2_global_obj_ref(module_configs), ao2_cleanup);
1182 struct ast_cdr *pub_cdr;
1184 CDR_DEBUG(mod_cfg, "%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
1185 cdr->party_a.snapshot->name,
1186 cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<none>");
1187 pub_cdr = cdr_object_create_public_records(cdr);
1188 cdr_detach(pub_cdr);
1192 * \brief Set the disposition on a \ref cdr_object based on a hangupcause code
1193 * \param cdr The \ref cdr_object
1194 * \param hangupcause The Asterisk hangup cause code
1196 static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
1198 RAII_VAR(struct module_config *, mod_cfg,
1199 ao2_global_obj_ref(module_configs), ao2_cleanup);
1201 /* Change the disposition based on the hang up cause */
1202 switch (hangupcause) {
1203 case AST_CAUSE_BUSY:
1204 cdr->disposition = AST_CDR_BUSY;
1206 case AST_CAUSE_CONGESTION:
1207 if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
1208 cdr->disposition = AST_CDR_FAILED;
1210 cdr->disposition = AST_CDR_CONGESTION;
1213 case AST_CAUSE_NO_ROUTE_DESTINATION:
1214 case AST_CAUSE_UNREGISTERED:
1215 cdr->disposition = AST_CDR_FAILED;
1217 case AST_CAUSE_NORMAL_CLEARING:
1218 case AST_CAUSE_NO_ANSWER:
1219 cdr->disposition = AST_CDR_NOANSWER;
1227 * \brief Finalize a CDR.
1229 * This function is safe to call multiple times. Note that you can call this
1230 * explicitly before going to the finalized state if there's a chance the CDR
1231 * will be re-activated, in which case the \ref cdr_object's end time should be
1232 * cleared. This function is implicitly called when a CDR transitions to the
1233 * finalized state and right before it is dispatched
1235 * \param cdr_object The CDR to finalize
1237 static void cdr_object_finalize(struct cdr_object *cdr)
1239 RAII_VAR(struct module_config *, mod_cfg,
1240 ao2_global_obj_ref(module_configs), ao2_cleanup);
1242 if (!ast_tvzero(cdr->end)) {
1245 cdr->end = ast_tvnow();
1247 if (cdr->disposition == AST_CDR_NULL) {
1248 if (!ast_tvzero(cdr->answer)) {
1249 cdr->disposition = AST_CDR_ANSWERED;
1250 } else if (cdr->party_a.snapshot->hangupcause) {
1251 cdr_object_set_disposition(cdr, cdr->party_a.snapshot->hangupcause);
1252 } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangupcause) {
1253 cdr_object_set_disposition(cdr, cdr->party_b.snapshot->hangupcause);
1255 cdr->disposition = AST_CDR_FAILED;
1259 /* tv_usec is suseconds_t, which could be int or long */
1260 ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dispo %s\n",
1261 cdr->party_a.snapshot->name,
1263 (long)cdr->start.tv_usec,
1265 (long)cdr->answer.tv_usec,
1267 (long)cdr->end.tv_usec,
1268 ast_cdr_disp2str(cdr->disposition));
1272 * \brief Check to see if a CDR needs to move to the finalized state because
1273 * its Party A hungup.
1275 static void cdr_object_check_party_a_hangup(struct cdr_object *cdr)
1277 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1279 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
1280 && ast_test_flag(&cdr->party_a.snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
1281 cdr_object_finalize(cdr);
1284 if (ast_test_flag(&cdr->party_a.snapshot->flags, AST_FLAG_DEAD)
1285 && cdr->fn_table != &finalized_state_fn_table) {
1286 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1291 * \brief Check to see if a CDR needs to be answered based on its Party A.
1292 * Note that this is safe to call as much as you want - we won't answer twice
1294 static void cdr_object_check_party_a_answer(struct cdr_object *cdr) {
1295 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1297 if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
1298 cdr->answer = ast_tvnow();
1299 /* tv_usec is suseconds_t, which could be int or long */
1300 CDR_DEBUG(mod_cfg, "%p - Set answered time to %ld.%06ld\n", cdr,
1302 (long)cdr->answer.tv_usec);
1306 /* \brief Set Caller ID information on a CDR */
1307 static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
1309 if (!old_snapshot->snapshot) {
1310 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
1311 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
1312 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
1315 if (!strcmp(old_snapshot->snapshot->caller_dnid, new_snapshot->caller_dnid)) {
1316 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
1318 if (!strcmp(old_snapshot->snapshot->caller_subaddr, new_snapshot->caller_subaddr)) {
1319 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
1321 if (!strcmp(old_snapshot->snapshot->dialed_subaddr, new_snapshot->dialed_subaddr)) {
1322 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
1327 * \brief Swap an old \ref cdr_object_snapshot's \ref ast_channel_snapshot for
1328 * a new \ref ast_channel_snapshot
1329 * \param old_snapshot The old \ref cdr_object_snapshot
1330 * \param new_snapshot The new \ref ast_channel_snapshot for old_snapshot
1332 static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot,
1333 struct ast_channel_snapshot *new_snapshot)
1335 cdr_object_update_cid(old_snapshot, new_snapshot);
1336 if (old_snapshot->snapshot) {
1337 ao2_t_ref(old_snapshot->snapshot, -1, "Drop ref for swap");
1339 ao2_t_ref(new_snapshot, +1, "Bump ref for swap");
1340 old_snapshot->snapshot = new_snapshot;
1343 /* BASE METHOD IMPLEMENTATIONS */
1345 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1347 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1349 ast_assert(strcasecmp(snapshot->name, cdr->party_a.snapshot->name) == 0);
1350 cdr_object_swap_snapshot(&cdr->party_a, snapshot);
1352 /* When Party A is originated to an application and the application exits, the stack
1353 * will attempt to clear the application and restore the dummy originate application
1354 * of "AppDialX". Prevent that, and any other application changes we might not want
1357 if (!ast_strlen_zero(snapshot->appl)
1358 && (strncasecmp(snapshot->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))
1359 && !ast_test_flag(&cdr->flags, AST_CDR_LOCK_APP)) {
1360 ast_string_field_set(cdr, appl, snapshot->appl);
1361 ast_string_field_set(cdr, data, snapshot->data);
1364 ast_string_field_set(cdr, linkedid, snapshot->linkedid);
1365 cdr_object_check_party_a_answer(cdr);
1366 cdr_object_check_party_a_hangup(cdr);
1371 static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1373 /* In general, most things shouldn't get a bridge leave */
1378 static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1380 /* In general, most things shouldn't get a dial end. */
1385 static enum process_bridge_enter_results base_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1387 /* Base process bridge enter simply indicates that we can't handle it */
1388 return BRIDGE_ENTER_NEED_CDR;
1391 static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
1393 char park_info[128];
1395 ast_assert(!strcasecmp(parking_info->parkee->name, cdr->party_a.snapshot->name));
1397 /* Update Party A information regardless */
1398 cdr->fn_table->process_party_a(cdr, parking_info->parkee);
1400 /* Fake out where we're parked */
1401 ast_string_field_set(cdr, appl, "Park");
1402 snprintf(park_info, sizeof(park_info), "%s:%u", parking_info->parkinglot, parking_info->parkingspace);
1403 ast_string_field_set(cdr, data, park_info);
1405 /* Prevent any further changes to the App/Data fields for this record */
1406 ast_set_flag(&cdr->flags, AST_CDR_LOCK_APP);
1413 static void single_state_init_function(struct cdr_object *cdr) {
1414 cdr->start = ast_tvnow();
1415 cdr_object_check_party_a_answer(cdr);
1418 static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1420 /* This should never happen! */
1421 ast_assert(cdr->party_b.snapshot == NULL);
1426 static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1428 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1430 if (caller && !strcasecmp(cdr->party_a.snapshot->name, caller->name)) {
1431 cdr_object_swap_snapshot(&cdr->party_a, caller);
1432 CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr,
1433 cdr->party_a.snapshot->name);
1434 cdr_object_swap_snapshot(&cdr->party_b, peer);
1435 CDR_DEBUG(mod_cfg, "%p - Updated Party B %s snapshot\n", cdr,
1436 cdr->party_b.snapshot->name);
1437 } else if (!strcasecmp(cdr->party_a.snapshot->name, peer->name)) {
1438 /* We're the entity being dialed, i.e., outbound origination */
1439 cdr_object_swap_snapshot(&cdr->party_a, peer);
1440 CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr,
1441 cdr->party_a.snapshot->name);
1444 cdr_object_transition_state(cdr, &dial_state_fn_table);
1449 * \brief Handle a comparison between our \ref cdr_object and a \ref cdr_object
1450 * already in the bridge while in the Single state. The goal of this is to find
1451 * a Party B for our CDR.
1453 * \param cdr Our \ref cdr_object in the Single state
1454 * \param cand_cdr The \ref cdr_object already in the Bridge state
1456 * \retval 0 The cand_cdr had a Party A or Party B that we could use as our
1458 * \retval 1 No party in the cand_cdr could be used as our Party B
1460 static int single_state_bridge_enter_comparison(struct cdr_object *cdr,
1461 struct cdr_object *cand_cdr)
1463 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1464 struct cdr_object_snapshot *party_a;
1466 /* Don't match on ourselves */
1467 if (!strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)) {
1471 /* Try the candidate CDR's Party A first */
1472 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
1473 if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
1474 CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n",
1475 cdr, cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name);
1476 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1477 if (!cand_cdr->party_b.snapshot) {
1478 /* We just stole them - finalize their CDR. Note that this won't
1479 * transition their state, it just sets the end time and the
1480 * disposition - if we need to re-activate them later, we can.
1482 cdr_object_finalize(cand_cdr);
1487 /* Try their Party B, unless it's us */
1488 if (!cand_cdr->party_b.snapshot
1489 || !strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name)) {
1492 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
1493 if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
1494 CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n",
1495 cdr, cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name);
1496 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
1503 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)
1505 struct ao2_iterator it_cdrs;
1509 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1511 if (ao2_container_count(bridge->channels) == 1) {
1512 /* No one in the bridge yet but us! */
1513 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1514 return BRIDGE_ENTER_ONLY_PARTY;
1517 for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
1518 !success && (channel_id = ao2_iterator_next(&it_cdrs));
1519 ao2_ref(channel_id, -1)) {
1520 RAII_VAR(struct cdr_object *, cand_cdr_master,
1521 ao2_find(active_cdrs_by_channel, channel_id, OBJ_KEY),
1523 struct cdr_object *cand_cdr;
1525 if (!cand_cdr_master) {
1529 ao2_lock(cand_cdr_master);
1530 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1531 /* Skip any records that are not in a bridge or in this bridge.
1532 * I'm not sure how that would happen, but it pays to be careful. */
1533 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1534 strcmp(cdr->bridge, cand_cdr->bridge)) {
1538 if (single_state_bridge_enter_comparison(cdr, cand_cdr)) {
1541 /* We successfully got a party B - break out */
1545 ao2_unlock(cand_cdr_master);
1547 ao2_iterator_destroy(&it_cdrs);
1549 /* We always transition state, even if we didn't get a peer */
1550 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1552 /* Success implies that we have a Party B */
1554 return BRIDGE_ENTER_OBTAINED_PARTY_B;
1557 return BRIDGE_ENTER_NO_PARTY_B;
1560 static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1562 cdr_object_transition_state(cdr, &parked_state_fn_table);
1569 static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1571 ast_assert(snapshot != NULL);
1573 if (!cdr->party_b.snapshot
1574 || strcasecmp(cdr->party_b.snapshot->name, snapshot->name)) {
1577 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1579 /* If party B hangs up, finalize this CDR */
1580 if (ast_test_flag(&cdr->party_b.snapshot->flags, AST_FLAG_DEAD)) {
1581 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1585 static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1587 /* Don't process a begin dial here. A party A already in the dial state will
1588 * who receives a dial begin for something else will be handled by the
1589 * message router callback and will add a new CDR for the party A */
1595 * \brief Convert a dial status to a CDR disposition
1597 static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
1599 RAII_VAR(struct module_config *, mod_cfg,
1600 ao2_global_obj_ref(module_configs), ao2_cleanup);
1602 if (!strcmp(dial_status, "ANSWER")) {
1603 return AST_CDR_ANSWERED;
1604 } else if (!strcmp(dial_status, "BUSY")) {
1605 return AST_CDR_BUSY;
1606 } else if (!strcmp(dial_status, "CANCEL") || !strcmp(dial_status, "NOANSWER")) {
1607 return AST_CDR_NOANSWER;
1608 } else if (!strcmp(dial_status, "CONGESTION")) {
1609 if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
1610 return AST_CDR_FAILED;
1612 return AST_CDR_CONGESTION;
1614 } else if (!strcmp(dial_status, "FAILED")) {
1615 return AST_CDR_FAILED;
1617 return AST_CDR_FAILED;
1620 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)
1622 RAII_VAR(struct module_config *, mod_cfg,
1623 ao2_global_obj_ref(module_configs), ao2_cleanup);
1624 struct ast_channel_snapshot *party_a;
1631 ast_assert(!strcasecmp(cdr->party_a.snapshot->name, party_a->name));
1632 cdr_object_swap_snapshot(&cdr->party_a, party_a);
1634 if (cdr->party_b.snapshot) {
1635 if (strcasecmp(cdr->party_b.snapshot->name, peer->name)) {
1636 /* Not the status for this CDR - defer back to the message router */
1639 cdr_object_swap_snapshot(&cdr->party_b, peer);
1642 /* Set the disposition based on the dial string. */
1643 cdr->disposition = dial_status_to_disposition(dial_status);
1644 if (cdr->disposition == AST_CDR_ANSWERED) {
1645 /* Switch to dial pending to wait and see what the caller does */
1646 cdr_object_transition_state(cdr, &dialed_pending_state_fn_table);
1648 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1654 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)
1656 struct ao2_iterator it_cdrs;
1660 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1662 /* Get parties in the bridge */
1663 if (ao2_container_count(bridge->channels) == 1) {
1664 /* No one in the bridge yet but us! */
1665 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1666 return BRIDGE_ENTER_ONLY_PARTY;
1669 for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
1670 !success && (channel_id = ao2_iterator_next(&it_cdrs));
1671 ao2_ref(channel_id, -1)) {
1672 RAII_VAR(struct cdr_object *, cand_cdr_master,
1673 ao2_find(active_cdrs_by_channel, channel_id, OBJ_KEY),
1675 struct cdr_object *cand_cdr;
1677 if (!cand_cdr_master) {
1681 ao2_lock(cand_cdr_master);
1682 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1683 /* Skip any records that are not in a bridge or in this bridge.
1684 * I'm not sure how that would happen, but it pays to be careful. */
1685 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1686 strcmp(cdr->bridge, cand_cdr->bridge)) {
1690 /* If we don't have a Party B (originated channel), skip it */
1691 if (!cdr->party_b.snapshot) {
1695 /* Skip any records that aren't our Party B */
1696 if (strcasecmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name)) {
1699 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1700 /* If they have a Party B, they joined up with someone else as their
1701 * Party A. Don't finalize them as they're active. Otherwise, we
1702 * have stolen them so they need to be finalized.
1704 if (!cand_cdr->party_b.snapshot) {
1705 cdr_object_finalize(cand_cdr);
1710 ao2_unlock(cand_cdr_master);
1712 ao2_iterator_destroy(&it_cdrs);
1714 /* We always transition state, even if we didn't get a peer */
1715 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1717 /* Success implies that we have a Party B */
1719 return BRIDGE_ENTER_OBTAINED_PARTY_B;
1721 return BRIDGE_ENTER_NO_PARTY_B;
1724 /* DIALED PENDING STATE */
1726 static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1728 /* If we get a CEP change, we're executing dialplan. If we have a Party B
1729 * that means we need a new CDR; otherwise, switch us over to single.
1731 if (snapshot_cep_changed(cdr->party_a.snapshot, snapshot)) {
1732 if (cdr->party_b.snapshot) {
1733 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1734 cdr->fn_table->process_party_a(cdr, snapshot);
1737 cdr_object_transition_state(cdr, &single_state_fn_table);
1738 cdr->fn_table->process_party_a(cdr, snapshot);
1742 base_process_party_a(cdr, snapshot);
1746 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)
1748 cdr_object_transition_state(cdr, &dial_state_fn_table);
1749 return cdr->fn_table->process_bridge_enter(cdr, bridge, channel);
1752 static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1754 if (cdr->party_b.snapshot) {
1755 /* We can't handle this as we have a Party B - ask for a new one */
1758 cdr_object_transition_state(cdr, &parked_state_fn_table);
1762 static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1764 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1766 /* Ask for a new CDR */
1772 static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1774 if (!cdr->party_b.snapshot
1775 || strcasecmp(cdr->party_b.snapshot->name, snapshot->name)) {
1778 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1780 /* If party B hangs up, finalize this CDR */
1781 if (ast_test_flag(&cdr->party_b.snapshot->flags, AST_FLAG_DEAD)) {
1782 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1786 static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1788 if (strcmp(cdr->bridge, bridge->uniqueid)) {
1791 if (strcasecmp(cdr->party_a.snapshot->name, channel->name)
1792 && cdr->party_b.snapshot
1793 && strcasecmp(cdr->party_b.snapshot->name, channel->name)) {
1796 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1803 static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1805 if (strcasecmp(cdr->party_a.snapshot->name, channel->name)) {
1808 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1813 /* FINALIZED STATE */
1815 static void finalized_state_init_function(struct cdr_object *cdr)
1817 cdr_object_finalize(cdr);
1820 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1822 RAII_VAR(struct module_config *, mod_cfg,
1823 ao2_global_obj_ref(module_configs), ao2_cleanup);
1825 /* If we ignore hangup logic, indicate that we don't need a new CDR */
1826 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
1827 && ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
1831 /* Indicate that, if possible, we should get a new CDR */
1837 * \brief Filter channel snapshots by technology
1839 static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
1841 return snapshot->tech_properties & AST_CHAN_TP_INTERNAL;
1846 * \brief Filter a channel cache update
1848 static int filter_channel_cache_message(struct ast_channel_snapshot *old_snapshot,
1849 struct ast_channel_snapshot *new_snapshot)
1853 /* Drop cache updates from certain channel technologies */
1855 ret |= filter_channel_snapshot(old_snapshot);
1858 ret |= filter_channel_snapshot(new_snapshot);
1864 /* TOPIC ROUTER CALLBACKS */
1867 * \brief Handler for Stasis-Core dial messages
1868 * \param data Passed on
1869 * \param sub The stasis subscription for this message callback
1870 * \param topic The topic this message was published for
1871 * \param message The message
1873 static void handle_dial_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
1875 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1876 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
1877 struct ast_multi_channel_blob *payload = stasis_message_data(message);
1878 struct ast_channel_snapshot *caller;
1879 struct ast_channel_snapshot *peer;
1880 struct cdr_object *it_cdr;
1881 struct ast_json *dial_status_blob;
1882 const char *dial_status = NULL;
1885 caller = ast_multi_channel_blob_get_channel(payload, "caller");
1886 peer = ast_multi_channel_blob_get_channel(payload, "peer");
1887 if (!peer && !caller) {
1890 dial_status_blob = ast_json_object_get(ast_multi_channel_blob_get_json(payload), "dialstatus");
1891 if (dial_status_blob) {
1892 dial_status = ast_json_string_get(dial_status_blob);
1895 CDR_DEBUG(mod_cfg, "Dial %s message for %s, %s: %u.%08u\n",
1896 ast_strlen_zero(dial_status) ? "Begin" : "End",
1897 caller ? caller->name : "(none)",
1898 peer ? peer->name : "(none)",
1899 (unsigned int)stasis_message_timestamp(message)->tv_sec,
1900 (unsigned int)stasis_message_timestamp(message)->tv_usec);
1902 if (filter_channel_snapshot(peer) || (caller && filter_channel_snapshot(caller))) {
1906 /* Figure out who is running this show */
1908 cdr = ao2_find(active_cdrs_by_channel, caller->uniqueid, OBJ_KEY);
1910 cdr = ao2_find(active_cdrs_by_channel, peer->uniqueid, OBJ_KEY);
1914 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->name : peer->name);
1919 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1920 if (ast_strlen_zero(dial_status)) {
1921 if (!it_cdr->fn_table->process_dial_begin) {
1924 CDR_DEBUG(mod_cfg, "%p - Processing Dial Begin message for channel %s, peer %s\n",
1926 caller ? caller->name : "(none)",
1927 peer ? peer->name : "(none)");
1928 res &= it_cdr->fn_table->process_dial_begin(it_cdr,
1932 if (!it_cdr->fn_table->process_dial_end) {
1935 CDR_DEBUG(mod_cfg, "%p - Processing Dial End message for channel %s, peer %s\n",
1937 caller ? caller->name : "(none)",
1938 peer ? peer->name : "(none)");
1939 it_cdr->fn_table->process_dial_end(it_cdr,
1946 /* If no CDR handled a dial begin message, make a new one */
1947 if (res && ast_strlen_zero(dial_status)) {
1948 struct cdr_object *new_cdr;
1950 new_cdr = cdr_object_create_and_append(cdr);
1954 new_cdr->fn_table->process_dial_begin(new_cdr,
1961 static int cdr_object_finalize_party_b(void *obj, void *arg, int flags)
1963 struct cdr_object *cdr = obj;
1964 struct ast_channel_snapshot *party_b = arg;
1965 struct cdr_object *it_cdr;
1966 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1967 if (it_cdr->party_b.snapshot
1968 && !strcasecmp(it_cdr->party_b.snapshot->name, party_b->name)) {
1969 /* Don't transition to the finalized state - let the Party A do
1970 * that when its ready
1972 cdr_object_finalize(it_cdr);
1978 static int cdr_object_update_party_b(void *obj, void *arg, int flags)
1980 struct cdr_object *cdr = obj;
1981 struct ast_channel_snapshot *party_b = arg;
1982 struct cdr_object *it_cdr;
1983 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1984 if (!it_cdr->fn_table->process_party_b) {
1987 if (it_cdr->party_b.snapshot
1988 && !strcasecmp(it_cdr->party_b.snapshot->name, party_b->name)) {
1989 it_cdr->fn_table->process_party_b(it_cdr, party_b);
1995 /*! \brief Determine if we need to add a new CDR based on snapshots */
1996 static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot,
1997 struct ast_channel_snapshot *new_snapshot)
1999 RAII_VAR(struct module_config *, mod_cfg,
2000 ao2_global_obj_ref(module_configs), ao2_cleanup);
2002 if (!new_snapshot) {
2006 if (ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD)) {
2010 /* Auto-fall through will increment the priority but have no application */
2011 if (ast_strlen_zero(new_snapshot->appl)) {
2015 if (old_snapshot && !snapshot_cep_changed(old_snapshot, new_snapshot)) {
2023 * \brief Handler for Stasis-Core channel cache update messages
2024 * \param data Passed on
2025 * \param sub The stasis subscription for this message callback
2026 * \param topic The topic this message was published for
2027 * \param message The message
2029 static void handle_channel_cache_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
2031 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
2032 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2033 struct stasis_cache_update *update = stasis_message_data(message);
2034 struct ast_channel_snapshot *old_snapshot;
2035 struct ast_channel_snapshot *new_snapshot;
2036 const char *uniqueid;
2038 struct cdr_object *it_cdr;
2040 ast_assert(update != NULL);
2041 ast_assert(ast_channel_snapshot_type() == update->type);
2043 old_snapshot = stasis_message_data(update->old_snapshot);
2044 new_snapshot = stasis_message_data(update->new_snapshot);
2045 uniqueid = new_snapshot ? new_snapshot->uniqueid : old_snapshot->uniqueid;
2046 name = new_snapshot ? new_snapshot->name : old_snapshot->name;
2048 if (filter_channel_cache_message(old_snapshot, new_snapshot)) {
2052 if (new_snapshot && !old_snapshot) {
2053 cdr = cdr_object_alloc(new_snapshot);
2057 ao2_link(active_cdrs_by_channel, cdr);
2060 /* Handle Party A */
2062 cdr = ao2_find(active_cdrs_by_channel, uniqueid, OBJ_KEY);
2065 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", name);
2070 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2071 if (!it_cdr->fn_table->process_party_a) {
2074 all_reject &= it_cdr->fn_table->process_party_a(it_cdr, new_snapshot);
2076 if (all_reject && check_new_cdr_needed(old_snapshot, new_snapshot)) {
2077 /* We're not hung up and we have a new snapshot - we need a new CDR */
2078 struct cdr_object *new_cdr;
2079 new_cdr = cdr_object_create_and_append(cdr);
2081 new_cdr->fn_table->process_party_a(new_cdr, new_snapshot);
2085 CDR_DEBUG(mod_cfg, "%p - Beginning finalize/dispatch for %s\n", cdr, old_snapshot->name);
2086 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2087 cdr_object_finalize(it_cdr);
2089 cdr_object_dispatch(cdr);
2090 ao2_unlink(active_cdrs_by_channel, cdr);
2095 /* Handle Party B */
2097 ao2_callback(active_cdrs_by_channel, OBJ_NODATA, cdr_object_update_party_b,
2100 ao2_callback(active_cdrs_by_channel, OBJ_NODATA, cdr_object_finalize_party_b,
2106 struct bridge_leave_data {
2107 struct ast_bridge_snapshot *bridge;
2108 struct ast_channel_snapshot *channel;
2111 /*! \brief Callback used to notify CDRs of a Party B leaving the bridge */
2112 static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, int flags)
2114 struct cdr_object *cdr = obj;
2115 struct bridge_leave_data *leave_data = arg;
2116 struct cdr_object *it_cdr;
2118 if (strcmp(cdr->bridge, leave_data->bridge->uniqueid)) {
2121 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2122 if (it_cdr->fn_table != &bridge_state_fn_table) {
2125 if (!it_cdr->party_b.snapshot) {
2128 if (strcasecmp(it_cdr->party_b.snapshot->name, leave_data->channel->name)) {
2131 /* It is our Party B, in our bridge. Set the end time and let the handler
2132 * transition our CDR appropriately when we leave the bridge.
2134 cdr_object_finalize(it_cdr);
2139 /*! \brief Filter bridge messages based on bridge technology */
2140 static int filter_bridge_messages(struct ast_bridge_snapshot *bridge)
2142 /* Ignore holding bridge technology messages. We treat this simply as an application
2143 * that a channel enters into.
2145 if (!strcmp(bridge->technology, "holding_bridge") && strcmp(bridge->subclass, "parking")) {
2152 * \brief Handler for when a channel leaves a bridge
2153 * \param data Passed on
2154 * \param sub The stasis subscription for this message callback
2155 * \param topic The topic this message was published for
2156 * \param message The message - hopefully a bridge one!
2158 static void handle_bridge_leave_message(void *data, struct stasis_subscription *sub,
2159 struct stasis_message *message)
2161 struct ast_bridge_blob *update = stasis_message_data(message);
2162 struct ast_bridge_snapshot *bridge = update->bridge;
2163 struct ast_channel_snapshot *channel = update->channel;
2164 RAII_VAR(struct module_config *, mod_cfg,
2165 ao2_global_obj_ref(module_configs), ao2_cleanup);
2166 RAII_VAR(struct cdr_object *, cdr,
2167 ao2_find(active_cdrs_by_channel, channel->uniqueid, OBJ_KEY),
2169 struct cdr_object *it_cdr;
2170 struct bridge_leave_data leave_data = {
2174 int left_bridge = 0;
2176 if (filter_bridge_messages(bridge)) {
2180 if (filter_channel_snapshot(channel)) {
2184 CDR_DEBUG(mod_cfg, "Bridge Leave message for %s: %u.%08u\n",
2186 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2187 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2190 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2196 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2197 if (!it_cdr->fn_table->process_bridge_leave) {
2200 CDR_DEBUG(mod_cfg, "%p - Processing Bridge Leave for %s\n",
2201 it_cdr, channel->name);
2202 if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
2203 ast_string_field_set(it_cdr, bridge, "");
2213 if (strcmp(bridge->subclass, "parking")) {
2215 ao2_callback(active_cdrs_by_channel, OBJ_NODATA,
2216 cdr_object_party_b_left_bridge_cb,
2223 * \brief Create a new CDR, append it to an existing CDR, and update its snapshots
2225 * \note The new CDR will be automatically transitioned to the bridge state
2227 static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
2228 struct cdr_object_snapshot *party_b)
2230 RAII_VAR(struct module_config *, mod_cfg,
2231 ao2_global_obj_ref(module_configs), ao2_cleanup);
2232 struct cdr_object *new_cdr;
2234 new_cdr = cdr_object_create_and_append(cdr);
2238 cdr_object_snapshot_copy(&new_cdr->party_b, party_b);
2239 cdr_object_check_party_a_answer(new_cdr);
2240 ast_string_field_set(new_cdr, bridge, cdr->bridge);
2241 cdr_object_transition_state(new_cdr, &bridge_state_fn_table);
2242 CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n",
2243 new_cdr, new_cdr->party_a.snapshot->name,
2244 party_b->snapshot->name);
2248 * \brief Process a single \ref bridge_candidate
2250 * When a CDR enters a bridge, it needs to make pairings with everyone else
2251 * that it is not currently paired with. This function determines, for the
2252 * CDR for the channel that entered the bridge and the CDR for every other
2253 * channel currently in the bridge, who is Party A and makes new CDRs.
2255 * \param cdr The \ref cdr_obj being processed
2256 * \param cand_cdr The \ref cdr_object that is a candidate
2259 static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
2261 RAII_VAR(struct module_config *, mod_cfg,
2262 ao2_global_obj_ref(module_configs), ao2_cleanup);
2263 struct cdr_object_snapshot *party_a;
2264 struct cdr_object *cand_cdr;
2266 SCOPED_AO2LOCK(lock, base_cand_cdr);
2268 for (cand_cdr = base_cand_cdr; cand_cdr; cand_cdr = cand_cdr->next) {
2269 /* Skip any records that are not in this bridge */
2270 if (strcmp(cand_cdr->bridge, cdr->bridge)) {
2274 /* If the candidate is us or someone we've taken on, pass on by */
2275 if (!strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)
2276 || (cdr->party_b.snapshot
2277 && !strcasecmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name))) {
2281 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
2282 /* We're party A - make a new CDR, append it to us, and set the candidate as
2284 if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
2285 bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);
2289 /* We're Party B. Check if we can add ourselves immediately or if we need
2290 * a new CDR for them (they already have a Party B) */
2291 if (cand_cdr->party_b.snapshot
2292 && strcasecmp(cand_cdr->party_b.snapshot->name, cdr->party_a.snapshot->name)) {
2293 bridge_candidate_add_to_cdr(cand_cdr, &cdr->party_a);
2295 CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n",
2296 cand_cdr, cand_cdr->party_a.snapshot->name,
2297 cdr->party_a.snapshot->name);
2298 cdr_object_snapshot_copy(&cand_cdr->party_b, &cdr->party_a);
2299 /* It's possible that this joined at one point and was never chosen
2300 * as party A. Clear their end time, as it would be set in such a
2303 memset(&cand_cdr->end, 0, sizeof(cand_cdr->end));
2310 * \brief Handle creating bridge pairings for the \ref cdr_object that just
2312 * \param cdr The \ref cdr_object that just entered the bridge
2313 * \param bridge The \ref ast_bridge_snapshot representing the bridge it just entered
2315 static void handle_bridge_pairings(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge)
2317 struct ao2_iterator it_channels;
2320 it_channels = ao2_iterator_init(bridge->channels, 0);
2321 while ((channel_id = ao2_iterator_next(&it_channels))) {
2322 RAII_VAR(struct cdr_object *, cand_cdr,
2323 ao2_find(active_cdrs_by_channel, channel_id, OBJ_KEY),
2327 ao2_ref(channel_id, -1);
2331 bridge_candidate_process(cdr, cand_cdr);
2333 ao2_ref(channel_id, -1);
2335 ao2_iterator_destroy(&it_channels);
2338 /*! \brief Handle entering into a parking bridge
2339 * \param cdr The CDR to operate on
2340 * \param bridge The bridge the channel just entered
2341 * \param channel The channel snapshot
2343 static void handle_parking_bridge_enter_message(struct cdr_object *cdr,
2344 struct ast_bridge_snapshot *bridge,
2345 struct ast_channel_snapshot *channel)
2347 RAII_VAR(struct module_config *, mod_cfg,
2348 ao2_global_obj_ref(module_configs), ao2_cleanup);
2350 struct cdr_object *it_cdr;
2351 struct cdr_object *new_cdr;
2355 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2356 if (it_cdr->fn_table->process_parking_bridge_enter) {
2357 res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
2359 if (it_cdr->fn_table->process_party_a) {
2360 CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr,
2362 it_cdr->fn_table->process_party_a(it_cdr, channel);
2367 /* No one handled it - we need a new one! */
2368 new_cdr = cdr_object_create_and_append(cdr);
2370 /* Let the single state transition us to Parked */
2371 cdr_object_transition_state(new_cdr, &single_state_fn_table);
2372 new_cdr->fn_table->process_parking_bridge_enter(new_cdr, bridge, channel);
2378 /*! \brief Handle a bridge enter message for a 'normal' bridge
2379 * \param cdr The CDR to operate on
2380 * \param bridge The bridge the channel just entered
2381 * \param channel The channel snapshot
2383 static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
2384 struct ast_bridge_snapshot *bridge,
2385 struct ast_channel_snapshot *channel)
2387 RAII_VAR(struct module_config *, mod_cfg,
2388 ao2_global_obj_ref(module_configs), ao2_cleanup);
2389 enum process_bridge_enter_results result;
2390 struct cdr_object *it_cdr;
2391 struct cdr_object *new_cdr;
2392 struct cdr_object *handled_cdr = NULL;
2396 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2397 if (it_cdr->fn_table->process_party_a) {
2398 CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr,
2400 it_cdr->fn_table->process_party_a(it_cdr, channel);
2403 /* Notify all states that they have entered a bridge */
2404 if (it_cdr->fn_table->process_bridge_enter) {
2405 CDR_DEBUG(mod_cfg, "%p - Processing bridge enter for %s\n", it_cdr,
2407 result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
2409 case BRIDGE_ENTER_ONLY_PARTY:
2411 case BRIDGE_ENTER_OBTAINED_PARTY_B:
2413 handled_cdr = it_cdr;
2416 case BRIDGE_ENTER_NEED_CDR:
2419 case BRIDGE_ENTER_NO_PARTY_B:
2420 /* We didn't win on any - end this CDR. If someone else comes in later
2421 * that is Party B to this CDR, it can re-activate this CDR.
2424 handled_cdr = it_cdr;
2426 cdr_object_finalize(cdr);
2432 /* Create the new matchings, but only for either:
2433 * * The first CDR in the chain that handled it. This avoids issues with
2435 * * If no one handled it, the last CDR in the chain. This would occur if
2436 * a CDR joined a bridge and it wasn't Party A for anyone. We still need
2437 * to make pairings with everyone in the bridge.
2440 handle_bridge_pairings(handled_cdr, bridge);
2442 /* Nothing handled it - we need a new one! */
2443 new_cdr = cdr_object_create_and_append(cdr);
2445 /* This is guaranteed to succeed: the new CDR is created in the single state
2446 * and will be able to handle the bridge enter message
2448 handle_standard_bridge_enter_message(cdr, bridge, channel);
2456 * \brief Handler for Stasis-Core bridge enter messages
2457 * \param data Passed on
2458 * \param sub The stasis subscription for this message callback
2459 * \param topic The topic this message was published for
2460 * \param message The message - hopefully a bridge one!
2462 static void handle_bridge_enter_message(void *data, struct stasis_subscription *sub,
2463 struct stasis_message *message)
2465 struct ast_bridge_blob *update = stasis_message_data(message);
2466 struct ast_bridge_snapshot *bridge = update->bridge;
2467 struct ast_channel_snapshot *channel = update->channel;
2468 RAII_VAR(struct cdr_object *, cdr,
2469 ao2_find(active_cdrs_by_channel, channel->uniqueid, OBJ_KEY),
2471 RAII_VAR(struct module_config *, mod_cfg,
2472 ao2_global_obj_ref(module_configs), ao2_cleanup);
2474 if (filter_bridge_messages(bridge)) {
2478 if (filter_channel_snapshot(channel)) {
2482 CDR_DEBUG(mod_cfg, "Bridge Enter message for channel %s: %u.%08u\n",
2484 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2485 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2488 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2492 if (!strcmp(bridge->subclass, "parking")) {
2493 handle_parking_bridge_enter_message(cdr, bridge, channel);
2495 handle_standard_bridge_enter_message(cdr, bridge, channel);
2500 * \brief Handler for when a channel is parked
2501 * \param data Passed on
2502 * \param sub The stasis subscription for this message callback
2503 * \param topic The topic this message was published for
2504 * \param message The message about who got parked
2506 static void handle_parked_call_message(void *data, struct stasis_subscription *sub,
2507 struct stasis_message *message)
2509 struct ast_parked_call_payload *payload = stasis_message_data(message);
2510 struct ast_channel_snapshot *channel = payload->parkee;
2511 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
2512 RAII_VAR(struct module_config *, mod_cfg,
2513 ao2_global_obj_ref(module_configs), ao2_cleanup);
2515 struct cdr_object *it_cdr;
2517 /* Anything other than getting parked will be handled by other updates */
2518 if (payload->event_type != PARKED_CALL) {
2522 /* No one got parked? */
2527 if (filter_channel_snapshot(channel)) {
2531 CDR_DEBUG(mod_cfg, "Parked Call message for channel %s: %u.%08u\n",
2533 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2534 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2536 cdr = ao2_find(active_cdrs_by_channel, channel->uniqueid, OBJ_KEY);
2538 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2544 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2545 if (it_cdr->fn_table->process_parked_channel) {
2546 unhandled &= it_cdr->fn_table->process_parked_channel(it_cdr, payload);
2551 /* Nothing handled the messgae - we need a new one! */
2552 struct cdr_object *new_cdr = cdr_object_create_and_append(cdr);
2554 /* As the new CDR is created in the single state, it is guaranteed
2555 * to have a function for the parked call message and will handle
2557 new_cdr->fn_table->process_parked_channel(new_cdr, payload);
2565 struct ast_cdr_config *ast_cdr_get_config(void)
2567 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2568 ao2_ref(mod_cfg->general, +1);
2569 return mod_cfg->general;
2572 void ast_cdr_set_config(struct ast_cdr_config *config)
2574 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2576 ao2_cleanup(mod_cfg->general);
2577 mod_cfg->general = config;
2578 ao2_ref(mod_cfg->general, +1);
2580 cdr_toggle_runtime_options();
2583 int ast_cdr_is_enabled(void)
2585 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2586 return ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED);
2589 int ast_cdr_backend_suspend(const char *name)
2592 struct cdr_beitem *i = NULL;
2594 AST_RWLIST_WRLOCK(&be_list);
2595 AST_RWLIST_TRAVERSE(&be_list, i, list) {
2596 if (!strcasecmp(name, i->name)) {
2597 ast_debug(3, "Suspending CDR backend %s\n", i->name);
2602 AST_RWLIST_UNLOCK(&be_list);
2607 int ast_cdr_backend_unsuspend(const char *name)
2610 struct cdr_beitem *i = NULL;
2612 AST_RWLIST_WRLOCK(&be_list);
2613 AST_RWLIST_TRAVERSE(&be_list, i, list) {
2614 if (!strcasecmp(name, i->name)) {
2615 ast_debug(3, "Unsuspending CDR backend %s\n", i->name);
2620 AST_RWLIST_UNLOCK(&be_list);
2625 int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
2627 struct cdr_beitem *i = NULL;
2633 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
2637 AST_RWLIST_WRLOCK(&be_list);
2638 AST_RWLIST_TRAVERSE(&be_list, i, list) {
2639 if (!strcasecmp(name, i->name)) {
2640 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
2641 AST_RWLIST_UNLOCK(&be_list);
2646 if (!(i = ast_calloc(1, sizeof(*i))))
2650 ast_copy_string(i->name, name, sizeof(i->name));
2651 ast_copy_string(i->desc, desc, sizeof(i->desc));
2653 AST_RWLIST_INSERT_HEAD(&be_list, i, list);
2654 AST_RWLIST_UNLOCK(&be_list);
2659 int ast_cdr_unregister(const char *name)
2661 struct cdr_beitem *match = NULL;
2664 AST_RWLIST_WRLOCK(&be_list);
2665 AST_RWLIST_TRAVERSE(&be_list, match, list) {
2666 if (!strcasecmp(name, match->name)) {
2672 AST_RWLIST_UNLOCK(&be_list);
2676 active_count = ao2_container_count(active_cdrs_by_channel);
2678 if (!match->suspended && active_count != 0) {
2679 AST_RWLIST_UNLOCK(&be_list);
2680 ast_log(AST_LOG_WARNING, "Unable to unregister CDR backend %s; %d CDRs are still active\n",
2681 name, active_count);
2685 AST_RWLIST_REMOVE(&be_list, match, list);
2686 AST_RWLIST_UNLOCK(&be_list);
2688 ast_verb(2, "Unregistered '%s' CDR backend\n", name);
2694 struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
2696 struct ast_cdr *newcdr;
2701 newcdr = ast_cdr_alloc();
2707 AST_LIST_HEAD_INIT_NOLOCK(&newcdr->varshead);
2708 copy_variables(&newcdr->varshead, &cdr->varshead);
2709 newcdr->next = NULL;
2714 static const char *cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
2716 struct ast_var_t *variables;
2718 if (ast_strlen_zero(name)) {
2722 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
2723 if (!strcasecmp(name, ast_var_name(variables))) {
2724 return ast_var_value(variables);
2731 static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
2733 if (fmt == NULL) { /* raw mode */
2734 snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec);
2736 buf[0] = '\0';/* Ensure the buffer is initialized. */
2740 ast_localtime(&when, &tm, NULL);
2741 ast_strftime(buf, bufsize, fmt, &tm);
2746 void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
2748 const char *fmt = "%Y-%m-%d %T";
2757 if (!strcasecmp(name, "clid")) {
2758 ast_copy_string(workspace, cdr->clid, workspacelen);
2759 } else if (!strcasecmp(name, "src")) {
2760 ast_copy_string(workspace, cdr->src, workspacelen);
2761 } else if (!strcasecmp(name, "dst")) {
2762 ast_copy_string(workspace, cdr->dst, workspacelen);
2763 } else if (!strcasecmp(name, "dcontext")) {
2764 ast_copy_string(workspace, cdr->dcontext, workspacelen);
2765 } else if (!strcasecmp(name, "channel")) {
2766 ast_copy_string(workspace, cdr->channel, workspacelen);
2767 } else if (!strcasecmp(name, "dstchannel")) {
2768 ast_copy_string(workspace, cdr->dstchannel, workspacelen);
2769 } else if (!strcasecmp(name, "lastapp")) {
2770 ast_copy_string(workspace, cdr->lastapp, workspacelen);
2771 } else if (!strcasecmp(name, "lastdata")) {
2772 ast_copy_string(workspace, cdr->lastdata, workspacelen);
2773 } else if (!strcasecmp(name, "start")) {
2774 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
2775 } else if (!strcasecmp(name, "answer")) {
2776 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
2777 } else if (!strcasecmp(name, "end")) {
2778 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
2779 } else if (!strcasecmp(name, "duration")) {
2780 snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
2781 } else if (!strcasecmp(name, "billsec")) {
2782 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);
2783 } else if (!strcasecmp(name, "disposition")) {
2785 snprintf(workspace, workspacelen, "%ld", cdr->disposition);
2787 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
2789 } else if (!strcasecmp(name, "amaflags")) {
2791 snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
2793 ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
2795 } else if (!strcasecmp(name, "accountcode")) {
2796 ast_copy_string(workspace, cdr->accountcode, workspacelen);
2797 } else if (!strcasecmp(name, "peeraccount")) {
2798 ast_copy_string(workspace, cdr->peeraccount, workspacelen);
2799 } else if (!strcasecmp(name, "uniqueid")) {
2800 ast_copy_string(workspace, cdr->uniqueid, workspacelen);
2801 } else if (!strcasecmp(name, "linkedid")) {
2802 ast_copy_string(workspace, cdr->linkedid, workspacelen);
2803 } else if (!strcasecmp(name, "userfield")) {
2804 ast_copy_string(workspace, cdr->userfield, workspacelen);
2805 } else if (!strcasecmp(name, "sequence")) {
2806 snprintf(workspace, workspacelen, "%d", cdr->sequence);
2807 } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
2808 ast_copy_string(workspace, varbuf, workspacelen);
2810 workspace[0] = '\0';
2813 if (!ast_strlen_zero(workspace)) {
2820 * \brief Callback that finds all CDRs that reference a particular channel by name
2822 static int cdr_object_select_all_by_name_cb(void *obj, void *arg, int flags)
2824 struct cdr_object *cdr = obj;
2825 const char *name = arg;
2827 if (!strcasecmp(cdr->party_a.snapshot->name, name) ||
2828 (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->name, name))) {
2836 * \brief Callback that finds a CDR by channel name
2838 static int cdr_object_get_by_name_cb(void *obj, void *arg, int flags)
2840 struct cdr_object *cdr = obj;
2841 const char *name = arg;
2843 if (!strcasecmp(cdr->party_a.snapshot->name, name)) {
2849 /* Read Only CDR variables */
2850 static const char * const cdr_readonly_vars[] = {
2874 int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
2876 struct cdr_object *cdr;
2877 struct cdr_object *it_cdr;
2878 struct ao2_iterator *it_cdrs;
2879 char *arg = ast_strdupa(channel_name);
2882 for (x = 0; cdr_readonly_vars[x]; x++) {
2883 if (!strcasecmp(name, cdr_readonly_vars[x])) {
2884 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
2889 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE, cdr_object_select_all_by_name_cb, arg);
2891 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
2895 for (; (cdr = ao2_iterator_next(it_cdrs)); ao2_unlock(cdr), ao2_cleanup(cdr)) {
2897 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2898 struct varshead *headp = NULL;
2900 if (it_cdr->fn_table == &finalized_state_fn_table) {
2903 if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->name)) {
2904 headp = &it_cdr->party_a.variables;
2905 } else if (it_cdr->party_b.snapshot
2906 && !strcasecmp(channel_name, it_cdr->party_b.snapshot->name)) {
2907 headp = &it_cdr->party_b.variables;
2910 set_variable(headp, name, value);
2914 ao2_iterator_destroy(it_cdrs);
2920 * \brief Format a variable on a \ref cdr_object
2922 static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
2924 struct ast_var_t *variable;
2926 AST_LIST_TRAVERSE(&cdr->party_a.variables, variable, entries) {
2927 if (!strcasecmp(name, ast_var_name(variable))) {
2928 ast_copy_string(value, ast_var_value(variable), length);
2937 * \brief Format one of the standard properties on a \ref cdr_object
2939 static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
2941 struct ast_channel_snapshot *party_a = cdr_obj->party_a.snapshot;
2942 struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;
2944 if (!strcasecmp(name, "clid")) {
2945 ast_callerid_merge(value, length, party_a->caller_name, party_a->caller_number, "");
2946 } else if (!strcasecmp(name, "src")) {
2947 ast_copy_string(value, party_a->caller_number, length);
2948 } else if (!strcasecmp(name, "dst")) {
2949 ast_copy_string(value, party_a->exten, length);
2950 } else if (!strcasecmp(name, "dcontext")) {
2951 ast_copy_string(value, party_a->context, length);
2952 } else if (!strcasecmp(name, "channel")) {
2953 ast_copy_string(value, party_a->name, length);
2954 } else if (!strcasecmp(name, "dstchannel")) {
2956 ast_copy_string(value, party_b->name, length);
2958 ast_copy_string(value, "", length);
2960 } else if (!strcasecmp(name, "lastapp")) {
2961 ast_copy_string(value, party_a->appl, length);
2962 } else if (!strcasecmp(name, "lastdata")) {
2963 ast_copy_string(value, party_a->data, length);
2964 } else if (!strcasecmp(name, "start")) {
2965 cdr_get_tv(cdr_obj->start, NULL, value, length);
2966 } else if (!strcasecmp(name, "answer")) {
2967 cdr_get_tv(cdr_obj->answer, NULL, value, length);
2968 } else if (!strcasecmp(name, "end")) {
2969 cdr_get_tv(cdr_obj->end, NULL, value, length);
2970 } else if (!strcasecmp(name, "duration")) {
2971 snprintf(value, length, "%ld", cdr_object_get_duration(cdr_obj));
2972 } else if (!strcasecmp(name, "billsec")) {
2973 snprintf(value, length, "%ld", cdr_object_get_billsec(cdr_obj));
2974 } else if (!strcasecmp(name, "disposition")) {
2975 snprintf(value, length, "%d", cdr_obj->disposition);
2976 } else if (!strcasecmp(name, "amaflags")) {
2977 snprintf(value, length, "%d", party_a->amaflags);
2978 } else if (!strcasecmp(name, "accountcode")) {
2979 ast_copy_string(value, party_a->accountcode, length);
2980 } else if (!strcasecmp(name, "peeraccount")) {
2982 ast_copy_string(value, party_b->accountcode, length);
2984 ast_copy_string(value, "", length);
2986 } else if (!strcasecmp(name, "uniqueid")) {
2987 ast_copy_string(value, party_a->uniqueid, length);
2988 } else if (!strcasecmp(name, "linkedid")) {
2989 ast_copy_string(value, cdr_obj->linkedid, length);
2990 } else if (!strcasecmp(name, "userfield")) {
2991 ast_copy_string(value, cdr_obj->party_a.userfield, length);
2992 } else if (!strcasecmp(name, "sequence")) {
2993 snprintf(value, length, "%d", cdr_obj->sequence);
3002 * \brief Look up and retrieve a CDR object by channel name
3003 * \param name The name of the channel
3004 * \retval NULL on error
3005 * \retval The \ref cdr_object for the channel on success, with the reference
3006 * count bumped by one.
3008 static struct cdr_object *cdr_object_get_by_name(const char *name)
3012 if (ast_strlen_zero(name)) {
3016 param = ast_strdupa(name);
3017 return ao2_callback(active_cdrs_by_channel, 0, cdr_object_get_by_name_cb, param);
3020 int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
3022 RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3023 struct cdr_object *cdr_obj;
3026 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3030 if (ast_strlen_zero(name)) {
3036 cdr_obj = cdr->last;
3037 if (cdr_object_format_property(cdr_obj, name, value, length)) {
3038 /* Property failed; attempt variable */
3039 cdr_object_format_var_internal(cdr_obj, name, value, length);
3047 int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
3049 RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3050 struct cdr_object *it_cdr;
3051 struct ast_var_t *variable;
3053 RAII_VAR(char *, workspace, ast_malloc(256), ast_free);
3054 int total = 0, x = 0, i;
3061 RAII_VAR(struct module_config *, mod_cfg,
3062 ao2_global_obj_ref(module_configs), ao2_cleanup);
3064 if (ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
3065 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3071 ast_str_reset(*buf);
3074 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3076 ast_str_append(buf, 0, "\n");
3078 AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
3079 if (!(var = ast_var_name(variable))) {
3083 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
3084 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3091 for (i = 0; cdr_readonly_vars[i]; i++) {
3092 if (cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace))) {
3093 /* Unhandled read-only CDR variable. */
3098 if (!ast_strlen_zero(workspace)
3099 && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
3100 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3110 void ast_cdr_free(struct ast_cdr *cdr)
3113 struct ast_cdr *next = cdr->next;
3115 free_variables(&cdr->varshead);
3121 struct ast_cdr *ast_cdr_alloc(void)
3125 x = ast_calloc(1, sizeof(*x));
3129 const char *ast_cdr_disp2str(int disposition)
3131 switch (disposition) {
3133 return "NO ANSWER"; /* by default, for backward compatibility */
3134 case AST_CDR_NOANSWER:
3136 case AST_CDR_FAILED:
3140 case AST_CDR_ANSWERED:
3142 case AST_CDR_CONGESTION:
3143 return "CONGESTION";
3148 struct party_b_userfield_update {
3149 const char *channel_name;
3150 const char *userfield;
3153 /*! \brief Callback used to update the userfield on Party B on all CDRs */
3154 static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, int flags)
3156 struct cdr_object *cdr = obj;
3157 struct party_b_userfield_update *info = arg;
3158 struct cdr_object *it_cdr;
3159 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3160 if (it_cdr->fn_table == &finalized_state_fn_table) {
3163 if (it_cdr->party_b.snapshot
3164 && !strcasecmp(it_cdr->party_b.snapshot->name, info->channel_name)) {
3165 strcpy(it_cdr->party_b.userfield, info->userfield);
3171 void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
3173 RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3174 struct party_b_userfield_update party_b_info = {
3175 .channel_name = channel_name,
3176 .userfield = userfield,
3178 struct cdr_object *it_cdr;
3180 /* Handle Party A */
3183 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3184 if (it_cdr->fn_table == &finalized_state_fn_table) {
3187 strcpy(it_cdr->party_a.userfield, userfield);
3192 /* Handle Party B */
3193 ao2_callback(active_cdrs_by_channel, OBJ_NODATA,
3194 cdr_object_update_party_b_userfield_cb,
3199 static void post_cdr(struct ast_cdr *cdr)
3201 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3202 struct cdr_beitem *i;
3204 for (; cdr ; cdr = cdr->next) {
3205 /* For people, who don't want to see unanswered single-channel events */
3206 if (!ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) &&
3207 cdr->disposition < AST_CDR_ANSWERED &&
3208 (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) {
3209 ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel);
3213 if (ast_test_flag(cdr, AST_CDR_FLAG_DISABLE)) {
3216 AST_RWLIST_RDLOCK(&be_list);
3217 AST_RWLIST_TRAVERSE(&be_list, i, list) {
3218 if (!i->suspended) {
3222 AST_RWLIST_UNLOCK(&be_list);
3226 int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
3228 RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3229 struct cdr_object *it_cdr;
3236 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3237 if (it_cdr->fn_table == &finalized_state_fn_table) {
3240 /* Note: in general, set the flags on both the CDR record as well as the
3241 * Party A. Sometimes all we have is the Party A to look at.
3243 ast_set_flag(&it_cdr->flags, option);
3244 ast_set_flag(&it_cdr->party_a, option);
3251 int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
3253 RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3254 struct cdr_object *it_cdr;
3261 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3262 if (it_cdr->fn_table == &finalized_state_fn_table) {
3265 ast_clear_flag(&it_cdr->flags, option);
3272 int ast_cdr_reset(const char *channel_name, int keep_variables)
3274 RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3275 struct ast_var_t *vardata;
3276 struct cdr_object *it_cdr;
3283 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3284 /* clear variables */
3285 if (!keep_variables) {
3286 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
3287 ast_var_delete(vardata);
3289 if (cdr->party_b.snapshot) {
3290 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
3291 ast_var_delete(vardata);
3296 /* Reset to initial state */
3297 memset(&it_cdr->start, 0, sizeof(it_cdr->start));
3298 memset(&it_cdr->end, 0, sizeof(it_cdr->end));
3299 memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
3300 it_cdr->start = ast_tvnow();
3301 cdr_object_check_party_a_answer(it_cdr);
3308 int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
3310 RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3311 struct cdr_object *new_cdr;
3312 struct cdr_object *it_cdr;
3313 struct cdr_object *cdr_obj;
3320 SCOPED_AO2LOCK(lock, cdr);
3321 cdr_obj = cdr->last;
3322 if (cdr_obj->fn_table == &finalized_state_fn_table) {
3323 /* If the last CDR in the chain is finalized, don't allow a fork -
3324 * things are already dying at this point
3329 /* Copy over the basic CDR information. The Party A information is
3330 * copied over automatically as part of the append
3332 ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->name);
3333 new_cdr = cdr_object_create_and_append(cdr);
3337 new_cdr->fn_table = cdr_obj->fn_table;
3338 ast_string_field_set(new_cdr, bridge, cdr->bridge);
3339 new_cdr->flags = cdr->flags;
3341 /* If there's a Party B, copy it over as well */
3342 if (cdr_obj->party_b.snapshot) {
3343 new_cdr->party_b.snapshot = cdr_obj->party_b.snapshot;
3344 ao2_ref(new_cdr->party_b.snapshot, +1);
3345 strcpy(new_cdr->party_b.userfield, cdr_obj->party_b.userfield);
3346 new_cdr->party_b.flags = cdr_obj->party_b.flags;
3347 if (ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3348 copy_variables(&new_cdr->party_b.variables, &cdr_obj->party_b.variables);
3351 new_cdr->start = cdr_obj->start;
3352 new_cdr->answer = cdr_obj->answer;
3354 /* Modify the times based on the flags passed in */
3355 if (ast_test_flag(options, AST_CDR_FLAG_SET_ANSWER)
3356 && new_cdr->party_a.snapshot->state == AST_STATE_UP) {
3357 new_cdr->answer = ast_tvnow();
3359 if (ast_test_flag(options, AST_CDR_FLAG_RESET)) {
3360 new_cdr->answer = ast_tvnow();
3361 new_cdr->start = ast_tvnow();
3364 /* Create and append, by default, copies over the variables */
3365 if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3366 free_variables(&new_cdr->party_a.variables);
3369 /* Finalize any current CDRs */
3370 if (ast_test_flag(options, AST_CDR_FLAG_FINALIZE)) {
3371 for (it_cdr = cdr; it_cdr != new_cdr; it_cdr = it_cdr->next) {
3372 if (it_cdr->fn_table == &finalized_state_fn_table) {
3375 /* Force finalization on the CDR. This will bypass any checks for
3376 * end before 'h' extension.
3378 cdr_object_finalize(it_cdr);
3379 cdr_object_transition_state(it_cdr, &finalized_state_fn_table);
3387 /*! \note Don't call without cdr_batch_lock */
3388 static void reset_batch(void)
3395 /*! \note Don't call without cdr_batch_lock */
3396 static int init_batch(void)
3398 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
3399 if (!(batch = ast_malloc(sizeof(*batch))))
3407 static void *do_batch_backend_process(void *data)
3409 struct cdr_batch_item *processeditem;
3410 struct cdr_batch_item *batchitem = data;
3412 /* Push each CDR into storage mechanism(s) and free all the memory */
3414 post_cdr(batchitem->cdr);
3415 ast_cdr_free(batchitem->cdr);
3416 processeditem = batchitem;
3417 batchitem = batchitem->next;
3418 ast_free(processeditem);
3424 static void cdr_submit_batch(int do_shutdown)
3426 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3427 struct cdr_batch_item *oldbatchitems = NULL;
3428 pthread_t batch_post_thread = AST_PTHREADT_NULL;
3430 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
3431 if (!batch || !batch->head) {
3435 /* move the old CDRs aside, and prepare a new CDR batch */
3436 ast_mutex_lock(&cdr_batch_lock);
3437 oldbatchitems = batch->head;
3439 ast_mutex_unlock(&cdr_batch_lock);
3441 /* if configured, spawn a new thread to post these CDRs,
3442 also try to save as much as possible if we are shutting down safely */
3443 if (ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SCHEDULER_ONLY) || do_shutdown) {
3444 ast_debug(1, "CDR single-threaded batch processing begins now\n");
3445 do_batch_backend_process(oldbatchitems);
3447 if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
3448 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
3449 do_batch_backend_process(oldbatchitems);
3451 ast_debug(1, "CDR multi-threaded batch processing begins now\n");
3456 static int submit_scheduled_batch(const void *data)
3458 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3459 cdr_submit_batch(0);
3460 /* manually reschedule from this point in time */
3462 ast_mutex_lock(&cdr_sched_lock);
3463 cdr_sched = ast_sched_add(sched, mod_cfg->general->batch_settings.size * 1000, submit_scheduled_batch, NULL);
3464 ast_mutex_unlock(&cdr_sched_lock);
3465 /* returning zero so the scheduler does not automatically reschedule */
3469 /*! Do not hold the batch lock while calling this function */
3470 static void submit_unscheduled_batch(void)
3472 /* Prevent two deletes from happening at the same time */
3473 ast_mutex_lock(&cdr_sched_lock);
3474 /* this is okay since we are not being called from within the scheduler */
3475 AST_SCHED_DEL(sched, cdr_sched);
3476 /* schedule the submission to occur ASAP (1 ms) */
3477 cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
3478 ast_mutex_unlock(&cdr_sched_lock);
3480 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
3481 ast_mutex_lock(&cdr_pending_lock);
3482 ast_cond_signal(&cdr_pending_cond);
3483 ast_mutex_unlock(&cdr_pending_lock);
3486 static void cdr_detach(struct ast_cdr *cdr)
3488 struct cdr_batch_item *newtail;
3490 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3491 int submit_batch = 0;
3497 /* maybe they disabled CDR stuff completely, so just drop it */
3498 if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
3499 ast_debug(1, "Dropping CDR !\n");
3504 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
3505 if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
3511 /* otherwise, each CDR gets put into a batch list (at the end) */
3512 ast_debug(1, "CDR detaching from this thread\n");
3514 /* we'll need a new tail for every CDR */
3515 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
3521 /* don't traverse a whole list (just keep track of the tail) */
3522 ast_mutex_lock(&cdr_batch_lock);
3526 /* new batch is empty, so point the head at the new tail */
3527 batch->head = newtail;
3529 /* already got a batch with something in it, so just append a new tail */
3530 batch->tail->next = newtail;
3533 batch->tail = newtail;
3534 curr = batch->size++;
3536 /* if we have enough stuff to post, then do it */
3537 if (curr >= (mod_cfg->general->batch_settings.size - 1)) {
3540 ast_mutex_unlock(&cdr_batch_lock);
3542 /* Don't call submit_unscheduled_batch with the cdr_batch_lock held */
3544 submit_unscheduled_batch();
3548 static void *do_cdr(void *data)
3550 struct timespec timeout;
3556 schedms = ast_sched_wait(sched);
3557 /* this shouldn't happen, but provide a 1 second default just in case */
3560 now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
3561 timeout.tv_sec = now.tv_sec;
3562 timeout.tv_nsec = now.tv_usec * 1000;
3563 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
3564 ast_mutex_lock(&cdr_pending_lock);
3565 ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
3566 numevents = ast_sched_runq(sched);
3567 ast_mutex_unlock(&cdr_pending_lock);
3568 ast_debug(2, "Processed %d scheduled CDR batches from the run queue\n", numevents);
3574 static char *handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3576 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3580 e->command = "cdr set debug [on|off]";
3581 e->usage = "Enable or disable extra debugging in the CDR Engine. Note\n"
3582 "that this will dump debug information to the VERBOSE setting\n"
3583 "and should only be used when debugging information from the\n"
3584 "CDR engine is needed.\n";
3591 return CLI_SHOWUSAGE;
3594 if (!strcasecmp(a->argv[3], "on")
3595 && !ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3596 ast_set_flag(&mod_cfg->general->settings, CDR_DEBUG);
3597 ast_cli(a->fd, "CDR debugging enabled\n");
3598 } else if (!strcasecmp(a->argv[3], "off")
3599 && ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3600 ast_clear_flag(&mod_cfg->general->settings, CDR_DEBUG);
3601 ast_cli(a->fd, "CDR debugging disabled\n");
3607 /*! \brief Complete user input for 'cdr show' */
3608 static char *cli_complete_show(struct ast_cli_args *a)
3610 char *result = NULL;
3611 int wordlen = strlen(a->word);
3613 struct ao2_iterator it_cdrs;
3614 struct cdr_object *cdr;
3616 it_cdrs = ao2_iterator_init(active_cdrs_by_channel, 0);
3617 while ((cdr = ao2_iterator_next(&it_cdrs))) {
3618 if (!strncasecmp(a->word, cdr->party_a.snapshot->name, wordlen) &&
3620 result = ast_strdup(cdr->party_a.snapshot->name);
3628 ao2_iterator_destroy(&it_cdrs);
3632 static void cli_show_channels(struct ast_cli_args *a)
3634 struct ao2_iterator it_cdrs;
3635 struct cdr_object *cdr;
3636 char start_time_buffer[64];
3637 char answer_time_buffer[64];
3638 char end_time_buffer[64];
3640 #define TITLE_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
3641 #define FORMAT_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
3643 ast_cli(a->fd, "\n");
3644 ast_cli(a->fd, "Channels with Call Detail Record (CDR) Information\n");
3645 ast_cli(a->fd, "--------------------------------------------------\n");
3646 ast_cli(a->fd, TITLE_STRING, "Channel", "Dst. Channel", "LastApp", "Start", "Answer", "End", "Billsec", "Duration");
3648 it_cdrs = ao2_iterator_init(active_cdrs_by_channel, 0);
3649 for (; (cdr = ao2_iterator_next(&it_cdrs)); ao2_cleanup(cdr)) {
3650 struct cdr_object *it_cdr;
3651 struct timeval start_time = { 0, };
3652 struct timeval answer_time = { 0, };
3653 struct timeval end_time = { 0, };
3655 SCOPED_AO2LOCK(lock, cdr);
3657 /* Calculate the start, end, answer, billsec, and duration over the
3658 * life of all of the CDR entries
3660 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3661 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
3664 if (ast_tvzero(start_time)) {
3665 start_time = it_cdr->start;
3667 if (!ast_tvzero(it_cdr->answer) && ast_tvzero(answer_time)) {
3668 answer_time = it_cdr->answer;
3672 /* If there was no start time, then all CDRs were for a dialed channel; skip */
3673 if (ast_tvzero(start_time)) {
3678 end_time = ast_tvzero(it_cdr->end) ? ast_tvnow() : it_cdr->end;
3679 cdr_get_tv(start_time, "%T", start_time_buffer, sizeof(start_time_buffer));
3680 cdr_get_tv(answer_time, "%T", answer_time_buffer, sizeof(answer_time_buffer));
3681 cdr_get_tv(end_time, "%T", end_time_buffer, sizeof(end_time_buffer));
3682 ast_cli(a->fd, FORMAT_STRING, it_cdr->party_a.snapshot->name,
3683 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",
3688 ast_tvzero(answer_time) ? 0 : (long)ast_tvdiff_ms(end_time, answer_time) / 1000,
3689 (long)ast_tvdiff_ms(end_time, start_time) / 1000);
3691 ao2_iterator_destroy(&it_cdrs);
3692 #undef FORMAT_STRING
3696 static void cli_show_channel(struct ast_cli_args *a)
3698 struct cdr_object *it_cdr;
3700 char start_time_buffer[64];
3701 char answer_time_buffer[64];
3702 char end_time_buffer[64];
3703 const char *channel_name = a->argv[3];
3704 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
3706 #define TITLE_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
3707 #define FORMAT_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
3709 cdr = cdr_object_get_by_name(channel_name);
3711 ast_cli(a->fd, "Unknown channel: %s\n", channel_name);
3715 ast_cli(a->fd, "\n");
3716 ast_cli(a->fd, "Call Detail Record (CDR) Information for %s\n", channel_name);
3717 ast_cli(a->fd, "--------------------------------------------------\n");
3718 ast_cli(a->fd, TITLE_STRING, "AccountCode", "CallerID", "Dst. Channel", "LastApp", "Data", "Start", "Answer", "End", "Billsec", "Duration");
3721 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3723 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
3726 ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller_name, it_cdr->party_a.snapshot->caller_number, "");
3727 if (ast_tvzero(it_cdr->end)) {
3732 cdr_get_tv(it_cdr->start, "%T", start_time_buffer, sizeof(start_time_buffer));
3733 cdr_get_tv(it_cdr->answer, "%T", answer_time_buffer, sizeof(answer_time_buffer));
3734 cdr_get_tv(end, "%T", end_time_buffer, sizeof(end_time_buffer));
3735 ast_cli(a->fd, FORMAT_STRING,
3736 it_cdr->party_a.snapshot->accountcode,
3738 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",
3744 (long)ast_tvdiff_ms(end, it_cdr->answer) / 1000,
3745 (long)ast_tvdiff_ms(end, it_cdr->start) / 1000);
3748 #undef FORMAT_STRING
3752 static char *handle_cli_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3756 e->command = "cdr show active";
3758 "Usage: cdr show active [channel]\n"
3759 " Displays a summary of all Call Detail Records when [channel]\n"
3760 " is omitted; displays all of the Call Detail Records\n"
3761 " currently in flight for a given [channel] when [channel] is\n"
3763 " Note that this will not display Call Detail Records that\n"
3764 " have already been dispatched to a backend storage, nor for\n"
3765 " channels that are no longer active.\n";
3768 return cli_complete_show(a);
3772 return CLI_SHOWUSAGE;
3773 } else if (a->argc < 4) {