2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Call Detail Record API
23 * \author Mark Spencer <markster@digium.com>
25 * \note Includes code and algorithms from the Zapata library.
27 * \note We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip
28 * through our fingers somehow. If someone allocates a CDR, it must be completely handled normally
29 * or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR
30 * isn't properly generated and posted.
33 /*! \li \ref cdr.c uses the configuration file \ref cdr.conf
34 * \addtogroup configuration_file Configuration Files
38 * \page cdr.conf cdr.conf
39 * \verbinclude cdr.conf.sample
43 <support_level>core</support_level>
48 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
53 #include "asterisk/lock.h"
54 #include "asterisk/channel.h"
55 #include "asterisk/cdr.h"
56 #include "asterisk/callerid.h"
57 #include "asterisk/manager.h"
58 #include "asterisk/causes.h"
59 #include "asterisk/linkedlists.h"
60 #include "asterisk/utils.h"
61 #include "asterisk/sched.h"
62 #include "asterisk/config.h"
63 #include "asterisk/cli.h"
64 #include "asterisk/stringfields.h"
65 #include "asterisk/data.h"
66 #include "asterisk/config_options.h"
67 #include "asterisk/json.h"
68 #include "asterisk/parking.h"
69 #include "asterisk/stasis.h"
70 #include "asterisk/stasis_channels.h"
71 #include "asterisk/stasis_bridges.h"
72 #include "asterisk/stasis_message_router.h"
73 #include "asterisk/astobj2.h"
76 <configInfo name="cdr" language="en_US">
77 <synopsis>Call Detail Record configuration</synopsis>
79 <para>CDR is Call Detail Record, which provides logging services via a variety of
80 pluggable backend modules. Detailed call information can be recorded to
81 databases, files, etc. Useful for billing, fraud prevention, compliance with
82 Sarbanes-Oxley aka The Enron Act, QOS evaluations, and more.</para>
84 <configFile name="cdr.conf">
85 <configObject name="general">
86 <synopsis>Global settings applied to the CDR engine.</synopsis>
87 <configOption name="debug">
88 <synopsis>Enable/disable verbose CDR debugging.</synopsis>
89 <description><para>When set to <literal>True</literal>, verbose updates
90 of changes in CDR information will be logged. Note that this is only
91 of use when debugging CDR behavior.</para>
94 <configOption name="enable">
95 <synopsis>Enable/disable CDR logging.</synopsis>
96 <description><para>Define whether or not to use CDR logging. Setting this to "no" will override
97 any loading of backend CDR modules. Default is "yes".</para>
100 <configOption name="unanswered">
101 <synopsis>Log calls that are never answered.</synopsis>
102 <description><para>Define whether or not to log unanswered calls. Setting this to "yes" will
103 report every attempt to ring a phone in dialing attempts, when it was not
104 answered. For example, if you try to dial 3 extensions, and this option is "yes",
105 you will get 3 CDR's, one for each phone that was rung. Some find this information horribly
106 useless. Others find it very valuable. Note, in "yes" mode, you will see one CDR, with one of
107 the call targets on one side, and the originating channel on the other, and then one CDR for
108 each channel attempted. This may seem redundant, but cannot be helped.</para>
109 <para>In brief, this option controls the reporting of unanswered calls which only have an A
110 party. Calls which get offered to an outgoing line, but are unanswered, are still
111 logged, and that is the intended behavior. (It also results in some B side CDRs being
112 output, as they have the B side channel as their source channel, and no destination
116 <configOption name="congestion">
117 <synopsis>Log congested calls.</synopsis>
118 <description><para>Define whether or not to log congested calls. Setting this to "yes" will
119 report each call that fails to complete due to congestion conditions.</para>
122 <configOption name="endbeforehexten">
123 <synopsis>Don't produce CDRs while executing hangup logic</synopsis>
125 <para>As each CDR for a channel is finished, its end time is updated
126 and the CDR is finalized. When a channel is hung up and hangup
127 logic is present (in the form of a hangup handler or the
128 <literal>h</literal> extension), a new CDR is generated for the
129 channel. Any statistics are gathered from this new CDR. By enabling
130 this option, no new CDR is created for the dialplan logic that is
131 executed in <literal>h</literal> extensions or attached hangup handler
132 subroutines. The default value is <literal>no</literal>, indicating
133 that a CDR will be generated during hangup logic.</para>
136 <configOption name="initiatedseconds">
137 <synopsis>Count microseconds for billsec purposes</synopsis>
138 <description><para>Normally, the <literal>billsec</literal> field logged to the CDR backends
139 is simply the end time (hangup time) minus the answer time in seconds. Internally,
140 asterisk stores the time in terms of microseconds and seconds. By setting
141 initiatedseconds to <literal>yes</literal>, you can force asterisk to report any seconds
142 that were initiated (a sort of round up method). Technically, this is
143 when the microsecond part of the end time is greater than the microsecond
144 part of the answer time, then the billsec time is incremented one second.</para>
147 <configOption name="batch">
148 <synopsis>Submit CDRs to the backends for processing in batches</synopsis>
149 <description><para>Define the CDR batch mode, where instead of posting the CDR at the end of
150 every call, the data will be stored in a buffer to help alleviate load on the
151 asterisk server.</para>
152 <warning><para>Use of batch mode may result in data loss after unsafe asterisk termination,
153 i.e., software crash, power failure, kill -9, etc.</para>
157 <configOption name="size">
158 <synopsis>The maximum number of CDRs to accumulate before triggering a batch</synopsis>
159 <description><para>Define the maximum number of CDRs to accumulate in the buffer before posting
160 them to the backend engines. batch must be set to <literal>yes</literal>.</para>
163 <configOption name="time">
164 <synopsis>The maximum time to accumulate CDRs before triggering a batch</synopsis>
165 <description><para>Define the maximum time to accumulate CDRs before posting them in a batch to the
166 backend engines. If this time limit is reached, then it will post the records, regardless of the value
167 defined for size. batch must be set to <literal>yes</literal>.</para>
168 <note><para>Time is expressed in seconds.</para></note>
171 <configOption name="scheduleronly">
172 <synopsis>Post batched CDRs on their own thread instead of the scheduler</synopsis>
173 <description><para>The CDR engine uses the internal asterisk scheduler to determine when to post
174 records. Posting can either occur inside the scheduler thread, or a new
175 thread can be spawned for the submission of every batch. For small batches,
176 it might be acceptable to just use the scheduler thread, so set this to <literal>yes</literal>.
177 For large batches, say anything over size=10, a new thread is recommended, so
178 set this to <literal>no</literal>.</para>
181 <configOption name="safeshutdown">
182 <synopsis>Block shutdown of Asterisk until CDRs are submitted</synopsis>
183 <description><para>When shutting down asterisk, you can block until the CDRs are submitted. If
184 you don't, then data will likely be lost. You can always check the size of
185 the CDR batch buffer with the CLI <astcli>cdr status</astcli> command. To enable blocking on
186 submission of CDR data during asterisk shutdown, set this to <literal>yes</literal>.</para>
195 #define DEFAULT_ENABLED "1"
196 #define DEFAULT_BATCHMODE "0"
197 #define DEFAULT_UNANSWERED "0"
198 #define DEFAULT_CONGESTION "0"
199 #define DEFAULT_END_BEFORE_H_EXTEN "0"
200 #define DEFAULT_INITIATED_SECONDS "0"
202 #define DEFAULT_BATCH_SIZE "100"
203 #define MAX_BATCH_SIZE 1000
204 #define DEFAULT_BATCH_TIME "300"
205 #define MAX_BATCH_TIME 86400
206 #define DEFAULT_BATCH_SCHEDULER_ONLY "0"
207 #define DEFAULT_BATCH_SAFE_SHUTDOWN "1"
209 #define CDR_DEBUG(mod_cfg, fmt, ...) \
211 if (ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG)) { \
212 ast_verb(1, (fmt), ##__VA_ARGS__); \
215 static void cdr_detach(struct ast_cdr *cdr);
216 static void cdr_submit_batch(int shutdown);
218 /*! \brief The configuration settings for this module */
219 struct module_config {
220 struct ast_cdr_config *general; /*< CDR global settings */
223 /*! \brief The container for the module configuration */
224 static AO2_GLOBAL_OBJ_STATIC(module_configs);
226 /*! \brief The type definition for general options */
227 static struct aco_type general_option = {
230 .item_offset = offsetof(struct module_config, general),
231 .category = "^general$",
232 .category_match = ACO_WHITELIST,
235 static void *module_config_alloc(void);
236 static void module_config_destructor(void *obj);
238 /*! \brief The file definition */
239 static struct aco_file module_file_conf = {
240 .filename = "cdr.conf",
241 .skip_category = "(^csv$|^custom$|^manager$|^odbc$|^pgsql$|^radius$|^sqlite$|^tds$|^mysql$)",
242 .types = ACO_TYPES(&general_option),
245 CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc,
246 .files = ACO_FILES(&module_file_conf),
249 static struct aco_type *general_options[] = ACO_TYPES(&general_option);
251 /*! \brief Dispose of a module config object */
252 static void module_config_destructor(void *obj)
254 struct module_config *cfg = obj;
259 ao2_ref(cfg->general, -1);
262 /*! \brief Create a new module config object */
263 static void *module_config_alloc(void)
265 struct module_config *mod_cfg;
266 struct ast_cdr_config *cdr_config;
268 mod_cfg = ao2_alloc(sizeof(*mod_cfg), module_config_destructor);
273 cdr_config = ao2_alloc(sizeof(*cdr_config), NULL);
275 ao2_ref(cdr_config, -1);
278 mod_cfg->general = cdr_config;
283 /*! \brief Registration object for CDR backends */
288 AST_RWLIST_ENTRY(cdr_beitem) list;
291 /*! \brief List of registered backends */
292 static AST_RWLIST_HEAD_STATIC(be_list, cdr_beitem);
294 /*! \brief Queued CDR waiting to be batched */
295 struct cdr_batch_item {
297 struct cdr_batch_item *next;
300 /*! \brief The actual batch queue */
301 static struct cdr_batch {
303 struct cdr_batch_item *head;
304 struct cdr_batch_item *tail;
307 /*! \brief The global sequence counter used for CDRs */
308 static int global_cdr_sequence = 0;
310 /*! \brief Scheduler items */
311 static struct ast_sched_context *sched;
312 static int cdr_sched = -1;
313 AST_MUTEX_DEFINE_STATIC(cdr_sched_lock);
314 static pthread_t cdr_thread = AST_PTHREADT_NULL;
316 /*! \brief Lock protecting modifications to the batch queue */
317 AST_MUTEX_DEFINE_STATIC(cdr_batch_lock);
319 /*! \brief These are used to wake up the CDR thread when there's work to do */
320 AST_MUTEX_DEFINE_STATIC(cdr_pending_lock);
321 static ast_cond_t cdr_pending_cond;
323 /*! \brief A container of the active CDRs indexed by Party A channel name */
324 static struct ao2_container *active_cdrs_by_channel;
326 /*! \brief Message router for stasis messages regarding channel state */
327 static struct stasis_message_router *stasis_router;
329 /*! \brief Our subscription for bridges */
330 static struct stasis_subscription *bridge_subscription;
332 /*! \brief Our subscription for channels */
333 static struct stasis_subscription *channel_subscription;
335 /*! \brief Our subscription for parking */
336 static struct stasis_subscription *parking_subscription;
338 /*! \brief The parent topic for all topics we want to aggregate for CDRs */
339 static struct stasis_topic *cdr_topic;
343 /*! \brief Return types for \ref process_bridge_enter functions */
344 enum process_bridge_enter_results {
346 * The CDR was the only party in the bridge.
348 BRIDGE_ENTER_ONLY_PARTY,
350 * The CDR was able to obtain a Party B from some other party already in the bridge
352 BRIDGE_ENTER_OBTAINED_PARTY_B,
354 * The CDR was not able to obtain a Party B
356 BRIDGE_ENTER_NO_PARTY_B,
358 * This CDR can't handle a bridge enter message and a new CDR needs to be created
360 BRIDGE_ENTER_NEED_CDR,
364 * \brief A virtual table used for \ref cdr_object.
366 * Note that all functions are optional - if a subclass does not need an
367 * implementation, it is safe to leave it NULL.
369 struct cdr_object_fn_table {
370 /*! \brief Name of the subclass */
374 * \brief An initialization function. This will be called automatically
375 * when a \ref cdr_object is switched to this type in
376 * \ref cdr_object_transition_state
378 * \param cdr The \ref cdr_object that was just transitioned
380 void (* const init_function)(struct cdr_object *cdr);
383 * \brief Process a Party A update for the \ref cdr_object
385 * \param cdr The \ref cdr_object to process the update
386 * \param snapshot The snapshot for the CDR's Party A
387 * \retval 0 the CDR handled the update or ignored it
388 * \retval 1 the CDR is finalized and a new one should be made to handle it
390 int (* const process_party_a)(struct cdr_object *cdr,
391 struct ast_channel_snapshot *snapshot);
394 * \brief Process a Party B update for the \ref cdr_object
396 * \param cdr The \ref cdr_object to process the update
397 * \param snapshot The snapshot for the CDR's Party B
399 void (* const process_party_b)(struct cdr_object *cdr,
400 struct ast_channel_snapshot *snapshot);
403 * \brief Process the beginning of a dial. A dial message implies one of two
405 * The \ref cdr_object's Party A has been originated
406 * The \ref cdr_object's Party A is dialing its Party B
408 * \param cdr The \ref cdr_object
409 * \param caller The originator of the dial attempt
410 * \param peer The destination of the dial attempt
412 * \retval 0 if the parties in the dial were handled by this CDR
413 * \retval 1 if the parties could not be handled by this CDR
415 int (* const process_dial_begin)(struct cdr_object *cdr,
416 struct ast_channel_snapshot *caller,
417 struct ast_channel_snapshot *peer);
420 * \brief Process the end of a dial. At the end of a dial, a CDR can be
421 * transitioned into one of two states - DialedPending
422 * (\ref dialed_pending_state_fn_table) or Finalized
423 * (\ref finalized_state_fn_table).
425 * \param cdr The \ref cdr_object
426 * \param caller The originator of the dial attempt
427 * \param peer the Destination of the dial attempt
428 * \param dial_status What happened
430 * \retval 0 if the parties in the dial were handled by this CDR
431 * \retval 1 if the parties could not be handled by this CDR
433 int (* const process_dial_end)(struct cdr_object *cdr,
434 struct ast_channel_snapshot *caller,
435 struct ast_channel_snapshot *peer,
436 const char *dial_status);
439 * \brief Process the entering of a bridge by this CDR. The purpose of this
440 * callback is to have the CDR prepare itself for the bridge and attempt to
441 * find a valid Party B. The act of creating new CDRs based on the entering
442 * of this channel into the bridge is handled by the higher level message
445 * Note that this handler is for when a channel enters into a "normal"
446 * bridge, where people actually talk to each other. Parking is its own
449 * \param cdr The \ref cdr_object
450 * \param bridge The bridge that the Party A just entered into
451 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
453 * \retval process_bridge_enter_results Defines whether or not this CDR was able
454 * to fully handle the bridge enter message.
456 enum process_bridge_enter_results (* const process_bridge_enter)(
457 struct cdr_object *cdr,
458 struct ast_bridge_snapshot *bridge,
459 struct ast_channel_snapshot *channel);
462 * \brief Process entering into a parking bridge.
464 * \param cdr The \ref cdr_object
465 * \param bridge The parking bridge that Party A just entered into
466 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
468 * \retval 0 This CDR successfully transitioned itself into the parked state
469 * \retval 1 This CDR couldn't handle the parking transition and we need a
472 int (* const process_parking_bridge_enter)(struct cdr_object *cdr,
473 struct ast_bridge_snapshot *bridge,
474 struct ast_channel_snapshot *channel);
477 * \brief Process the leaving of a bridge by this CDR.
479 * \param cdr The \ref cdr_object
480 * \param bridge The bridge that the Party A just left
481 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
483 * \retval 0 This CDR left successfully
486 int (* const process_bridge_leave)(struct cdr_object *cdr,
487 struct ast_bridge_snapshot *bridge,
488 struct ast_channel_snapshot *channel);
491 * \brief Process an update informing us that the channel got itself parked
493 * \param cdr The \ref cdr_object
494 * \param channel The parking information for this CDR's party A
496 * \retval 0 This CDR successfully parked itself
497 * \retval 1 This CDR couldn't handle the park
499 int (* const process_parked_channel)(struct cdr_object *cdr,
500 struct ast_parked_call_payload *parking_info);
503 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
504 static enum process_bridge_enter_results base_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
505 static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
506 static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
507 static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info);
509 static void single_state_init_function(struct cdr_object *cdr);
510 static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
511 static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
512 static enum process_bridge_enter_results single_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
513 static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
516 * \brief The virtual table for the Single state.
518 * A \ref cdr_object starts off in this state. This represents a channel that
519 * has no Party B information itself.
521 * A \ref cdr_object from this state can go into any of the following states:
522 * * \ref dial_state_fn_table
523 * * \ref bridge_state_fn_table
524 * * \ref finalized_state_fn_table
526 struct cdr_object_fn_table single_state_fn_table = {
528 .init_function = single_state_init_function,
529 .process_party_a = base_process_party_a,
530 .process_party_b = single_state_process_party_b,
531 .process_dial_begin = single_state_process_dial_begin,
532 .process_dial_end = base_process_dial_end,
533 .process_bridge_enter = single_state_process_bridge_enter,
534 .process_parking_bridge_enter = single_state_process_parking_bridge_enter,
535 .process_bridge_leave = base_process_bridge_leave,
536 .process_parked_channel = base_process_parked_channel,
539 static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
540 static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
541 static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
542 static enum process_bridge_enter_results dial_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
545 * \brief The virtual table for the Dial state.
547 * A \ref cdr_object that has begun a dial operation. This state is entered when
548 * the Party A for a CDR is determined to be dialing out to a Party B or when
549 * a CDR is for an originated channel (in which case the Party A information is
550 * the originated channel, and there is no Party B).
552 * A \ref cdr_object from this state can go in any of the following states:
553 * * \ref dialed_pending_state_fn_table
554 * * \ref bridge_state_fn_table
555 * * \ref finalized_state_fn_table
557 struct cdr_object_fn_table dial_state_fn_table = {
559 .process_party_a = base_process_party_a,
560 .process_party_b = dial_state_process_party_b,
561 .process_dial_begin = dial_state_process_dial_begin,
562 .process_dial_end = dial_state_process_dial_end,
563 .process_bridge_enter = dial_state_process_bridge_enter,
564 .process_bridge_leave = base_process_bridge_leave,
567 static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
568 static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
569 static enum process_bridge_enter_results dialed_pending_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
570 static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
573 * \brief The virtual table for the Dialed Pending state.
575 * A \ref cdr_object that has successfully finished a dial operation, but we
576 * don't know what they're going to do yet. It's theoretically possible to dial
577 * a party and then have that party not be bridged with the caller; likewise,
578 * an origination can complete and the channel go off and execute dialplan. The
579 * pending state acts as a bridge between either:
580 * * Entering a bridge
581 * * Getting a new CDR for new dialplan execution
582 * * Switching from being originated to executing dialplan
584 * A \ref cdr_object from this state can go in any of the following states:
585 * * \ref single_state_fn_table
586 * * \ref dialed_pending_state_fn_table
587 * * \ref bridge_state_fn_table
588 * * \ref finalized_state_fn_table
590 struct cdr_object_fn_table dialed_pending_state_fn_table = {
591 .name = "DialedPending",
592 .process_party_a = dialed_pending_state_process_party_a,
593 .process_dial_begin = dialed_pending_state_process_dial_begin,
594 .process_bridge_enter = dialed_pending_state_process_bridge_enter,
595 .process_parking_bridge_enter = dialed_pending_state_process_parking_bridge_enter,
596 .process_bridge_leave = base_process_bridge_leave,
597 .process_parked_channel = base_process_parked_channel,
600 static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
601 static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
604 * \brief The virtual table for the Bridged state
606 * A \ref cdr_object enters this state when it receives notification that the
607 * channel has entered a bridge.
609 * A \ref cdr_object from this state can go to:
610 * * \ref finalized_state_fn_table
612 struct cdr_object_fn_table bridge_state_fn_table = {
614 .process_party_a = base_process_party_a,
615 .process_party_b = bridge_state_process_party_b,
616 .process_bridge_leave = bridge_state_process_bridge_leave,
617 .process_parked_channel = base_process_parked_channel,
620 static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
623 * \brief The virtual table for the Parked state
625 * Parking is weird. Unlike typical bridges, it has to be treated somewhat
626 * uniquely - a channel in a parking bridge (which is a subclass of a holding
627 * bridge) has to be handled as if the channel went into an application.
628 * However, when the channel comes out, we need a new CDR - unlike the Single
631 struct cdr_object_fn_table parked_state_fn_table = {
633 .process_party_a = base_process_party_a,
634 .process_bridge_leave = parked_state_process_bridge_leave,
635 .process_parked_channel = base_process_parked_channel,
638 static void finalized_state_init_function(struct cdr_object *cdr);
639 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
642 * \brief The virtual table for the finalized state.
644 * Once in the finalized state, the CDR is done. No modifications can be made
647 struct cdr_object_fn_table finalized_state_fn_table = {
649 .init_function = finalized_state_init_function,
650 .process_party_a = finalized_state_process_party_a,
651 .process_bridge_enter = base_process_bridge_enter,
654 /*! \brief A wrapper object around a snapshot.
655 * Fields that are mutable by the CDR engine are replicated here.
657 struct cdr_object_snapshot {
658 struct ast_channel_snapshot *snapshot; /*!< The channel snapshot */
659 char userfield[AST_MAX_USER_FIELD]; /*!< Userfield for the channel */
660 unsigned int flags; /*!< Specific flags for this party */
661 struct varshead variables; /*!< CDR variables for the channel */
664 /*! \brief An in-memory representation of an active CDR */
666 struct cdr_object_snapshot party_a; /*!< The Party A information */
667 struct cdr_object_snapshot party_b; /*!< The Party B information */
668 struct cdr_object_fn_table *fn_table; /*!< The current virtual table */
670 enum ast_cdr_disposition disposition; /*!< The disposition of the CDR */
671 struct timeval start; /*!< When this CDR was created */
672 struct timeval answer; /*!< Either when the channel was answered, or when the path between channels was established */
673 struct timeval end; /*!< When this CDR was finalized */
674 unsigned int sequence; /*!< A monotonically increasing number for each CDR */
675 struct ast_flags flags; /*!< Flags on the CDR */
676 AST_DECLARE_STRING_FIELDS(
677 AST_STRING_FIELD(linkedid); /*!< Linked ID. Cached here as it may change out from party A, which must be immutable */
678 AST_STRING_FIELD(name); /*!< Channel name of party A. Cached here as the party A address may change */
679 AST_STRING_FIELD(bridge); /*!< The bridge the party A happens to be in. */
680 AST_STRING_FIELD(appl); /*!< The last accepted application party A was in */
681 AST_STRING_FIELD(data); /*!< The data for the last accepted application party A was in */
683 struct cdr_object *next; /*!< The next CDR object in the chain */
684 struct cdr_object *last; /*!< The last CDR object in the chain */
688 * \brief Copy variables from one list to another
689 * \param to_list destination
690 * \param from_list source
691 * \retval The number of copied variables
693 static int copy_variables(struct varshead *to_list, struct varshead *from_list)
695 struct ast_var_t *variables;
696 struct ast_var_t *newvariable;
701 AST_LIST_TRAVERSE(from_list, variables, entries) {
702 var = ast_var_name(variables);
703 if (ast_strlen_zero(var)) {
706 val = ast_var_value(variables);
707 if (ast_strlen_zero(val)) {
710 newvariable = ast_var_assign(var, val);
712 AST_LIST_INSERT_HEAD(to_list, newvariable, entries);
721 * \brief Delete all variables from a variable list
722 * \param headp The head pointer to the variable list to delete
724 static void free_variables(struct varshead *headp)
726 struct ast_var_t *vardata;
728 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
729 ast_var_delete(vardata);
734 * \brief Copy a snapshot and its details
735 * \param dst The destination
736 * \param src The source
738 static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
741 ao2_t_ref(dst->snapshot, -1, "release old snapshot during copy");
743 dst->snapshot = src->snapshot;
744 ao2_t_ref(dst->snapshot, +1, "bump new snapshot during copy");
745 strcpy(dst->userfield, src->userfield);
746 dst->flags = src->flags;
747 copy_variables(&dst->variables, &src->variables);
751 * \brief Transition a \ref cdr_object to a new state
752 * \param cdr The \ref cdr_object to transition
753 * \param fn_table The \ref cdr_object_fn_table state to go to
755 static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
757 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
759 CDR_DEBUG(mod_cfg, "%p - Transitioning CDR for %s from state %s to %s\n",
760 cdr, cdr->party_a.snapshot->name,
761 cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
762 cdr->fn_table = fn_table;
763 if (cdr->fn_table->init_function) {
764 cdr->fn_table->init_function(cdr);
768 * \brief Hash function for containers of CDRs indexing by Party A name */
769 static int cdr_object_channel_hash_fn(const void *obj, const int flags)
771 const struct cdr_object *cdr = obj;
772 const char *name = (flags & OBJ_KEY) ? obj : cdr->name;
773 return ast_str_case_hash(name);
777 * \brief Comparison function for containers of CDRs indexing by Party A name
779 static int cdr_object_channel_cmp_fn(void *obj, void *arg, int flags)
781 struct cdr_object *left = obj;
782 struct cdr_object *right = arg;
783 const char *match = (flags & OBJ_KEY) ? arg : right->name;
784 return strcasecmp(left->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
788 * \brief Comparison function for containers of CDRs indexing by bridge. Note
789 * that we expect there to be collisions, as a single bridge may have multiple
790 * CDRs active at one point in time
792 static int cdr_object_bridge_cmp_fn(void *obj, void *arg, int flags)
794 struct cdr_object *left = obj;
795 struct cdr_object *it_cdr;
796 const char *match = arg;
798 for (it_cdr = left; it_cdr; it_cdr = it_cdr->next) {
799 if (!strcasecmp(it_cdr->bridge, match)) {
807 * \brief \ref cdr_object Destructor
809 static void cdr_object_dtor(void *obj)
811 struct cdr_object *cdr = obj;
812 struct ast_var_t *it_var;
818 ao2_cleanup(cdr->party_a.snapshot);
819 ao2_cleanup(cdr->party_b.snapshot);
820 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_a.variables, entries))) {
821 ast_var_delete(it_var);
823 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_b.variables, entries))) {
824 ast_var_delete(it_var);
826 ast_string_field_free_memory(cdr);
829 ao2_cleanup(cdr->next);
834 * \brief \ref cdr_object constructor
835 * \param chan The \ref ast_channel_snapshot that is the CDR's Party A
837 * This implicitly sets the state of the newly created CDR to the Single state
838 * (\ref single_state_fn_table)
840 static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan)
842 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
843 struct cdr_object *cdr;
845 ast_assert(chan != NULL);
847 cdr = ao2_alloc(sizeof(*cdr), cdr_object_dtor);
852 if (ast_string_field_init(cdr, 64)) {
855 ast_string_field_set(cdr, name, chan->name);
856 ast_string_field_set(cdr, linkedid, chan->linkedid);
857 cdr->disposition = AST_CDR_NULL;
858 cdr->sequence = ast_atomic_fetchadd_int(&global_cdr_sequence, +1);
860 cdr->party_a.snapshot = chan;
861 ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
863 CDR_DEBUG(mod_cfg, "%p - Created CDR for channel %s\n", cdr, chan->name);
865 cdr_object_transition_state(cdr, &single_state_fn_table);
871 * \brief Create a new \ref cdr_object and append it to an existing chain
872 * \param cdr The \ref cdr_object to append to
874 static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr)
876 struct cdr_object *new_cdr;
877 struct cdr_object *it_cdr;
878 struct cdr_object *cdr_last;
880 cdr_last = cdr->last;
881 new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot);
885 new_cdr->disposition = AST_CDR_NULL;
887 /* Copy over the linkedid, as it may have changed */
888 ast_string_field_set(new_cdr, linkedid, cdr_last->linkedid);
889 ast_string_field_set(new_cdr, appl, cdr_last->appl);
890 ast_string_field_set(new_cdr, data, cdr_last->data);
892 /* Copy over other Party A information */
893 cdr_object_snapshot_copy(&new_cdr->party_a, &cdr_last->party_a);
895 /* Append the CDR to the end of the list */
896 for (it_cdr = cdr; it_cdr->next; it_cdr = it_cdr->next) {
897 it_cdr->last = new_cdr;
899 it_cdr->last = new_cdr;
900 it_cdr->next = new_cdr;
906 * \brief Return whether or not a channel has changed its state in the dialplan, subject
907 * to endbeforehexten logic
909 * \param old_snapshot The previous state
910 * \param new_snapshot The new state
912 * \retval 0 if the state has not changed
913 * \retval 1 if the state changed
915 static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
916 struct ast_channel_snapshot *new_snapshot)
918 RAII_VAR(struct module_config *, mod_cfg,
919 ao2_global_obj_ref(module_configs), ao2_cleanup);
921 /* If we ignore hangup logic, don't indicate that we're executing anything new */
922 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
923 && ast_test_flag(&new_snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
927 /* When Party A is originated to an application and the application exits, the stack
928 * will attempt to clear the application and restore the dummy originate application
929 * of "AppDialX". Ignore application changes to AppDialX as a result.
931 if (strcmp(new_snapshot->appl, old_snapshot->appl) && strncasecmp(new_snapshot->appl, "appdial", 7)
932 && (strcmp(new_snapshot->context, old_snapshot->context)
933 || strcmp(new_snapshot->exten, old_snapshot->exten)
934 || new_snapshot->priority != old_snapshot->priority)) {
942 * \brief Return whether or not a \ref ast_channel_snapshot is for a channel
943 * that was created as the result of a dial operation
945 * \retval 0 the channel was not created as the result of a dial
946 * \retval 1 the channel was created as the result of a dial
948 static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
950 return (ast_test_flag(&snapshot->flags, AST_FLAG_OUTGOING)
951 && !(ast_test_flag(&snapshot->flags, AST_FLAG_ORIGINATED)));
955 * \brief Given two CDR snapshots, figure out who should be Party A for the
957 * \param left One of the snapshots
958 * \param right The other snapshot
959 * \retval The snapshot that won
961 static struct cdr_object_snapshot *cdr_object_pick_party_a(struct cdr_object_snapshot *left, struct cdr_object_snapshot *right)
963 /* Check whether or not the party is dialed. A dialed party is never the
964 * Party A with a party that was not dialed.
966 if (!snapshot_is_dialed(left->snapshot) && snapshot_is_dialed(right->snapshot)) {
968 } else if (snapshot_is_dialed(left->snapshot) && !snapshot_is_dialed(right->snapshot)) {
972 /* Try the Party A flag */
973 if (ast_test_flag(left, AST_CDR_FLAG_PARTY_A) && !ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
975 } else if (!ast_test_flag(right, AST_CDR_FLAG_PARTY_A) && ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
979 /* Neither party is dialed and neither has the Party A flag - defer to
981 if (left->snapshot->creationtime.tv_sec < right->snapshot->creationtime.tv_sec) {
983 } else if (left->snapshot->creationtime.tv_sec > right->snapshot->creationtime.tv_sec) {
985 } else if (left->snapshot->creationtime.tv_usec > right->snapshot->creationtime.tv_usec) {
988 /* Okay, fine, take the left one */
994 * Compute the duration for a \ref cdr_object
996 static long cdr_object_get_duration(struct cdr_object *cdr)
998 return (long)(ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->start) / 1000);
1002 * \brief Compute the billsec for a \ref cdr_object
1004 static long cdr_object_get_billsec(struct cdr_object *cdr)
1006 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1009 if (ast_tvzero(cdr->answer)) {
1012 ms = ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->answer);
1013 if (ast_test_flag(&mod_cfg->general->settings, CDR_INITIATED_SECONDS)
1014 && (ms % 1000 >= 500)) {
1015 ms = (ms / 1000) + 1;
1025 * \brief Set a variable on a CDR object
1027 * \param headp The header pointer to the variable to set
1028 * \param name The name of the variable
1029 * \param value The value of the variable
1031 static void set_variable(struct varshead *headp, const char *name, const char *value)
1033 struct ast_var_t *newvariable;
1035 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1036 if (!strcasecmp(ast_var_name(newvariable), name)) {
1037 AST_LIST_REMOVE_CURRENT(entries);
1038 ast_var_delete(newvariable);
1042 AST_LIST_TRAVERSE_SAFE_END;
1044 if (value && (newvariable = ast_var_assign(name, value))) {
1045 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1050 * \brief Create a chain of \ref ast_cdr objects from a chain of \ref cdr_object
1051 * suitable for consumption by the registered CDR backends
1052 * \param cdr The \ref cdr_object to convert to a public record
1053 * \retval A chain of \ref ast_cdr objects on success
1054 * \retval NULL on failure
1056 static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr)
1058 struct ast_cdr *pub_cdr = NULL, *cdr_prev = NULL;
1059 struct cdr_object *it_cdr;
1060 struct ast_var_t *it_var, *it_copy_var;
1061 struct ast_channel_snapshot *party_a;
1062 struct ast_channel_snapshot *party_b;
1064 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1065 struct ast_cdr *cdr_copy;
1067 /* Don't create records for CDRs where the party A was a dialed channel */
1068 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
1072 cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
1078 party_a = it_cdr->party_a.snapshot;
1079 party_b = it_cdr->party_b.snapshot;
1082 ast_assert(party_a != NULL);
1083 ast_copy_string(cdr_copy->accountcode, party_a->accountcode, sizeof(cdr_copy->accountcode));
1084 cdr_copy->amaflags = party_a->amaflags;
1085 ast_copy_string(cdr_copy->channel, party_a->name, sizeof(cdr_copy->channel));
1086 ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller_name, party_a->caller_number, "");
1087 ast_copy_string(cdr_copy->src, party_a->caller_number, sizeof(cdr_copy->src));
1088 ast_copy_string(cdr_copy->uniqueid, party_a->uniqueid, sizeof(cdr_copy->uniqueid));
1089 ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
1090 ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
1091 ast_copy_string(cdr_copy->dst, party_a->exten, sizeof(cdr_copy->dst));
1092 ast_copy_string(cdr_copy->dcontext, party_a->context, sizeof(cdr_copy->dcontext));
1096 ast_copy_string(cdr_copy->dstchannel, party_b->name, sizeof(cdr_copy->dstchannel));
1097 ast_copy_string(cdr_copy->peeraccount, party_b->accountcode, sizeof(cdr_copy->peeraccount));
1098 if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
1099 snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
1102 if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) {
1103 ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield));
1106 /* Timestamps/durations */
1107 cdr_copy->start = it_cdr->start;
1108 cdr_copy->answer = it_cdr->answer;
1109 cdr_copy->end = it_cdr->end;
1110 cdr_copy->billsec = cdr_object_get_billsec(it_cdr);
1111 cdr_copy->duration = cdr_object_get_duration(it_cdr);
1114 ast_copy_flags(cdr_copy, &it_cdr->flags, AST_FLAGS_ALL);
1115 ast_copy_string(cdr_copy->linkedid, it_cdr->linkedid, sizeof(cdr_copy->linkedid));
1116 cdr_copy->disposition = it_cdr->disposition;
1117 cdr_copy->sequence = it_cdr->sequence;
1120 copy_variables(&cdr_copy->varshead, &it_cdr->party_a.variables);
1121 AST_LIST_TRAVERSE(&it_cdr->party_b.variables, it_var, entries) {
1123 struct ast_var_t *newvariable;
1124 AST_LIST_TRAVERSE(&cdr_copy->varshead, it_copy_var, entries) {
1125 if (!strcasecmp(ast_var_name(it_var), ast_var_name(it_copy_var))) {
1130 if (!found && (newvariable = ast_var_assign(ast_var_name(it_var), ast_var_value(it_var)))) {
1131 AST_LIST_INSERT_TAIL(&cdr_copy->varshead, newvariable, entries);
1139 cdr_prev->next = cdr_copy;
1140 cdr_prev = cdr_copy;
1148 * \brief Dispatch a CDR.
1149 * \param cdr The \ref cdr_object to dispatch
1151 * This will create a \ref ast_cdr object and publish it to the various backends
1153 static void cdr_object_dispatch(struct cdr_object *cdr)
1155 RAII_VAR(struct module_config *, mod_cfg,
1156 ao2_global_obj_ref(module_configs), ao2_cleanup);
1157 struct ast_cdr *pub_cdr;
1159 CDR_DEBUG(mod_cfg, "%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
1160 cdr->party_a.snapshot->name,
1161 cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<none>");
1162 pub_cdr = cdr_object_create_public_records(cdr);
1163 cdr_detach(pub_cdr);
1167 * \brief Set the disposition on a \ref cdr_object based on a hangupcause code
1168 * \param cdr The \ref cdr_object
1169 * \param hangupcause The Asterisk hangup cause code
1171 static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
1173 RAII_VAR(struct module_config *, mod_cfg,
1174 ao2_global_obj_ref(module_configs), ao2_cleanup);
1176 /* Change the disposition based on the hang up cause */
1177 switch (hangupcause) {
1178 case AST_CAUSE_BUSY:
1179 cdr->disposition = AST_CDR_BUSY;
1181 case AST_CAUSE_CONGESTION:
1182 if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
1183 cdr->disposition = AST_CDR_FAILED;
1185 cdr->disposition = AST_CDR_CONGESTION;
1188 case AST_CAUSE_NO_ROUTE_DESTINATION:
1189 case AST_CAUSE_UNREGISTERED:
1190 cdr->disposition = AST_CDR_FAILED;
1192 case AST_CAUSE_NORMAL_CLEARING:
1193 case AST_CAUSE_NO_ANSWER:
1194 cdr->disposition = AST_CDR_NOANSWER;
1202 * \brief Finalize a CDR.
1204 * This function is safe to call multiple times. Note that you can call this
1205 * explicitly before going to the finalized state if there's a chance the CDR
1206 * will be re-activated, in which case the \ref cdr_object's end time should be
1207 * cleared. This function is implicitly called when a CDR transitions to the
1208 * finalized state and right before it is dispatched
1210 * \param cdr_object The CDR to finalize
1212 static void cdr_object_finalize(struct cdr_object *cdr)
1214 RAII_VAR(struct module_config *, mod_cfg,
1215 ao2_global_obj_ref(module_configs), ao2_cleanup);
1217 if (!ast_tvzero(cdr->end)) {
1220 cdr->end = ast_tvnow();
1222 if (cdr->disposition == AST_CDR_NULL) {
1223 if (!ast_tvzero(cdr->answer)) {
1224 cdr->disposition = AST_CDR_ANSWERED;
1225 } else if (cdr->party_a.snapshot->hangupcause) {
1226 cdr_object_set_disposition(cdr, cdr->party_a.snapshot->hangupcause);
1227 } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangupcause) {
1228 cdr_object_set_disposition(cdr, cdr->party_b.snapshot->hangupcause);
1230 cdr->disposition = AST_CDR_FAILED;
1234 /* tv_usec is suseconds_t, which could be int or long */
1235 ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dispo %s\n",
1236 cdr->party_a.snapshot->name,
1238 (long)cdr->start.tv_usec,
1240 (long)cdr->answer.tv_usec,
1242 (long)cdr->end.tv_usec,
1243 ast_cdr_disp2str(cdr->disposition));
1247 * \brief Check to see if a CDR needs to move to the finalized state because
1248 * its Party A hungup.
1250 static void cdr_object_check_party_a_hangup(struct cdr_object *cdr)
1252 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1254 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
1255 && ast_test_flag(&cdr->party_a.snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
1256 cdr_object_finalize(cdr);
1259 if (ast_test_flag(&cdr->party_a.snapshot->flags, AST_FLAG_DEAD)
1260 && cdr->fn_table != &finalized_state_fn_table) {
1261 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1266 * \brief Check to see if a CDR needs to be answered based on its Party A.
1267 * Note that this is safe to call as much as you want - we won't answer twice
1269 static void cdr_object_check_party_a_answer(struct cdr_object *cdr) {
1270 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1272 if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
1273 cdr->answer = ast_tvnow();
1274 /* tv_usec is suseconds_t, which could be int or long */
1275 CDR_DEBUG(mod_cfg, "%p - Set answered time to %ld.%06ld\n", cdr,
1277 (long)cdr->answer.tv_usec);
1281 /* \brief Set Caller ID information on a CDR */
1282 static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
1284 if (!old_snapshot->snapshot) {
1285 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
1286 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
1287 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
1290 if (!strcmp(old_snapshot->snapshot->caller_dnid, new_snapshot->caller_dnid)) {
1291 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
1293 if (!strcmp(old_snapshot->snapshot->caller_subaddr, new_snapshot->caller_subaddr)) {
1294 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
1296 if (!strcmp(old_snapshot->snapshot->dialed_subaddr, new_snapshot->dialed_subaddr)) {
1297 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
1302 * \brief Swap an old \ref cdr_object_snapshot's \ref ast_channel_snapshot for
1303 * a new \ref ast_channel_snapshot
1304 * \param old_snapshot The old \ref cdr_object_snapshot
1305 * \param new_snapshot The new \ref ast_channel_snapshot for old_snapshot
1307 static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot,
1308 struct ast_channel_snapshot *new_snapshot)
1310 cdr_object_update_cid(old_snapshot, new_snapshot);
1311 if (old_snapshot->snapshot) {
1312 ao2_t_ref(old_snapshot->snapshot, -1, "Drop ref for swap");
1314 ao2_t_ref(new_snapshot, +1, "Bump ref for swap");
1315 old_snapshot->snapshot = new_snapshot;
1318 /* BASE METHOD IMPLEMENTATIONS */
1320 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1322 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1324 ast_assert(strcasecmp(snapshot->name, cdr->party_a.snapshot->name) == 0);
1325 cdr_object_swap_snapshot(&cdr->party_a, snapshot);
1327 /* When Party A is originated to an application and the application exits, the stack
1328 * will attempt to clear the application and restore the dummy originate application
1329 * of "AppDialX". Prevent that, and any other application changes we might not want
1332 if (!ast_strlen_zero(snapshot->appl)
1333 && (strncasecmp(snapshot->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))
1334 && !ast_test_flag(&cdr->flags, AST_CDR_LOCK_APP)) {
1335 ast_string_field_set(cdr, appl, snapshot->appl);
1336 ast_string_field_set(cdr, data, snapshot->data);
1339 ast_string_field_set(cdr, linkedid, snapshot->linkedid);
1340 cdr_object_check_party_a_answer(cdr);
1341 cdr_object_check_party_a_hangup(cdr);
1346 static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1348 /* In general, most things shouldn't get a bridge leave */
1353 static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1355 /* In general, most things shouldn't get a dial end. */
1360 static enum process_bridge_enter_results base_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1362 /* Base process bridge enter simply indicates that we can't handle it */
1363 return BRIDGE_ENTER_NEED_CDR;
1366 static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
1368 char park_info[128];
1370 ast_assert(!strcasecmp(parking_info->parkee->name, cdr->party_a.snapshot->name));
1372 /* Update Party A information regardless */
1373 cdr->fn_table->process_party_a(cdr, parking_info->parkee);
1375 /* Fake out where we're parked */
1376 ast_string_field_set(cdr, appl, "Park");
1377 snprintf(park_info, sizeof(park_info), "%s:%u", parking_info->parkinglot, parking_info->parkingspace);
1378 ast_string_field_set(cdr, data, park_info);
1380 /* Prevent any further changes to the App/Data fields for this record */
1381 ast_set_flag(&cdr->flags, AST_CDR_LOCK_APP);
1388 static void single_state_init_function(struct cdr_object *cdr) {
1389 cdr->start = ast_tvnow();
1390 cdr_object_check_party_a_answer(cdr);
1393 static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1395 /* This should never happen! */
1396 ast_assert(cdr->party_b.snapshot == NULL);
1401 static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1403 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1405 if (caller && !strcasecmp(cdr->party_a.snapshot->name, caller->name)) {
1406 cdr_object_swap_snapshot(&cdr->party_a, caller);
1407 CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr,
1408 cdr->party_a.snapshot->name);
1409 cdr_object_swap_snapshot(&cdr->party_b, peer);
1410 CDR_DEBUG(mod_cfg, "%p - Updated Party B %s snapshot\n", cdr,
1411 cdr->party_b.snapshot->name);
1412 } else if (!strcasecmp(cdr->party_a.snapshot->name, peer->name)) {
1413 /* We're the entity being dialed, i.e., outbound origination */
1414 cdr_object_swap_snapshot(&cdr->party_a, peer);
1415 CDR_DEBUG(mod_cfg, "%p - Updated Party A %s snapshot\n", cdr,
1416 cdr->party_a.snapshot->name);
1419 cdr_object_transition_state(cdr, &dial_state_fn_table);
1424 * \brief Handle a comparison between our \ref cdr_object and a \ref cdr_object
1425 * already in the bridge while in the Single state. The goal of this is to find
1426 * a Party B for our CDR.
1428 * \param cdr Our \ref cdr_object in the Single state
1429 * \param cand_cdr The \ref cdr_object already in the Bridge state
1431 * \retval 0 The cand_cdr had a Party A or Party B that we could use as our
1433 * \retval 1 No party in the cand_cdr could be used as our Party B
1435 static int single_state_bridge_enter_comparison(struct cdr_object *cdr,
1436 struct cdr_object *cand_cdr)
1438 struct cdr_object_snapshot *party_a;
1440 /* Don't match on ourselves */
1441 if (!strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)) {
1445 /* Try the candidate CDR's Party A first */
1446 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
1447 if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
1448 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1449 if (!cand_cdr->party_b.snapshot) {
1450 /* We just stole them - finalize their CDR. Note that this won't
1451 * transition their state, it just sets the end time and the
1452 * disposition - if we need to re-activate them later, we can.
1454 cdr_object_finalize(cand_cdr);
1459 /* Try their Party B, unless it's us */
1460 if (!cand_cdr->party_b.snapshot
1461 || !strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name)) {
1464 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
1465 if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
1466 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
1473 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)
1475 struct ao2_iterator *it_cdrs;
1476 struct cdr_object *cand_cdr_master;
1477 char *bridge_id = ast_strdupa(bridge->uniqueid);
1480 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1482 /* Get parties in the bridge */
1483 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
1484 cdr_object_bridge_cmp_fn, bridge_id);
1486 /* No one in the bridge yet! */
1487 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1488 return BRIDGE_ENTER_ONLY_PARTY;
1491 while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
1492 struct cdr_object *cand_cdr;
1493 RAII_VAR(struct cdr_object *, cdr_cleanup, cand_cdr_master, ao2_cleanup);
1494 SCOPED_AO2LOCK(lock, cand_cdr_master);
1496 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1497 /* Skip any records that are not in a bridge or in this bridge.
1498 * I'm not sure how that would happen, but it pays to be careful. */
1499 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1500 strcmp(cdr->bridge, cand_cdr->bridge)) {
1504 if (single_state_bridge_enter_comparison(cdr, cand_cdr)) {
1507 /* We successfully got a party B - break out */
1512 ao2_iterator_destroy(it_cdrs);
1514 /* We always transition state, even if we didn't get a peer */
1515 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1517 /* Success implies that we have a Party B */
1519 return BRIDGE_ENTER_OBTAINED_PARTY_B;
1522 return BRIDGE_ENTER_NO_PARTY_B;
1525 static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1527 cdr_object_transition_state(cdr, &parked_state_fn_table);
1534 static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1536 ast_assert(snapshot != NULL);
1538 if (!cdr->party_b.snapshot
1539 || strcasecmp(cdr->party_b.snapshot->name, snapshot->name)) {
1542 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1544 /* If party B hangs up, finalize this CDR */
1545 if (ast_test_flag(&cdr->party_b.snapshot->flags, AST_FLAG_DEAD)) {
1546 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1550 static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1552 /* Don't process a begin dial here. A party A already in the dial state will
1553 * who receives a dial begin for something else will be handled by the
1554 * message router callback and will add a new CDR for the party A */
1560 * \brief Convert a dial status to a CDR disposition
1562 static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
1564 RAII_VAR(struct module_config *, mod_cfg,
1565 ao2_global_obj_ref(module_configs), ao2_cleanup);
1567 if (!strcmp(dial_status, "ANSWER")) {
1568 return AST_CDR_ANSWERED;
1569 } else if (!strcmp(dial_status, "BUSY")) {
1570 return AST_CDR_BUSY;
1571 } else if (!strcmp(dial_status, "CANCEL") || !strcmp(dial_status, "NOANSWER")) {
1572 return AST_CDR_NOANSWER;
1573 } else if (!strcmp(dial_status, "CONGESTION")) {
1574 if (!ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION)) {
1575 return AST_CDR_FAILED;
1577 return AST_CDR_CONGESTION;
1579 } else if (!strcmp(dial_status, "FAILED")) {
1580 return AST_CDR_FAILED;
1582 return AST_CDR_FAILED;
1585 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)
1587 RAII_VAR(struct module_config *, mod_cfg,
1588 ao2_global_obj_ref(module_configs), ao2_cleanup);
1589 struct ast_channel_snapshot *party_a;
1596 ast_assert(!strcasecmp(cdr->party_a.snapshot->name, party_a->name));
1597 cdr_object_swap_snapshot(&cdr->party_a, party_a);
1599 if (cdr->party_b.snapshot) {
1600 if (strcasecmp(cdr->party_b.snapshot->name, peer->name)) {
1601 /* Not the status for this CDR - defer back to the message router */
1604 cdr_object_swap_snapshot(&cdr->party_b, peer);
1607 /* Set the disposition based on the dial string. */
1608 cdr->disposition = dial_status_to_disposition(dial_status);
1609 if (cdr->disposition == AST_CDR_ANSWERED) {
1610 /* Switch to dial pending to wait and see what the caller does */
1611 cdr_object_transition_state(cdr, &dialed_pending_state_fn_table);
1613 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1619 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)
1621 struct ao2_iterator *it_cdrs;
1622 char *bridge_id = ast_strdupa(bridge->uniqueid);
1623 struct cdr_object *cand_cdr_master;
1626 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1628 /* Get parties in the bridge */
1629 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
1630 cdr_object_bridge_cmp_fn, bridge_id);
1632 /* No one in the bridge yet! */
1633 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1634 return BRIDGE_ENTER_ONLY_PARTY;
1637 while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
1638 struct cdr_object *cand_cdr;
1639 RAII_VAR(struct cdr_object *, cdr_cleanup, cand_cdr_master, ao2_cleanup);
1640 SCOPED_AO2LOCK(lock, cand_cdr_master);
1642 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1643 /* Skip any records that are not in a bridge or in this bridge.
1644 * I'm not sure how that would happen, but it pays to be careful. */
1645 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1646 strcmp(cdr->bridge, cand_cdr->bridge)) {
1650 /* If we don't have a Party B (originated channel), skip it */
1651 if (!cdr->party_b.snapshot) {
1655 /* Skip any records that aren't our Party B */
1656 if (strcasecmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name)) {
1659 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1660 /* If they have a Party B, they joined up with someone else as their
1661 * Party A. Don't finalize them as they're active. Otherwise, we
1662 * have stolen them so they need to be finalized.
1664 if (!cand_cdr->party_b.snapshot) {
1665 cdr_object_finalize(cand_cdr);
1671 ao2_iterator_destroy(it_cdrs);
1673 /* We always transition state, even if we didn't get a peer */
1674 cdr_object_transition_state(cdr, &bridge_state_fn_table);
1676 /* Success implies that we have a Party B */
1678 return BRIDGE_ENTER_OBTAINED_PARTY_B;
1680 return BRIDGE_ENTER_NO_PARTY_B;
1683 /* DIALED PENDING STATE */
1685 static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1687 /* If we get a CEP change, we're executing dialplan. If we have a Party B
1688 * that means we need a new CDR; otherwise, switch us over to single.
1690 if (snapshot_cep_changed(cdr->party_a.snapshot, snapshot)) {
1691 if (cdr->party_b.snapshot) {
1692 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1693 cdr->fn_table->process_party_a(cdr, snapshot);
1696 cdr_object_transition_state(cdr, &single_state_fn_table);
1697 cdr->fn_table->process_party_a(cdr, snapshot);
1701 base_process_party_a(cdr, snapshot);
1705 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)
1707 cdr_object_transition_state(cdr, &dial_state_fn_table);
1708 return cdr->fn_table->process_bridge_enter(cdr, bridge, channel);
1711 static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1713 /* We can't handle this as we have a Party B - ask for a new one */
1717 static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1719 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1721 /* Ask for a new CDR */
1727 static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1729 if (!cdr->party_b.snapshot
1730 || strcasecmp(cdr->party_b.snapshot->name, snapshot->name)) {
1733 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1735 /* If party B hangs up, finalize this CDR */
1736 if (ast_test_flag(&cdr->party_b.snapshot->flags, AST_FLAG_DEAD)) {
1737 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1741 static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1743 if (strcmp(cdr->bridge, bridge->uniqueid)) {
1746 if (strcasecmp(cdr->party_a.snapshot->name, channel->name)
1747 && cdr->party_b.snapshot
1748 && strcasecmp(cdr->party_b.snapshot->name, channel->name)) {
1751 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1758 static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1760 if (strcasecmp(cdr->party_a.snapshot->name, channel->name)) {
1763 cdr_object_transition_state(cdr, &finalized_state_fn_table);
1768 /* FINALIZED STATE */
1770 static void finalized_state_init_function(struct cdr_object *cdr)
1772 cdr_object_finalize(cdr);
1775 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1777 RAII_VAR(struct module_config *, mod_cfg,
1778 ao2_global_obj_ref(module_configs), ao2_cleanup);
1780 /* If we ignore hangup logic, indicate that we don't need a new CDR */
1781 if (ast_test_flag(&mod_cfg->general->settings, CDR_END_BEFORE_H_EXTEN)
1782 && ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
1786 /* Indicate that, if possible, we should get a new CDR */
1790 /* TOPIC ROUTER CALLBACKS */
1793 * \brief Handler for Stasis-Core dial messages
1794 * \param data Passed on
1795 * \param sub The stasis subscription for this message callback
1796 * \param topic The topic this message was published for
1797 * \param message The message
1799 static void handle_dial_message(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
1801 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1802 struct cdr_object *cdr;
1803 struct ast_multi_channel_blob *payload = stasis_message_data(message);
1804 struct ast_channel_snapshot *caller;
1805 struct ast_channel_snapshot *peer;
1806 struct cdr_object *it_cdr;
1807 struct ast_json *dial_status_blob;
1808 const char *dial_status = NULL;
1811 caller = ast_multi_channel_blob_get_channel(payload, "caller");
1812 peer = ast_multi_channel_blob_get_channel(payload, "peer");
1813 if (!peer && !caller) {
1816 dial_status_blob = ast_json_object_get(ast_multi_channel_blob_get_json(payload), "dialstatus");
1817 if (dial_status_blob) {
1818 dial_status = ast_json_string_get(dial_status_blob);
1821 CDR_DEBUG(mod_cfg, "Dial %s message for %s, %s: %u.%08u\n",
1822 ast_strlen_zero(dial_status) ? "Begin" : "End",
1823 caller ? caller->name : "(none)",
1824 peer ? peer->name : "(none)",
1825 (unsigned int)stasis_message_timestamp(message)->tv_sec,
1826 (unsigned int)stasis_message_timestamp(message)->tv_usec);
1828 /* Figure out who is running this show */
1830 cdr = ao2_find(active_cdrs_by_channel, caller->name, OBJ_KEY);
1832 cdr = ao2_find(active_cdrs_by_channel, peer->name, OBJ_KEY);
1836 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->name : peer->name);
1841 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1842 if (ast_strlen_zero(dial_status)) {
1843 if (!it_cdr->fn_table->process_dial_begin) {
1846 CDR_DEBUG(mod_cfg, "%p - Processing Dial Begin message for channel %s, peer %s\n",
1848 caller ? caller->name : "(none)",
1849 peer ? peer->name : "(none)");
1850 res &= it_cdr->fn_table->process_dial_begin(it_cdr,
1854 if (!it_cdr->fn_table->process_dial_end) {
1857 CDR_DEBUG(mod_cfg, "%p - Processing Dial End message for channel %s, peer %s\n",
1859 caller ? caller->name : "(none)",
1860 peer ? peer->name : "(none)");
1861 it_cdr->fn_table->process_dial_end(it_cdr,
1868 /* If no CDR handled a dial begin message, make a new one */
1869 if (res && ast_strlen_zero(dial_status)) {
1870 struct cdr_object *new_cdr;
1872 new_cdr = cdr_object_create_and_append(cdr);
1876 new_cdr->fn_table->process_dial_begin(new_cdr,
1883 static int cdr_object_finalize_party_b(void *obj, void *arg, int flags)
1885 struct cdr_object *cdr = obj;
1886 struct ast_channel_snapshot *party_b = arg;
1887 struct cdr_object *it_cdr;
1888 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1889 if (it_cdr->party_b.snapshot
1890 && !strcasecmp(it_cdr->party_b.snapshot->name, party_b->name)) {
1891 /* Don't transition to the finalized state - let the Party A do
1892 * that when its ready
1894 cdr_object_finalize(it_cdr);
1900 static int cdr_object_update_party_b(void *obj, void *arg, int flags)
1902 struct cdr_object *cdr = obj;
1903 struct ast_channel_snapshot *party_b = arg;
1904 struct cdr_object *it_cdr;
1905 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1906 if (!it_cdr->fn_table->process_party_b) {
1909 if (it_cdr->party_b.snapshot
1910 && !strcasecmp(it_cdr->party_b.snapshot->name, party_b->name)) {
1911 it_cdr->fn_table->process_party_b(it_cdr, party_b);
1919 * \brief Filter channel snapshots by technology
1921 static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
1923 return snapshot->tech_properties & AST_CHAN_TP_INTERNAL;
1928 * \brief Filter a channel cache update
1930 static int filter_channel_cache_message(struct ast_channel_snapshot *old_snapshot,
1931 struct ast_channel_snapshot *new_snapshot)
1935 /* Drop cache updates from certain channel technologies */
1937 ret |= filter_channel_snapshot(old_snapshot);
1940 ret |= filter_channel_snapshot(new_snapshot);
1946 /*! \brief Determine if we need to add a new CDR based on snapshots */
1947 static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot,
1948 struct ast_channel_snapshot *new_snapshot)
1950 RAII_VAR(struct module_config *, mod_cfg,
1951 ao2_global_obj_ref(module_configs), ao2_cleanup);
1953 if (!new_snapshot) {
1957 if (ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD)) {
1961 /* Auto-fall through will increment the priority but have no application */
1962 if (ast_strlen_zero(new_snapshot->appl)) {
1966 if (old_snapshot && !snapshot_cep_changed(old_snapshot, new_snapshot)) {
1974 * \brief Handler for Stasis-Core channel cache update messages
1975 * \param data Passed on
1976 * \param sub The stasis subscription for this message callback
1977 * \param topic The topic this message was published for
1978 * \param message The message
1980 static void handle_channel_cache_message(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message)
1982 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
1983 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
1984 struct stasis_cache_update *update = stasis_message_data(message);
1985 struct ast_channel_snapshot *old_snapshot;
1986 struct ast_channel_snapshot *new_snapshot;
1988 struct cdr_object *it_cdr;
1990 ast_assert(update != NULL);
1991 ast_assert(ast_channel_snapshot_type() == update->type);
1993 old_snapshot = stasis_message_data(update->old_snapshot);
1994 new_snapshot = stasis_message_data(update->new_snapshot);
1995 name = new_snapshot ? new_snapshot->name : old_snapshot->name;
1997 if (filter_channel_cache_message(old_snapshot, new_snapshot)) {
2001 CDR_DEBUG(mod_cfg, "Channel Update message for %s: %u.%08u\n",
2003 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2004 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2006 if (new_snapshot && !old_snapshot) {
2007 cdr = cdr_object_alloc(new_snapshot);
2011 ao2_link(active_cdrs_by_channel, cdr);
2014 /* Handle Party A */
2016 cdr = ao2_find(active_cdrs_by_channel, name, OBJ_KEY);
2019 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", name);
2024 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2025 if (!it_cdr->fn_table->process_party_a) {
2028 CDR_DEBUG(mod_cfg, "%p - Processing new channel snapshot %s\n", it_cdr, new_snapshot->name);
2029 all_reject &= it_cdr->fn_table->process_party_a(it_cdr, new_snapshot);
2031 if (all_reject && check_new_cdr_needed(old_snapshot, new_snapshot)) {
2032 /* We're not hung up and we have a new snapshot - we need a new CDR */
2033 struct cdr_object *new_cdr;
2034 new_cdr = cdr_object_create_and_append(cdr);
2036 new_cdr->fn_table->process_party_a(new_cdr, new_snapshot);
2040 CDR_DEBUG(mod_cfg, "%p - Beginning finalize/dispatch for %s\n", cdr, old_snapshot->name);
2041 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2042 cdr_object_finalize(it_cdr);
2044 cdr_object_dispatch(cdr);
2045 ao2_unlink(active_cdrs_by_channel, cdr);
2050 /* Handle Party B */
2052 ao2_callback(active_cdrs_by_channel, OBJ_NODATA, cdr_object_update_party_b,
2055 ao2_callback(active_cdrs_by_channel, OBJ_NODATA, cdr_object_finalize_party_b,
2061 struct bridge_leave_data {
2062 struct ast_bridge_snapshot *bridge;
2063 struct ast_channel_snapshot *channel;
2066 /*! \brief Callback used to notify CDRs of a Party B leaving the bridge */
2067 static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, int flags)
2069 struct cdr_object *cdr = obj;
2070 struct bridge_leave_data *leave_data = arg;
2071 struct cdr_object *it_cdr;
2073 if (strcmp(cdr->bridge, leave_data->bridge->uniqueid)) {
2076 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2077 if (it_cdr->fn_table != &bridge_state_fn_table) {
2080 if (!it_cdr->party_b.snapshot) {
2083 if (strcasecmp(it_cdr->party_b.snapshot->name, leave_data->channel->name)) {
2086 /* It is our Party B, in our bridge. Set the end time and let the handler
2087 * transition our CDR appropriately when we leave the bridge.
2089 cdr_object_finalize(it_cdr);
2094 /*! \brief Filter bridge messages based on bridge technology */
2095 static int filter_bridge_messages(struct ast_bridge_snapshot *bridge)
2097 /* Ignore holding bridge technology messages. We treat this simply as an application
2098 * that a channel enters into.
2100 if (!strcmp(bridge->technology, "holding_bridge") && strcmp(bridge->subclass, "parking")) {
2107 * \brief Handler for when a channel leaves a bridge
2108 * \param data Passed on
2109 * \param sub The stasis subscription for this message callback
2110 * \param topic The topic this message was published for
2111 * \param message The message - hopefully a bridge one!
2113 static void handle_bridge_leave_message(void *data, struct stasis_subscription *sub,
2114 struct stasis_topic *topic, struct stasis_message *message)
2116 struct ast_bridge_blob *update = stasis_message_data(message);
2117 struct ast_bridge_snapshot *bridge = update->bridge;
2118 struct ast_channel_snapshot *channel = update->channel;
2119 RAII_VAR(struct module_config *, mod_cfg,
2120 ao2_global_obj_ref(module_configs), ao2_cleanup);
2121 RAII_VAR(struct cdr_object *, cdr,
2122 ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY),
2124 struct cdr_object *it_cdr;
2125 struct bridge_leave_data leave_data = {
2129 int left_bridge = 0;
2131 if (filter_bridge_messages(bridge)) {
2135 CDR_DEBUG(mod_cfg, "Bridge Leave message for %s: %u.%08u\n",
2137 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2138 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2141 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2147 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2148 if (!it_cdr->fn_table->process_bridge_leave) {
2151 CDR_DEBUG(mod_cfg, "%p - Processing Bridge Leave for %s\n",
2152 it_cdr, channel->name);
2153 if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
2154 ast_string_field_set(it_cdr, bridge, "");
2164 if (strcmp(bridge->subclass, "parking")) {
2166 ao2_callback(active_cdrs_by_channel, OBJ_NODATA,
2167 cdr_object_party_b_left_bridge_cb,
2172 struct bridge_candidate {
2173 struct cdr_object *cdr; /*!< The actual CDR this candidate belongs to, either as A or B */
2174 struct cdr_object_snapshot candidate; /*!< The candidate for a new pairing */
2178 * \brief Comparison function for \ref bridge_candidate objects
2180 static int bridge_candidate_cmp_fn(void *obj, void *arg, int flags)
2182 struct bridge_candidate *left = obj;
2183 struct bridge_candidate *right = arg;
2184 const char *match = (flags & OBJ_KEY) ? arg : right->candidate.snapshot->name;
2185 return strcasecmp(left->candidate.snapshot->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
2189 * \brief Hash function for \ref bridge_candidate objects
2191 static int bridge_candidate_hash_fn(const void *obj, const int flags)
2193 const struct bridge_candidate *bc = obj;
2194 const char *id = (flags & OBJ_KEY) ? obj : bc->candidate.snapshot->name;
2195 return ast_str_case_hash(id);
2198 /*! \brief \ref bridge_candidate Destructor */
2199 static void bridge_candidate_dtor(void *obj)
2201 struct bridge_candidate *bcand = obj;
2202 ao2_cleanup(bcand->cdr);
2203 ao2_cleanup(bcand->candidate.snapshot);
2204 free_variables(&bcand->candidate.variables);
2208 * \brief \ref bridge_candidate Constructor
2209 * \param cdr The \ref cdr_object that is a candidate for being compared to in
2210 * a bridge operation
2211 * \param candidate The \ref cdr_object_snapshot candidate snapshot in the CDR
2212 * that should be used during the operaton
2214 static struct bridge_candidate *bridge_candidate_alloc(struct cdr_object *cdr, struct cdr_object_snapshot *candidate)
2216 struct bridge_candidate *bcand;
2218 bcand = ao2_alloc(sizeof(*bcand), bridge_candidate_dtor);
2223 ao2_ref(bcand->cdr, +1);
2224 bcand->candidate.flags = candidate->flags;
2225 strcpy(bcand->candidate.userfield, candidate->userfield);
2226 bcand->candidate.snapshot = candidate->snapshot;
2227 ao2_ref(bcand->candidate.snapshot, +1);
2228 copy_variables(&bcand->candidate.variables, &candidate->variables);
2235 * \brief Build and add bridge candidates based on a CDR
2237 * \param bridge_id The ID of the bridge we need candidates for
2238 * \param candidates The container of \ref bridge_candidate objects
2239 * \param cdr The \ref cdr_object that is our candidate
2240 * \param party_a Non-zero if we should look at the Party A channel; 0 if Party B
2242 static void add_candidate_for_bridge(const char *bridge_id,
2243 struct ao2_container *candidates,
2244 struct cdr_object *cdr,
2247 struct cdr_object *it_cdr;
2249 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2250 struct cdr_object_snapshot *party_snapshot;
2251 RAII_VAR(struct bridge_candidate *, bcand, NULL, ao2_cleanup);
2253 party_snapshot = party_a ? &it_cdr->party_a : &it_cdr->party_b;
2255 if (it_cdr->fn_table != &bridge_state_fn_table || strcmp(bridge_id, it_cdr->bridge)) {
2259 if (!party_snapshot->snapshot) {
2263 /* Don't add a party twice */
2264 bcand = ao2_find(candidates, party_snapshot->snapshot->name, OBJ_KEY);
2269 bcand = bridge_candidate_alloc(it_cdr, party_snapshot);
2271 ao2_link(candidates, bcand);
2277 * \brief Create new \ref bridge_candidate objects for each party currently
2279 * \param bridge The \param ast_bridge_snapshot for the bridge we're processing
2281 * Note that we use two passes here instead of one so that we only create a
2282 * candidate for a party B if they are never a party A in the bridge. Otherwise,
2283 * we don't care about them.
2285 static struct ao2_container *create_candidates_for_bridge(struct ast_bridge_snapshot *bridge)
2287 struct ao2_container *candidates = ao2_container_alloc(51, bridge_candidate_hash_fn, bridge_candidate_cmp_fn);
2288 char *bridge_id = ast_strdupa(bridge->uniqueid);
2289 struct ao2_iterator *it_cdrs;
2290 struct cdr_object *cand_cdr_master;
2296 /* For each CDR that has a record in the bridge, get their Party A and
2297 * make them a candidate. Note that we do this in two passes as opposed to one so
2298 * that we give preference CDRs where the channel is Party A */
2299 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
2300 cdr_object_bridge_cmp_fn, bridge_id);
2302 /* No one in the bridge yet! */
2303 ao2_cleanup(candidates);
2306 for (; (cand_cdr_master = ao2_iterator_next(it_cdrs)); ao2_cleanup(cand_cdr_master)) {
2307 SCOPED_AO2LOCK(lock, cand_cdr_master);
2308 add_candidate_for_bridge(bridge->uniqueid, candidates, cand_cdr_master, 1);
2310 ao2_iterator_destroy(it_cdrs);
2311 /* For each CDR that has a record in the bridge, get their Party B and
2312 * make them a candidate. */
2313 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
2314 cdr_object_bridge_cmp_fn, bridge_id);
2316 /* Now it's just an error. */
2317 ao2_cleanup(candidates);
2320 for (; (cand_cdr_master = ao2_iterator_next(it_cdrs)); ao2_cleanup(cand_cdr_master)) {
2321 SCOPED_AO2LOCK(lock, cand_cdr_master);
2322 add_candidate_for_bridge(bridge->uniqueid, candidates, cand_cdr_master, 0);
2324 ao2_iterator_destroy(it_cdrs);
2331 * \brief Create a new CDR, append it to an existing CDR, and update its snapshots
2333 * \note The new CDR will be automatically transitioned to the bridge state
2335 static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
2336 const char *bridge_id,
2337 struct cdr_object_snapshot *party_b)
2339 struct cdr_object *new_cdr;
2341 new_cdr = cdr_object_create_and_append(cdr);
2345 cdr_object_snapshot_copy(&new_cdr->party_b, party_b);
2346 cdr_object_check_party_a_answer(new_cdr);
2347 ast_string_field_set(new_cdr, bridge, cdr->bridge);
2348 cdr_object_transition_state(new_cdr, &bridge_state_fn_table);
2352 * \brief Process a single \ref bridge_candidate. Note that this is called as
2353 * part of an \ref ao2_callback on an \ref ao2_container of \ref bridge_candidate
2354 * objects previously created by \ref create_candidates_for_bridge.
2356 * \param obj The \ref bridge_candidate being processed
2357 * \param arg The \ref cdr_object that is being compared against the candidates
2359 * The purpose of this function is to create the necessary CDR entries as a
2360 * result of \ref cdr_object having entered the same bridge as the CDR
2361 * represented by \ref bridge_candidate.
2363 static int bridge_candidate_process(void *obj, void *arg, int flags)
2365 struct bridge_candidate *bcand = obj;
2366 struct cdr_object *cdr = arg;
2367 struct cdr_object_snapshot *party_a;
2369 /* If the candidate is us or someone we've taken on, pass on by */
2370 if (!strcasecmp(cdr->party_a.snapshot->name, bcand->candidate.snapshot->name)
2371 || (cdr->party_b.snapshot
2372 && !strcasecmp(cdr->party_b.snapshot->name, bcand->candidate.snapshot->name))) {
2375 party_a = cdr_object_pick_party_a(&cdr->party_a, &bcand->candidate);
2376 /* We're party A - make a new CDR, append it to us, and set the candidate as
2378 if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
2379 bridge_candidate_add_to_cdr(cdr, cdr->bridge, &bcand->candidate);
2383 /* We're Party B. Check if the candidate is the CDR's Party A. If so, find out if we
2384 * can add ourselves directly as the Party B, or if we need a new CDR. */
2385 if (!strcasecmp(bcand->cdr->party_a.snapshot->name, bcand->candidate.snapshot->name)) {
2386 if (bcand->cdr->party_b.snapshot
2387 && strcasecmp(bcand->cdr->party_b.snapshot->name, cdr->party_a.snapshot->name)) {
2388 bridge_candidate_add_to_cdr(bcand->cdr, cdr->bridge, &cdr->party_a);
2390 cdr_object_snapshot_copy(&bcand->cdr->party_b, &cdr->party_a);
2391 /* It's possible that this joined at one point and was never chosen
2392 * as party A. Clear their end time, as it would be set in such a
2395 memset(&bcand->cdr->end, 0, sizeof(bcand->cdr->end));
2398 /* We are Party B to a candidate CDR's Party B. Since a candidate
2399 * CDR will only have a Party B represented here if that channel
2400 * was never a Party A in the bridge, we have to go looking for
2401 * that channel's primary CDR record.
2403 struct cdr_object *b_party = ao2_find(active_cdrs_by_channel, bcand->candidate.snapshot->name, OBJ_KEY);
2405 /* Holy cow - no CDR? */
2406 b_party = cdr_object_alloc(bcand->candidate.snapshot);
2407 cdr_object_snapshot_copy(&b_party->party_a, &bcand->candidate);
2408 cdr_object_snapshot_copy(&b_party->party_b, &cdr->party_a);
2409 cdr_object_check_party_a_answer(b_party);
2410 ast_string_field_set(b_party, bridge, cdr->bridge);
2411 cdr_object_transition_state(b_party, &bridge_state_fn_table);
2412 ao2_link(active_cdrs_by_channel, b_party);
2414 bridge_candidate_add_to_cdr(b_party, cdr->bridge, &cdr->party_a);
2416 ao2_ref(b_party, -1);
2423 * \brief Handle creating bridge pairings for the \ref cdr_object that just
2425 * \param cdr The \ref cdr_object that just entered the bridge
2426 * \param bridge The \ref ast_bridge_snapshot representing the bridge it just entered
2428 static void handle_bridge_pairings(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge)
2430 RAII_VAR(struct ao2_container *, candidates,
2431 create_candidates_for_bridge(bridge),
2437 ao2_callback(candidates, OBJ_NODATA,
2438 bridge_candidate_process,
2444 /*! \brief Handle entering into a parking bridge
2445 * \param cdr The CDR to operate on
2446 * \param bridge The bridge the channel just entered
2447 * \param channel The channel snapshot
2449 static void handle_parking_bridge_enter_message(struct cdr_object *cdr,
2450 struct ast_bridge_snapshot *bridge,
2451 struct ast_channel_snapshot *channel)
2453 RAII_VAR(struct module_config *, mod_cfg,
2454 ao2_global_obj_ref(module_configs), ao2_cleanup);
2456 struct cdr_object *it_cdr;
2457 struct cdr_object *new_cdr;
2461 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2462 if (it_cdr->fn_table->process_parking_bridge_enter) {
2463 res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
2465 if (it_cdr->fn_table->process_party_a) {
2466 CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr,
2468 it_cdr->fn_table->process_party_a(it_cdr, channel);
2473 /* No one handled it - we need a new one! */
2474 new_cdr = cdr_object_create_and_append(cdr);
2476 /* Let the single state transition us to Parked */
2477 cdr_object_transition_state(new_cdr, &single_state_fn_table);
2478 new_cdr->fn_table->process_parking_bridge_enter(new_cdr, bridge, channel);
2484 /*! \brief Handle a bridge enter message for a 'normal' bridge
2485 * \param cdr The CDR to operate on
2486 * \param bridge The bridge the channel just entered
2487 * \param channel The channel snapshot
2489 static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
2490 struct ast_bridge_snapshot *bridge,
2491 struct ast_channel_snapshot *channel)
2493 RAII_VAR(struct module_config *, mod_cfg,
2494 ao2_global_obj_ref(module_configs), ao2_cleanup);
2495 enum process_bridge_enter_results result;
2496 struct cdr_object *it_cdr;
2497 struct cdr_object *new_cdr;
2498 struct cdr_object *handled_cdr = NULL;
2502 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2503 if (it_cdr->fn_table->process_party_a) {
2504 CDR_DEBUG(mod_cfg, "%p - Updating Party A %s snapshot\n", it_cdr,
2506 it_cdr->fn_table->process_party_a(it_cdr, channel);
2509 /* Notify all states that they have entered a bridge */
2510 if (it_cdr->fn_table->process_bridge_enter) {
2511 CDR_DEBUG(mod_cfg, "%p - Processing bridge enter for %s\n", it_cdr,
2513 result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
2515 case BRIDGE_ENTER_ONLY_PARTY:
2517 case BRIDGE_ENTER_OBTAINED_PARTY_B:
2519 handled_cdr = it_cdr;
2522 case BRIDGE_ENTER_NEED_CDR:
2525 case BRIDGE_ENTER_NO_PARTY_B:
2526 /* We didn't win on any - end this CDR. If someone else comes in later
2527 * that is Party B to this CDR, it can re-activate this CDR.
2530 handled_cdr = it_cdr;
2532 cdr_object_finalize(cdr);
2538 /* Create the new matchings, but only for either:
2539 * * The first CDR in the chain that handled it. This avoids issues with
2541 * * If no one handled it, the last CDR in the chain. This would occur if
2542 * a CDR joined a bridge and it wasn't Party A for anyone. We still need
2543 * to make pairings with everyone in the bridge.
2546 handle_bridge_pairings(handled_cdr, bridge);
2548 /* Nothing handled it - we need a new one! */
2549 new_cdr = cdr_object_create_and_append(cdr);
2551 /* This is guaranteed to succeed: the new CDR is created in the single state
2552 * and will be able to handle the bridge enter message
2554 handle_standard_bridge_enter_message(cdr, bridge, channel);
2561 * \brief Handler for Stasis-Core bridge enter messages
2562 * \param data Passed on
2563 * \param sub The stasis subscription for this message callback
2564 * \param topic The topic this message was published for
2565 * \param message The message - hopefully a bridge one!
2567 static void handle_bridge_enter_message(void *data, struct stasis_subscription *sub,
2568 struct stasis_topic *topic, struct stasis_message *message)
2570 struct ast_bridge_blob *update = stasis_message_data(message);
2571 struct ast_bridge_snapshot *bridge = update->bridge;
2572 struct ast_channel_snapshot *channel = update->channel;
2573 RAII_VAR(struct cdr_object *, cdr,
2574 ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY),
2576 RAII_VAR(struct module_config *, mod_cfg,
2577 ao2_global_obj_ref(module_configs), ao2_cleanup);
2579 if (filter_bridge_messages(bridge)) {
2583 CDR_DEBUG(mod_cfg, "Bridge Enter message for channel %s: %u.%08u\n",
2585 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2586 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2589 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2593 if (!strcmp(bridge->subclass, "parking")) {
2594 handle_parking_bridge_enter_message(cdr, bridge, channel);
2596 handle_standard_bridge_enter_message(cdr, bridge, channel);
2601 * \brief Handler for when a channel is parked
2602 * \param data Passed on
2603 * \param sub The stasis subscription for this message callback
2604 * \param topic The topic this message was published for
2605 * \param message The message about who got parked
2607 static void handle_parked_call_message(void *data, struct stasis_subscription *sub,
2608 struct stasis_topic *topic, struct stasis_message *message)
2610 struct ast_parked_call_payload *payload = stasis_message_data(message);
2611 struct ast_channel_snapshot *channel = payload->parkee;
2612 RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
2613 RAII_VAR(struct module_config *, mod_cfg,
2614 ao2_global_obj_ref(module_configs), ao2_cleanup);
2615 struct cdr_object *it_cdr;
2617 /* Anything other than getting parked will be handled by other updates */
2618 if (payload->event_type != PARKED_CALL) {
2622 /* No one got parked? */
2627 CDR_DEBUG(mod_cfg, "Parked Call message for channel %s: %u.%08u\n",
2629 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2630 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2632 cdr = ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY);
2634 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
2640 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2641 if (it_cdr->fn_table->process_parked_channel) {
2642 it_cdr->fn_table->process_parked_channel(it_cdr, payload);
2650 struct ast_cdr_config *ast_cdr_get_config(void)
2652 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2653 ao2_ref(mod_cfg->general, +1);
2654 return mod_cfg->general;
2657 void ast_cdr_set_config(struct ast_cdr_config *config)
2659 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2660 ao2_cleanup(mod_cfg->general);
2661 mod_cfg->general = config;
2662 ao2_ref(mod_cfg->general, +1);
2665 int ast_cdr_is_enabled(void)
2667 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
2668 return ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED);
2671 int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
2673 struct cdr_beitem *i = NULL;
2679 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
2683 AST_RWLIST_WRLOCK(&be_list);
2684 AST_RWLIST_TRAVERSE(&be_list, i, list) {
2685 if (!strcasecmp(name, i->name)) {
2686 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
2687 AST_RWLIST_UNLOCK(&be_list);
2692 if (!(i = ast_calloc(1, sizeof(*i))))
2696 ast_copy_string(i->name, name, sizeof(i->name));
2697 ast_copy_string(i->desc, desc, sizeof(i->desc));
2699 AST_RWLIST_INSERT_HEAD(&be_list, i, list);
2700 AST_RWLIST_UNLOCK(&be_list);
2705 void ast_cdr_unregister(const char *name)
2707 struct cdr_beitem *i = NULL;
2709 AST_RWLIST_WRLOCK(&be_list);
2710 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) {
2711 if (!strcasecmp(name, i->name)) {
2712 AST_RWLIST_REMOVE_CURRENT(list);
2716 AST_RWLIST_TRAVERSE_SAFE_END;
2717 AST_RWLIST_UNLOCK(&be_list);
2720 ast_verb(2, "Unregistered '%s' CDR backend\n", name);
2725 struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
2727 struct ast_cdr *newcdr;
2732 newcdr = ast_cdr_alloc();
2738 AST_LIST_HEAD_INIT_NOLOCK(&newcdr->varshead);
2739 copy_variables(&newcdr->varshead, &cdr->varshead);
2740 newcdr->next = NULL;
2745 static const char *cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
2747 struct ast_var_t *variables;
2749 if (ast_strlen_zero(name)) {
2753 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
2754 if (!strcasecmp(name, ast_var_name(variables))) {
2755 return ast_var_value(variables);
2762 static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
2764 if (fmt == NULL) { /* raw mode */
2765 snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec);
2770 ast_localtime(&when, &tm, NULL);
2771 ast_strftime(buf, bufsize, fmt, &tm);
2776 void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
2778 const char *fmt = "%Y-%m-%d %T";
2787 if (!strcasecmp(name, "clid")) {
2788 ast_copy_string(workspace, cdr->clid, workspacelen);
2789 } else if (!strcasecmp(name, "src")) {
2790 ast_copy_string(workspace, cdr->src, workspacelen);
2791 } else if (!strcasecmp(name, "dst")) {
2792 ast_copy_string(workspace, cdr->dst, workspacelen);
2793 } else if (!strcasecmp(name, "dcontext")) {
2794 ast_copy_string(workspace, cdr->dcontext, workspacelen);
2795 } else if (!strcasecmp(name, "channel")) {
2796 ast_copy_string(workspace, cdr->channel, workspacelen);
2797 } else if (!strcasecmp(name, "dstchannel")) {
2798 ast_copy_string(workspace, cdr->dstchannel, workspacelen);
2799 } else if (!strcasecmp(name, "lastapp")) {
2800 ast_copy_string(workspace, cdr->lastapp, workspacelen);
2801 } else if (!strcasecmp(name, "lastdata")) {
2802 ast_copy_string(workspace, cdr->lastdata, workspacelen);
2803 } else if (!strcasecmp(name, "start")) {
2804 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
2805 } else if (!strcasecmp(name, "answer")) {
2806 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
2807 } else if (!strcasecmp(name, "end")) {
2808 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
2809 } else if (!strcasecmp(name, "duration")) {
2810 snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
2811 } else if (!strcasecmp(name, "billsec")) {
2812 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);
2813 } else if (!strcasecmp(name, "disposition")) {
2815 snprintf(workspace, workspacelen, "%ld", cdr->disposition);
2817 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
2819 } else if (!strcasecmp(name, "amaflags")) {
2821 snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
2823 ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
2825 } else if (!strcasecmp(name, "accountcode")) {
2826 ast_copy_string(workspace, cdr->accountcode, workspacelen);
2827 } else if (!strcasecmp(name, "peeraccount")) {
2828 ast_copy_string(workspace, cdr->peeraccount, workspacelen);
2829 } else if (!strcasecmp(name, "uniqueid")) {
2830 ast_copy_string(workspace, cdr->uniqueid, workspacelen);
2831 } else if (!strcasecmp(name, "linkedid")) {
2832 ast_copy_string(workspace, cdr->linkedid, workspacelen);
2833 } else if (!strcasecmp(name, "userfield")) {
2834 ast_copy_string(workspace, cdr->userfield, workspacelen);
2835 } else if (!strcasecmp(name, "sequence")) {
2836 snprintf(workspace, workspacelen, "%d", cdr->sequence);
2837 } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
2838 ast_copy_string(workspace, varbuf, workspacelen);
2840 workspace[0] = '\0';
2843 if (!ast_strlen_zero(workspace)) {
2850 * \brief Callback that finds all CDRs that reference a particular channel
2852 static int cdr_object_select_all_by_channel_cb(void *obj, void *arg, int flags)
2854 struct cdr_object *cdr = obj;
2855 const char *name = arg;
2857 if (!strcasecmp(cdr->party_a.snapshot->name, name) ||
2858 (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->name, name))) {
2864 /* Read Only CDR variables */
2865 static const char * const cdr_readonly_vars[] = { "clid", "src", "dst", "dcontext",
2866 "channel", "dstchannel", "lastapp", "lastdata", "start", "answer", "end", "duration",
2867 "billsec", "disposition", "amaflags", "accountcode", "uniqueid", "linkedid",
2868 "userfield", "sequence", "total_duration", "total_billsec", "first_start",
2869 "first_answer", NULL };
2871 int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
2873 struct cdr_object *cdr;
2874 struct cdr_object *it_cdr;
2875 struct ao2_iterator *it_cdrs;
2876 char *arg = ast_strdupa(channel_name);
2879 for (x = 0; cdr_readonly_vars[x]; x++) {
2880 if (!strcasecmp(name, cdr_readonly_vars[x])) {
2881 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
2886 it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE, cdr_object_select_all_by_channel_cb, arg);
2888 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
2892 for (; (cdr = ao2_iterator_next(it_cdrs)); ao2_unlock(cdr), ao2_cleanup(cdr)) {
2894 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2895 struct varshead *headp = NULL;
2897 if (it_cdr->fn_table == &finalized_state_fn_table) {
2900 if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->name)) {
2901 headp = &it_cdr->party_a.variables;
2902 } else if (it_cdr->party_b.snapshot
2903 && !strcasecmp(channel_name, it_cdr->party_b.snapshot->name)) {
2904 headp = &it_cdr->party_b.variables;
2907 set_variable(headp, name, value);
2911 ao2_iterator_destroy(it_cdrs);
2917 * \brief Format a variable on a \ref cdr_object
2919 static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
2921 struct ast_var_t *variable;
2923 AST_LIST_TRAVERSE(&cdr->party_a.variables, variable, entries) {
2924 if (!strcasecmp(name, ast_var_name(variable))) {
2925 ast_copy_string(value, ast_var_value(variable), length);
2934 * \brief Format one of the standard properties on a \ref cdr_object
2936 static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
2938 struct ast_channel_snapshot *party_a = cdr_obj->party_a.snapshot;
2939 struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;
2941 if (!strcasecmp(name, "clid")) {
2942 ast_callerid_merge(value, length, party_a->caller_name, party_a->caller_number, "");
2943 } else if (!strcasecmp(name, "src")) {
2944 ast_copy_string(value, party_a->caller_number, length);
2945 } else if (!strcasecmp(name, "dst")) {
2946 ast_copy_string(value, party_a->exten, length);
2947 } else if (!strcasecmp(name, "dcontext")) {
2948 ast_copy_string(value, party_a->context, length);
2949 } else if (!strcasecmp(name, "channel")) {
2950 ast_copy_string(value, party_a->name, length);
2951 } else if (!strcasecmp(name, "dstchannel")) {
2953 ast_copy_string(value, party_b->name, length);
2955 ast_copy_string(value, "", length);
2957 } else if (!strcasecmp(name, "lastapp")) {
2958 ast_copy_string(value, party_a->appl, length);
2959 } else if (!strcasecmp(name, "lastdata")) {
2960 ast_copy_string(value, party_a->data, length);
2961 } else if (!strcasecmp(name, "start")) {
2962 cdr_get_tv(cdr_obj->start, NULL, value, length);
2963 } else if (!strcasecmp(name, "answer")) {
2964 cdr_get_tv(cdr_obj->answer, NULL, value, length);
2965 } else if (!strcasecmp(name, "end")) {
2966 cdr_get_tv(cdr_obj->end, NULL, value, length);
2967 } else if (!strcasecmp(name, "duration")) {
2968 snprintf(value, length, "%ld", cdr_object_get_duration(cdr_obj));
2969 } else if (!strcasecmp(name, "billsec")) {
2970 snprintf(value, length, "%ld", cdr_object_get_billsec(cdr_obj));
2971 } else if (!strcasecmp(name, "disposition")) {
2972 snprintf(value, length, "%d", cdr_obj->disposition);
2973 } else if (!strcasecmp(name, "amaflags")) {
2974 snprintf(value, length, "%d", party_a->amaflags);
2975 } else if (!strcasecmp(name, "accountcode")) {
2976 ast_copy_string(value, party_a->accountcode, length);
2977 } else if (!strcasecmp(name, "peeraccount")) {
2979 ast_copy_string(value, party_b->accountcode, length);
2981 ast_copy_string(value, "", length);
2983 } else if (!strcasecmp(name, "uniqueid")) {
2984 ast_copy_string(value, party_a->uniqueid, length);
2985 } else if (!strcasecmp(name, "linkedid")) {
2986 ast_copy_string(value, cdr_obj->linkedid, length);
2987 } else if (!strcasecmp(name, "userfield")) {
2988 ast_copy_string(value, cdr_obj->party_a.userfield, length);
2989 } else if (!strcasecmp(name, "sequence")) {
2990 snprintf(value, length, "%d", cdr_obj->sequence);
2998 int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
3000 RAII_VAR(struct cdr_object *, cdr,
3001 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3003 struct cdr_object *cdr_obj;
3006 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3010 if (ast_strlen_zero(name)) {
3016 cdr_obj = cdr->last;
3017 if (cdr_object_format_property(cdr_obj, name, value, length)) {
3018 /* Property failed; attempt variable */
3019 cdr_object_format_var_internal(cdr_obj, name, value, length);
3027 int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
3029 RAII_VAR(struct cdr_object *, cdr,
3030 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3032 struct cdr_object *it_cdr;
3033 struct ast_var_t *variable;
3035 RAII_VAR(char *, workspace, ast_malloc(256), ast_free);
3036 int total = 0, x = 0, i;
3043 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3047 ast_str_reset(*buf);
3050 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3052 ast_str_append(buf, 0, "\n");
3054 AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
3055 if (!(var = ast_var_name(variable))) {
3059 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
3060 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3067 for (i = 0; cdr_readonly_vars[i]; i++) {
3068 /* null out the workspace, because the cdr_get_tv() won't write anything if time is NULL, so you get old vals */
3070 cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace));
3072 if (!ast_strlen_zero(workspace)
3073 && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
3074 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3084 void ast_cdr_free(struct ast_cdr *cdr)
3087 struct ast_cdr *next = cdr->next;
3089 free_variables(&cdr->varshead);
3095 struct ast_cdr *ast_cdr_alloc(void)
3099 x = ast_calloc(1, sizeof(*x));
3103 const char *ast_cdr_disp2str(int disposition)
3105 switch (disposition) {
3107 return "NO ANSWER"; /* by default, for backward compatibility */
3108 case AST_CDR_NOANSWER:
3110 case AST_CDR_FAILED:
3114 case AST_CDR_ANSWERED:
3116 case AST_CDR_CONGESTION:
3117 return "CONGESTION";
3122 struct party_b_userfield_update {
3123 const char *channel_name;
3124 const char *userfield;
3127 /*! \brief Callback used to update the userfield on Party B on all CDRs */
3128 static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, int flags)
3130 struct cdr_object *cdr = obj;
3131 struct party_b_userfield_update *info = arg;
3132 struct cdr_object *it_cdr;
3133 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3134 if (it_cdr->fn_table == &finalized_state_fn_table) {
3137 if (it_cdr->party_b.snapshot
3138 && !strcasecmp(it_cdr->party_b.snapshot->name, info->channel_name)) {
3139 strcpy(it_cdr->party_b.userfield, info->userfield);
3145 void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
3147 RAII_VAR(struct cdr_object *, cdr,
3148 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3150 struct party_b_userfield_update party_b_info = {
3151 .channel_name = channel_name,
3152 .userfield = userfield,
3154 struct cdr_object *it_cdr;
3156 /* Handle Party A */
3159 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3160 if (it_cdr->fn_table == &finalized_state_fn_table) {
3163 strcpy(it_cdr->party_a.userfield, userfield);
3168 /* Handle Party B */
3169 ao2_callback(active_cdrs_by_channel, OBJ_NODATA,
3170 cdr_object_update_party_b_userfield_cb,
3175 static void post_cdr(struct ast_cdr *cdr)
3177 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3178 struct cdr_beitem *i;
3180 for (; cdr ; cdr = cdr->next) {
3181 /* For people, who don't want to see unanswered single-channel events */
3182 if (!ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) &&
3183 cdr->disposition < AST_CDR_ANSWERED &&
3184 (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) {
3185 ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel);
3189 if (ast_test_flag(cdr, AST_CDR_FLAG_DISABLE)) {
3192 AST_RWLIST_RDLOCK(&be_list);
3193 AST_RWLIST_TRAVERSE(&be_list, i, list) {
3196 AST_RWLIST_UNLOCK(&be_list);
3200 int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
3202 RAII_VAR(struct cdr_object *, cdr,
3203 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3205 struct cdr_object *it_cdr;
3212 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3213 if (it_cdr->fn_table == &finalized_state_fn_table) {
3216 /* Note: in general, set the flags on both the CDR record as well as the
3217 * Party A. Sometimes all we have is the Party A to look at.
3219 ast_set_flag(&it_cdr->flags, option);
3220 ast_set_flag(&it_cdr->party_a, option);
3227 int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
3229 RAII_VAR(struct cdr_object *, cdr,
3230 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3232 struct cdr_object *it_cdr;
3239 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3240 if (it_cdr->fn_table == &finalized_state_fn_table) {
3243 ast_clear_flag(&it_cdr->flags, option);
3250 int ast_cdr_reset(const char *channel_name, struct ast_flags *options)
3252 RAII_VAR(struct cdr_object *, cdr,
3253 ao2_find(active_cdrs_by_channel, channel_name, OBJ_KEY),
3255 struct ast_var_t *vardata;
3256 struct cdr_object *it_cdr;
3263 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3264 /* clear variables */
3265 if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3266 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
3267 ast_var_delete(vardata);
3269 if (cdr->party_b.snapshot) {
3270 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
3271 ast_var_delete(vardata);