Asterisk - The Open Source Telephony Project GIT-master-3dae2cf
cdr.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2006, Digium, Inc.
5 *
6 * Mark Spencer <markster@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Call Detail Record API
22 *
23 * \author Mark Spencer <markster@digium.com>
24 *
25 * \note Includes code and algorithms from the Zapata library.
26 *
27 * \note We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip
28 * through our fingers somehow. If someone allocates a CDR, it must be completely handled normally
29 * or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR
30 * isn't properly generated and posted.
31 */
32
33/*! \li \ref cdr.c uses the configuration file \ref cdr.conf
34 * \addtogroup configuration_file Configuration Files
35 */
36
37/*!
38 * \page cdr.conf cdr.conf
39 * \verbinclude cdr.conf.sample
40 */
41
42/*** MODULEINFO
43 <support_level>core</support_level>
44 ***/
45
46#include "asterisk.h"
47
48#include <signal.h>
49#include <inttypes.h>
50
51#include "asterisk/lock.h"
52#include "asterisk/channel.h"
53#include "asterisk/cdr.h"
54#include "asterisk/callerid.h"
55#include "asterisk/manager.h"
56#include "asterisk/module.h"
57#include "asterisk/causes.h"
59#include "asterisk/utils.h"
60#include "asterisk/sched.h"
61#include "asterisk/config.h"
62#include "asterisk/cli.h"
65#include "asterisk/json.h"
66#include "asterisk/parking.h"
67#include "asterisk/stasis.h"
71#include "asterisk/astobj2.h"
73
74/*** DOCUMENTATION
75 <configInfo name="cdr" language="en_US">
76 <synopsis>Call Detail Record configuration</synopsis>
77 <description>
78 <para>CDR is Call Detail Record, which provides logging services via a variety of
79 pluggable backend modules. Detailed call information can be recorded to
80 databases, files, etc. Useful for billing, fraud prevention, compliance with
81 Sarbanes-Oxley aka The Enron Act, QOS evaluations, and more.</para>
82 </description>
83 <configFile name="cdr.conf">
84 <configObject name="general">
85 <synopsis>Global settings applied to the CDR engine.</synopsis>
86 <configOption name="debug">
87 <synopsis>Enable/disable verbose CDR debugging.</synopsis>
88 <description><para>When set to <literal>True</literal>, verbose updates
89 of changes in CDR information will be logged. Note that this is only
90 of use when debugging CDR behavior.</para>
91 </description>
92 </configOption>
93 <configOption name="enable" default="yes">
94 <synopsis>Enable/disable CDR logging.</synopsis>
95 <description><para>Define whether or not to use CDR logging. Setting this to "no" will override
96 any loading of backend CDR modules.</para>
97 </description>
98 </configOption>
99 <configOption name="channeldefaultenabled" default="yes">
100 <synopsis>Whether CDR is enabled on a channel by default</synopsis>
101 <description><para>Define whether or not CDR should be enabled on a channel by default.
102 Setting this to "yes" will enable CDR on every channel unless it is explicitly disabled.
103 Setting this to "no" will disable CDR on every channel unless it is explicitly enabled.
104 </para>
105 <para>Note that CDR must still be globally enabled (<literal>enable = yes</literal>) for this
106 option to have any effect. This only applies to whether CDR is enabled or disabled on
107 newly created channels, which can be changed in the dialplan during a call.</para>
108 <para>If this is set to "yes", you should use <literal>Set(CDR_PROP(disable)=1)</literal>
109 to disable CDR for a call.</para>
110 <para>If this is set to "no", you should use <literal>Set(CDR_PROP(disable)=0)</literal>
111 to undisable (enable) CDR for a call.</para>
112 </description>
113 </configOption>
114 <configOption name="ignorestatechanges" default="no">
115 <synopsis>Whether CDR is updated or forked by bridging changes.</synopsis>
116 <description><para>Define whether or not CDR should be updated by bridging changes.
117 This includes entering and leaving bridges and call parking.</para>
118 <para>If this is set to "no", bridging changes will be ignored for all CDRs.
119 This should only be done if these events should not affect CDRs and are undesired,
120 such as to use a single CDR for the lifetime of the channel.</para>
121 <para>This setting cannot be changed on a reload.</para>
122 </description>
123 </configOption>
124 <configOption name="ignoredialchanges" default="no">
125 <synopsis>Whether CDR is updated or forked by dial updates.</synopsis>
126 <description><para>Define whether or not CDR should be updated by dial updates.</para>
127 <para>If this is set to "no", a single CDR will be used for the channel, even if
128 multiple endpoints or destinations are dialed sequentially. Note that you will also
129 lose detailed nonanswer dial dispositions if this option is enabled, which may not be acceptable,
130 e.g. instead of detailed no-answer dispositions like BUSY and CONGESTION, the disposition
131 will always be NO ANSWER if the channel was unanswered (it will still be ANSWERED
132 if the channel was answered).</para>
133 <para>This option should be enabled if a single CDR is desired for the lifetime of
134 the channel.</para>
135 </description>
136 </configOption>
137 <configOption name="unanswered">
138 <synopsis>Log calls that are never answered and don't set an outgoing party.</synopsis>
139 <description><para>
140 Define whether or not to log unanswered calls that don't involve an outgoing party. Setting
141 this to "yes" will make calls to extensions that don't answer and don't set a side B channel
142 (such as by using the Dial application) receive CDR log entries. If this option is set to
143 "no", then those log entries will not be created. Unanswered calls which get offered to an
144 outgoing line will always receive log entries regardless of this option, and that is the
145 intended behavior.
146 </para>
147 </description>
148 </configOption>
149 <configOption name="congestion">
150 <synopsis>Log congested calls.</synopsis>
151 <description><para>Define whether or not to log congested calls. Setting this to "yes" will
152 report each call that fails to complete due to congestion conditions.</para>
153 </description>
154 </configOption>
155 <configOption name="endbeforehexten">
156 <synopsis>Don't produce CDRs while executing hangup logic</synopsis>
157 <description>
158 <para>As each CDR for a channel is finished, its end time is updated
159 and the CDR is finalized. When a channel is hung up and hangup
160 logic is present (in the form of a hangup handler or the
161 <literal>h</literal> extension), a new CDR is generated for the
162 channel. Any statistics are gathered from this new CDR. By enabling
163 this option, no new CDR is created for the dialplan logic that is
164 executed in <literal>h</literal> extensions or attached hangup handler
165 subroutines. The default value is <literal>yes</literal>, indicating
166 that a CDR will be generated during hangup logic.</para>
167 </description>
168 </configOption>
169 <configOption name="initiatedseconds">
170 <synopsis>Count microseconds for billsec purposes</synopsis>
171 <description><para>Normally, the <literal>billsec</literal> field logged to the CDR backends
172 is simply the end time (hangup time) minus the answer time in seconds. Internally,
173 asterisk stores the time in terms of microseconds and seconds. By setting
174 initiatedseconds to <literal>yes</literal>, you can force asterisk to report any seconds
175 that were initiated (a sort of round up method). Technically, this is
176 when the microsecond part of the end time is greater than the microsecond
177 part of the answer time, then the billsec time is incremented one second.</para>
178 </description>
179 </configOption>
180 <configOption name="batch">
181 <synopsis>Submit CDRs to the backends for processing in batches</synopsis>
182 <description><para>Define the CDR batch mode, where instead of posting the CDR at the end of
183 every call, the data will be stored in a buffer to help alleviate load on the
184 asterisk server.</para>
185 <warning><para>Use of batch mode may result in data loss after unsafe asterisk termination,
186 i.e., software crash, power failure, kill -9, etc.</para>
187 </warning>
188 </description>
189 </configOption>
190 <configOption name="size">
191 <synopsis>The maximum number of CDRs to accumulate before triggering a batch</synopsis>
192 <description><para>Define the maximum number of CDRs to accumulate in the buffer before posting
193 them to the backend engines. batch must be set to <literal>yes</literal>.</para>
194 </description>
195 </configOption>
196 <configOption name="time">
197 <synopsis>The maximum time to accumulate CDRs before triggering a batch</synopsis>
198 <description><para>Define the maximum time to accumulate CDRs before posting them in a batch to the
199 backend engines. If this time limit is reached, then it will post the records, regardless of the value
200 defined for size. batch must be set to <literal>yes</literal>.</para>
201 <note><para>Time is expressed in seconds.</para></note>
202 </description>
203 </configOption>
204 <configOption name="scheduleronly">
205 <synopsis>Post batched CDRs on their own thread instead of the scheduler</synopsis>
206 <description><para>The CDR engine uses the internal asterisk scheduler to determine when to post
207 records. Posting can either occur inside the scheduler thread, or a new
208 thread can be spawned for the submission of every batch. For small batches,
209 it might be acceptable to just use the scheduler thread, so set this to <literal>yes</literal>.
210 For large batches, say anything over size=10, a new thread is recommended, so
211 set this to <literal>no</literal>.</para>
212 </description>
213 </configOption>
214 <configOption name="safeshutdown">
215 <synopsis>Block shutdown of Asterisk until CDRs are submitted</synopsis>
216 <description><para>When shutting down asterisk, you can block until the CDRs are submitted. If
217 you don't, then data will likely be lost. You can always check the size of
218 the CDR batch buffer with the CLI <astcli>cdr status</astcli> command. To enable blocking on
219 submission of CDR data during asterisk shutdown, set this to <literal>yes</literal>.</para>
220 </description>
221 </configOption>
222 </configObject>
223 </configFile>
224 </configInfo>
225 ***/
226
227#define DEFAULT_ENABLED "1"
228#define DEFAULT_BATCHMODE "0"
229#define DEFAULT_UNANSWERED "0"
230#define DEFAULT_CONGESTION "0"
231#define DEFAULT_END_BEFORE_H_EXTEN "1"
232#define DEFAULT_INITIATED_SECONDS "0"
233#define DEFAULT_CHANNEL_ENABLED "1"
234#define DEFAULT_IGNORE_STATE_CHANGES "0"
235#define DEFAULT_IGNORE_DIAL_CHANGES "0"
236
237#define DEFAULT_BATCH_SIZE "100"
238#define MAX_BATCH_SIZE 1000
239#define DEFAULT_BATCH_TIME "300"
240#define MAX_BATCH_TIME 86400
241#define DEFAULT_BATCH_SCHEDULER_ONLY "0"
242#define DEFAULT_BATCH_SAFE_SHUTDOWN "1"
243
244#define cdr_set_debug_mode(mod_cfg) \
245 do { \
246 cdr_debug_enabled = ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG); \
247 } while (0)
248
251
252#define CDR_DEBUG(fmt, ...) \
253 do { \
254 if (cdr_debug_enabled) { \
255 ast_verbose((fmt), ##__VA_ARGS__); \
256 } \
257 } while (0)
258
259static void cdr_detach(struct ast_cdr *cdr);
260static void cdr_submit_batch(int shutdown);
261static int cdr_toggle_runtime_options(void);
262
263/*! \brief The configuration settings for this module */
265 struct ast_cdr_config *general; /*!< CDR global settings */
266};
267
268/*! \brief The container for the module configuration */
269static AO2_GLOBAL_OBJ_STATIC(module_configs);
270
271/*! \brief The type definition for general options */
272static struct aco_type general_option = {
273 .type = ACO_GLOBAL,
274 .name = "general",
275 .item_offset = offsetof(struct module_config, general),
276 .category = "general",
277 .category_match = ACO_WHITELIST_EXACT,
278};
279
280/*! Config sections used by existing modules. Do not add to this list. */
281static const char *ignore_categories[] = {
282 "csv",
283 "custom",
284 "manager",
285 "odbc",
286 "pgsql",
287 "radius",
288 "sqlite",
289 "tds",
290 "mysql",
291 NULL,
292};
293
294static struct aco_type ignore_option = {
295 .type = ACO_IGNORE,
296 .name = "modules",
297 .category = (const char*)ignore_categories,
299};
300
301static void *module_config_alloc(void);
302static void module_config_destructor(void *obj);
303static void module_config_post_apply(void);
304
305/*! \brief The file definition */
306static struct aco_file module_file_conf = {
307 .filename = "cdr.conf",
309};
310
311CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc,
312 .files = ACO_FILES(&module_file_conf),
313 .post_apply_config = module_config_post_apply,
314);
315
317
319{
320 struct module_config *mod_cfg;
321
322 mod_cfg = ao2_global_obj_ref(module_configs);
323 if (!mod_cfg) {
324 return;
325 }
326 cdr_set_debug_mode(mod_cfg);
327 ao2_cleanup(mod_cfg);
328}
329
330/*! \brief Dispose of a module config object */
331static void module_config_destructor(void *obj)
332{
333 struct module_config *cfg = obj;
334
335 if (!cfg) {
336 return;
337 }
338 ao2_ref(cfg->general, -1);
339}
340
341/*! \brief Create a new module config object */
342static void *module_config_alloc(void)
343{
344 struct module_config *mod_cfg;
346
347 mod_cfg = ao2_alloc(sizeof(*mod_cfg), module_config_destructor);
348 if (!mod_cfg) {
349 return NULL;
350 }
351
352 cdr_config = ao2_alloc(sizeof(*cdr_config), NULL);
353 if (!cdr_config) {
354 ao2_ref(cdr_config, -1);
355 return NULL;
356 }
357 mod_cfg->general = cdr_config;
358
359 return mod_cfg;
360}
361
362/*! \brief Registration object for CDR backends */
364 char name[20];
365 char desc[80];
368 int suspended:1;
369};
370
371/*! \brief List of registered backends */
373
374/*! \brief List of registered modifiers */
376
377/*! \brief Queued CDR waiting to be batched */
379 struct ast_cdr *cdr;
381};
382
383/*! \brief The actual batch queue */
384static struct cdr_batch {
385 int size;
389
390/*! \brief The global sequence counter used for CDRs */
391static int global_cdr_sequence = 0;
392
393/*! \brief Scheduler items */
395static int cdr_sched = -1;
397static pthread_t cdr_thread = AST_PTHREADT_NULL;
398
399/*! \brief Lock protecting modifications to the batch queue */
401
402/*! \brief These are used to wake up the CDR thread when there's work to do */
405
406/*! \brief A container of the active master CDRs indexed by Party A channel uniqueid */
408
409/*! \brief A container of all active CDRs with a Party B indexed by Party B channel name */
411
412/*! \brief Message router for stasis messages regarding channel state */
414
415/*! \brief Our subscription for bridges */
417
418/*! \brief Our subscription for channels */
420
421/*! \brief Our subscription for parking */
423
424/*! \brief The parent topic for all topics we want to aggregate for CDRs */
425static struct stasis_topic *cdr_topic;
426
427/*! \brief A message type used to synchronize with the CDR topic */
428STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_sync_message_type);
429
430struct cdr_object;
431
432/*! \brief Return types for \p process_bridge_enter functions */
434 /*!
435 * The CDR was the only party in the bridge.
436 */
438 /*!
439 * The CDR was able to obtain a Party B from some other party already in the bridge
440 */
442 /*!
443 * The CDR was not able to obtain a Party B
444 */
446 /*!
447 * This CDR can't handle a bridge enter message and a new CDR needs to be created
448 */
450};
451
452/*!
453 * \brief A virtual table used for \ref cdr_object.
454 *
455 * Note that all functions are optional - if a subclass does not need an
456 * implementation, it is safe to leave it NULL.
457 */
459 /*! \brief Name of the subclass */
460 const char *name;
461
462 /*!
463 * \brief An initialization function. This will be called automatically
464 * when a \ref cdr_object is switched to this type in
465 * \ref cdr_object_transition_state
466 *
467 * \param cdr The \ref cdr_object that was just transitioned
468 */
469 void (* const init_function)(struct cdr_object *cdr);
470
471 /*!
472 * \brief Process a Party A update for the \ref cdr_object
473 *
474 * \param cdr The \ref cdr_object to process the update
475 * \param snapshot The snapshot for the CDR's Party A
476 * \retval 0 the CDR handled the update or ignored it
477 * \retval 1 the CDR is finalized and a new one should be made to handle it
478 */
479 int (* const process_party_a)(struct cdr_object *cdr,
480 struct ast_channel_snapshot *snapshot);
481
482 /*!
483 * \brief Process a Party B update for the \ref cdr_object
484 *
485 * \param cdr The \ref cdr_object to process the update
486 * \param snapshot The snapshot for the CDR's Party B
487 */
488 void (* const process_party_b)(struct cdr_object *cdr,
489 struct ast_channel_snapshot *snapshot);
490
491 /*!
492 * \brief Process the beginning of a dial. A dial message implies one of two
493 * things:
494 * The \ref cdr_object's Party A has been originated
495 * The \ref cdr_object's Party A is dialing its Party B
496 *
497 * \param cdr The \ref cdr_object
498 * \param caller The originator of the dial attempt
499 * \param peer The destination of the dial attempt
500 *
501 * \retval 0 if the parties in the dial were handled by this CDR
502 * \retval 1 if the parties could not be handled by this CDR
503 */
504 int (* const process_dial_begin)(struct cdr_object *cdr,
506 struct ast_channel_snapshot *peer);
507
508 /*!
509 * \brief Process the end of a dial. At the end of a dial, a CDR can be
510 * transitioned into one of two states - DialedPending
511 * (\ref dialed_pending_state_fn_table) or Finalized
512 * (\ref finalized_state_fn_table).
513 *
514 * \param cdr The \ref cdr_object
515 * \param caller The originator of the dial attempt
516 * \param peer the Destination of the dial attempt
517 * \param dial_status What happened
518 *
519 * \retval 0 if the parties in the dial were handled by this CDR
520 * \retval 1 if the parties could not be handled by this CDR
521 */
522 int (* const process_dial_end)(struct cdr_object *cdr,
525 const char *dial_status);
526
527 /*!
528 * \brief Process the entering of a bridge by this CDR. The purpose of this
529 * callback is to have the CDR prepare itself for the bridge and attempt to
530 * find a valid Party B. The act of creating new CDRs based on the entering
531 * of this channel into the bridge is handled by the higher level message
532 * handler.
533 *
534 * Note that this handler is for when a channel enters into a "normal"
535 * bridge, where people actually talk to each other. Parking is its own
536 * thing.
537 *
538 * \param cdr The \ref cdr_object
539 * \param bridge The bridge that the Party A just entered into
540 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
541 *
542 * \return process_bridge_enter_results Defines whether or not this CDR was able
543 * to fully handle the bridge enter message.
544 */
546 struct cdr_object *cdr,
547 struct ast_bridge_snapshot *bridge,
548 struct ast_channel_snapshot *channel);
549
550 /*!
551 * \brief Process entering into a parking bridge.
552 *
553 * \param cdr The \ref cdr_object
554 * \param bridge The parking bridge that Party A just entered into
555 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
556 *
557 * \retval 0 This CDR successfully transitioned itself into the parked state
558 * \retval 1 This CDR couldn't handle the parking transition and we need a
559 * new CDR.
560 */
561 int (* const process_parking_bridge_enter)(struct cdr_object *cdr,
562 struct ast_bridge_snapshot *bridge,
563 struct ast_channel_snapshot *channel);
564
565 /*!
566 * \brief Process the leaving of a bridge by this CDR.
567 *
568 * \param cdr The \ref cdr_object
569 * \param bridge The bridge that the Party A just left
570 * \param channel The \ref ast_channel_snapshot for this CDR's Party A
571 *
572 * \retval 0 This CDR left successfully
573 * \retval 1 Error
574 */
575 int (* const process_bridge_leave)(struct cdr_object *cdr,
576 struct ast_bridge_snapshot *bridge,
577 struct ast_channel_snapshot *channel);
578
579 /*!
580 * \brief Process an update informing us that the channel got itself parked
581 *
582 * \param cdr The \ref cdr_object
583 * \param channel The parking information for this CDR's party A
584 *
585 * \retval 0 This CDR successfully parked itself
586 * \retval 1 This CDR couldn't handle the park
587 */
588 int (* const process_parked_channel)(struct cdr_object *cdr,
589 struct ast_parked_call_payload *parking_info);
590};
591
592static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
594static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
595static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
596static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info);
597
598static void single_state_init_function(struct cdr_object *cdr);
599static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
600static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
602static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
603
604/*!
605 * \brief The virtual table for the Single state.
606 *
607 * A \ref cdr_object starts off in this state. This represents a channel that
608 * has no Party B information itself.
609 *
610 * A \ref cdr_object from this state can go into any of the following states:
611 * * \ref dial_state_fn_table
612 * * \ref bridge_state_fn_table
613 * * \ref finalized_state_fn_table
614 */
616 .name = "Single",
617 .init_function = single_state_init_function,
618 .process_party_a = base_process_party_a,
619 .process_party_b = single_state_process_party_b,
620 .process_dial_begin = single_state_process_dial_begin,
621 .process_dial_end = base_process_dial_end,
622 .process_bridge_enter = single_state_process_bridge_enter,
623 .process_parking_bridge_enter = single_state_process_parking_bridge_enter,
624 .process_bridge_leave = base_process_bridge_leave,
625 .process_parked_channel = base_process_parked_channel,
626};
627
628static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
629static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
630static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
632
633/*!
634 * \brief The virtual table for the Dial state.
635 *
636 * A \ref cdr_object that has begun a dial operation. This state is entered when
637 * the Party A for a CDR is determined to be dialing out to a Party B or when
638 * a CDR is for an originated channel (in which case the Party A information is
639 * the originated channel, and there is no Party B).
640 *
641 * A \ref cdr_object from this state can go in any of the following states:
642 * * \ref dialed_pending_state_fn_table
643 * * \ref bridge_state_fn_table
644 * * \ref finalized_state_fn_table
645 */
647 .name = "Dial",
648 .process_party_a = base_process_party_a,
649 .process_party_b = dial_state_process_party_b,
650 .process_dial_begin = dial_state_process_dial_begin,
651 .process_dial_end = dial_state_process_dial_end,
652 .process_bridge_enter = dial_state_process_bridge_enter,
653 .process_bridge_leave = base_process_bridge_leave,
654};
655
656static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
657static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
660
661/*!
662 * \brief The virtual table for the Dialed Pending state.
663 *
664 * A \ref cdr_object that has successfully finished a dial operation, but we
665 * don't know what they're going to do yet. It's theoretically possible to dial
666 * a party and then have that party not be bridged with the caller; likewise,
667 * an origination can complete and the channel go off and execute dialplan. The
668 * pending state acts as a bridge between either:
669 * * Entering a bridge
670 * * Getting a new CDR for new dialplan execution
671 * * Switching from being originated to executing dialplan
672 *
673 * A \ref cdr_object from this state can go in any of the following states:
674 * * \ref single_state_fn_table
675 * * \ref dialed_pending_state_fn_table
676 * * \ref bridge_state_fn_table
677 * * \ref finalized_state_fn_table
678 */
680 .name = "DialedPending",
681 .process_party_a = dialed_pending_state_process_party_a,
682 .process_dial_begin = dialed_pending_state_process_dial_begin,
683 .process_bridge_enter = dialed_pending_state_process_bridge_enter,
684 .process_parking_bridge_enter = dialed_pending_state_process_parking_bridge_enter,
685 .process_bridge_leave = base_process_bridge_leave,
686 .process_parked_channel = base_process_parked_channel,
687};
688
689static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
690static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
691
692/*!
693 * \brief The virtual table for the Bridged state
694 *
695 * A \ref cdr_object enters this state when it receives notification that the
696 * channel has entered a bridge.
697 *
698 * A \ref cdr_object from this state can go to:
699 * * \ref finalized_state_fn_table
700 */
702 .name = "Bridged",
703 .process_party_a = base_process_party_a,
704 .process_party_b = bridge_state_process_party_b,
705 .process_bridge_leave = bridge_state_process_bridge_leave,
706 .process_parked_channel = base_process_parked_channel,
707};
708
709static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
710
711/*!
712 * \brief The virtual table for the Parked state
713 *
714 * Parking is weird. Unlike typical bridges, it has to be treated somewhat
715 * uniquely - a channel in a parking bridge (which is a subclass of a holding
716 * bridge) has to be handled as if the channel went into an application.
717 * However, when the channel comes out, we need a new CDR - unlike the Single
718 * state.
719 */
721 .name = "Parked",
722 .process_party_a = base_process_party_a,
723 .process_bridge_leave = parked_state_process_bridge_leave,
724 .process_parked_channel = base_process_parked_channel,
725};
726
727static void finalized_state_init_function(struct cdr_object *cdr);
728static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
729
730/*!
731 * \brief The virtual table for the finalized state.
732 *
733 * Once in the finalized state, the CDR is done. No modifications can be made
734 * to the CDR.
735 */
737 .name = "Finalized",
738 .init_function = finalized_state_init_function,
739 .process_party_a = finalized_state_process_party_a,
740 .process_bridge_enter = base_process_bridge_enter,
741};
742
743/*! \brief A wrapper object around a snapshot.
744 * Fields that are mutable by the CDR engine are replicated here.
745 */
747 struct ast_channel_snapshot *snapshot; /*!< The channel snapshot */
748 char userfield[AST_MAX_USER_FIELD]; /*!< Userfield for the channel */
749 unsigned int flags; /*!< Specific flags for this party */
750 struct varshead variables; /*!< CDR variables for the channel */
751};
752
753/*! \brief An in-memory representation of an active CDR */
755 struct cdr_object_snapshot party_a; /*!< The Party A information */
756 struct cdr_object_snapshot party_b; /*!< The Party B information */
757 struct cdr_object_fn_table *fn_table; /*!< The current virtual table */
758
759 enum ast_cdr_disposition disposition; /*!< The disposition of the CDR */
760 struct timeval start; /*!< When this CDR was created */
761 struct timeval answer; /*!< Either when the channel was answered, or when the path between channels was established */
762 struct timeval end; /*!< When this CDR was finalized */
763 struct timeval lastevent; /*!< The time at which the last event was created regarding this CDR */
764 unsigned int sequence; /*!< A monotonically increasing number for each CDR */
765 struct ast_flags flags; /*!< Flags on the CDR */
767 AST_STRING_FIELD(linkedid); /*!< Linked ID. Cached here as it may change out from party A, which must be immutable */
768 AST_STRING_FIELD(uniqueid); /*!< Unique id of party A. Cached here as it is the master CDR container key */
769 AST_STRING_FIELD(tenantid); /*!< Tenant ID. Cached here because the value can be manipulated through dialplan */
770 AST_STRING_FIELD(name); /*!< Channel name of party A. Cached here as the party A address may change */
771 AST_STRING_FIELD(bridge); /*!< The bridge the party A happens to be in. */
772 AST_STRING_FIELD(appl); /*!< The last accepted application party A was in */
773 AST_STRING_FIELD(data); /*!< The data for the last accepted application party A was in */
774 AST_STRING_FIELD(context); /*!< The accepted context for Party A */
775 AST_STRING_FIELD(exten); /*!< The accepted extension for Party A */
776 AST_STRING_FIELD(party_b_name); /*!< Party B channel name. Cached here as it is the all CDRs container key */
777 );
778 struct cdr_object *next; /*!< The next CDR object in the chain */
779 struct cdr_object *last; /*!< The last CDR object in the chain */
780 int is_root; /*!< True if this is the first CDR in the chain */
781};
782
783/*!
784 * \brief Copy variables from one list to another
785 * \param to_list destination
786 * \param from_list source
787 * \return The number of copied variables
788 */
789static int copy_variables(struct varshead *to_list, struct varshead *from_list)
790{
791 struct ast_var_t *variables;
792 struct ast_var_t *newvariable;
793 const char *var;
794 const char *val;
795 int x = 0;
796
797 AST_LIST_TRAVERSE(from_list, variables, entries) {
798 var = ast_var_name(variables);
799 if (ast_strlen_zero(var)) {
800 continue;
801 }
802 val = ast_var_value(variables);
803 if (ast_strlen_zero(val)) {
804 continue;
805 }
806 newvariable = ast_var_assign(var, val);
807 if (newvariable) {
808 AST_LIST_INSERT_HEAD(to_list, newvariable, entries);
809 ++x;
810 }
811 }
812
813 return x;
814}
815
816/*!
817 * \brief Delete all variables from a variable list
818 * \param headp The head pointer to the variable list to delete
819 */
820static void free_variables(struct varshead *headp)
821{
822 struct ast_var_t *vardata;
823
824 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
825 ast_var_delete(vardata);
826 }
827}
828
829/*!
830 * \brief Copy a snapshot and its details
831 * \param dst The destination
832 * \param src The source
833 */
835{
836 ao2_t_replace(dst->snapshot, src->snapshot, "CDR snapshot copy");
837 strcpy(dst->userfield, src->userfield);
838 dst->flags = src->flags;
839 copy_variables(&dst->variables, &src->variables);
840}
841
842/*!
843 * \brief Transition a \ref cdr_object to a new state with initiation flag
844 * \param cdr The \ref cdr_object to transition
845 * \param fn_table The \ref cdr_object_fn_table state to go to
846 * \param do_init
847 */
848static void cdr_object_transition_state_init(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table, int do_init)
849{
850 CDR_DEBUG("%p - Transitioning CDR for %s from state %s to %s\n",
851 cdr, cdr->party_a.snapshot->base->name,
852 cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
853 cdr->fn_table = fn_table;
854
855 if (cdr->fn_table->init_function && do_init) {
856 cdr->fn_table->init_function(cdr);
857 }
858}
859
860/*!
861 * \brief Transition a \ref cdr_object to a new state
862 * \param cdr The \ref cdr_object to transition
863 * \param fn_table The \ref cdr_object_fn_table state to go to
864 */
865static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
866{
867 cdr_object_transition_state_init(cdr, fn_table, 1);
868}
869
870/*!
871 * \internal
872 * \brief Hash function for master CDR container indexed by Party A uniqueid.
873 */
874static int cdr_master_hash_fn(const void *obj, const int flags)
875{
876 const struct cdr_object *cdr;
877 const char *key;
878
879 switch (flags & OBJ_SEARCH_MASK) {
880 case OBJ_SEARCH_KEY:
881 key = obj;
882 break;
884 cdr = obj;
885 key = cdr->uniqueid;
886 break;
887 default:
888 ast_assert(0);
889 return 0;
890 }
891 return ast_str_case_hash(key);
892}
893
894/*!
895 * \internal
896 * \brief Comparison function for master CDR container indexed by Party A uniqueid.
897 */
898static int cdr_master_cmp_fn(void *obj, void *arg, int flags)
899{
900 struct cdr_object *left = obj;
901 struct cdr_object *right = arg;
902 const char *right_key = arg;
903 int cmp;
904
905 switch (flags & OBJ_SEARCH_MASK) {
907 right_key = right->uniqueid;
908 /* Fall through */
909 case OBJ_SEARCH_KEY:
910 cmp = strcmp(left->uniqueid, right_key);
911 break;
913 /*
914 * We could also use a partial key struct containing a length
915 * so strlen() does not get called for every comparison instead.
916 */
917 cmp = strncmp(left->uniqueid, right_key, strlen(right_key));
918 break;
919 default:
920 /* Sort can only work on something with a full or partial key. */
921 ast_assert(0);
922 cmp = 0;
923 break;
924 }
925 return cmp ? 0 : CMP_MATCH;
926}
927
928/*!
929 * \internal
930 * \brief Hash function for all CDR container indexed by Party B channel name.
931 */
932static int cdr_all_hash_fn(const void *obj, const int flags)
933{
934 const struct cdr_object *cdr;
935 const char *key;
936
937 switch (flags & OBJ_SEARCH_MASK) {
938 case OBJ_SEARCH_KEY:
939 key = obj;
940 break;
942 cdr = obj;
943 key = cdr->party_b_name;
944 break;
945 default:
946 ast_assert(0);
947 return 0;
948 }
949 return ast_str_case_hash(key);
950}
951
952/*!
953 * \internal
954 * \brief Comparison function for all CDR container indexed by Party B channel name.
955 */
956static int cdr_all_cmp_fn(void *obj, void *arg, int flags)
957{
958 struct cdr_object *left = obj;
959 struct cdr_object *right = arg;
960 const char *right_key = arg;
961 int cmp;
962
963 switch (flags & OBJ_SEARCH_MASK) {
965 right_key = right->party_b_name;
966 /* Fall through */
967 case OBJ_SEARCH_KEY:
968 cmp = strcasecmp(left->party_b_name, right_key);
969 break;
971 /*
972 * We could also use a partial key struct containing a length
973 * so strlen() does not get called for every comparison instead.
974 */
975 cmp = strncasecmp(left->party_b_name, right_key, strlen(right_key));
976 break;
977 default:
978 /* Sort can only work on something with a full or partial key. */
979 ast_assert(0);
980 cmp = 0;
981 break;
982 }
983 return cmp ? 0 : CMP_MATCH;
984}
985
986/*!
987 * \internal
988 * \brief Relink the CDR because Party B's snapshot changed.
989 * \since 13.19.0
990 */
991static void cdr_all_relink(struct cdr_object *cdr)
992{
994 if (cdr->party_b.snapshot) {
995 if (strcasecmp(cdr->party_b_name, cdr->party_b.snapshot->base->name)) {
999 }
1000 } else {
1003 }
1005}
1006
1007/*!
1008 * \internal
1009 * \brief Unlink the master CDR and chained records from the active_cdrs_all container.
1010 * \since 13.19.0
1011 */
1012static void cdr_all_unlink(struct cdr_object *cdr)
1013{
1014 struct cdr_object *cur;
1015 struct cdr_object *next;
1016
1017 ast_assert(cdr->is_root);
1018
1019 /* Hold a ref to the root CDR to ensure the list members don't go away on us. */
1020 ao2_ref(cdr, +1);
1022 for (cur = cdr; cur; cur = next) {
1023 next = cur->next;
1025 /*
1026 * It is safe to still use cur after unlinking because the
1027 * root CDR holds a ref to all the CDRs in the list and we
1028 * have a ref to the root CDR.
1029 */
1031 }
1033 ao2_ref(cdr, -1);
1034}
1035
1036/*!
1037 * \brief \ref cdr_object Destructor
1038 */
1039static void cdr_object_dtor(void *obj)
1040{
1041 struct cdr_object *cdr = obj;
1042 struct ast_var_t *it_var;
1043
1046 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_a.variables, entries))) {
1047 ast_var_delete(it_var);
1048 }
1049 while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_b.variables, entries))) {
1050 ast_var_delete(it_var);
1051 }
1053
1054 /* CDR destruction used to work by calling ao2_cleanup(next) and
1055 * allowing the chain to destroy itself neatly. Unfortunately, for
1056 * really long chains, this can result in a stack overflow. So now
1057 * when the root CDR is destroyed, it is responsible for unreffing
1058 * all CDRs in the chain
1059 */
1060 if (cdr->is_root) {
1061 struct cdr_object *curr = cdr->next;
1062 struct cdr_object *next;
1063
1064 while (curr) {
1065 next = curr->next;
1066 ao2_cleanup(curr);
1067 curr = next;
1068 }
1069 }
1070}
1071
1072/*!
1073 * \brief \ref cdr_object constructor
1074 * \param chan The \ref ast_channel_snapshot that is the CDR's Party A
1075 * \param event_time
1076 *
1077 * This implicitly sets the state of the newly created CDR to the Single state
1078 * (\ref single_state_fn_table)
1079 */
1080static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
1081{
1082 struct cdr_object *cdr;
1083
1084 ast_assert(chan != NULL);
1085
1086 cdr = ao2_alloc(sizeof(*cdr), cdr_object_dtor);
1087 if (!cdr) {
1088 return NULL;
1089 }
1090 cdr->last = cdr;
1091 if (ast_string_field_init(cdr, 64)) {
1092 ao2_cleanup(cdr);
1093 return NULL;
1094 }
1096 ast_string_field_set(cdr, name, chan->base->name);
1101 cdr->lastevent = *event_time;
1102
1103 cdr->party_a.snapshot = chan;
1104 ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
1105
1106 CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->base->name);
1107
1109
1110 return cdr;
1111}
1112
1113/*!
1114 * \brief Create a new \ref cdr_object and append it to an existing chain
1115 * \param cdr The \ref cdr_object to append to
1116 * \param event_time
1117 */
1118static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
1119{
1120 struct cdr_object *new_cdr;
1121 struct cdr_object *it_cdr;
1122 struct cdr_object *cdr_last;
1123
1124 cdr_last = cdr->last;
1125 new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot, event_time);
1126 if (!new_cdr) {
1127 return NULL;
1128 }
1129 new_cdr->disposition = AST_CDR_NULL;
1130
1131 /* Copy over the linkedid, as it may have changed */
1132 ast_string_field_set(new_cdr, linkedid, cdr_last->linkedid);
1133 ast_string_field_set(new_cdr, appl, cdr_last->appl);
1134 ast_string_field_set(new_cdr, data, cdr_last->data);
1135 ast_string_field_set(new_cdr, context, cdr_last->context);
1136 ast_string_field_set(new_cdr, exten, cdr_last->exten);
1137
1138 /*
1139 * If the current CDR says to disable all future ones,
1140 * keep the disable chain going
1141 */
1142 if (ast_test_flag(&cdr_last->flags, AST_CDR_FLAG_DISABLE_ALL)) {
1144 }
1145
1146 /* Copy over other Party A information */
1147 cdr_object_snapshot_copy(&new_cdr->party_a, &cdr_last->party_a);
1148
1149 /* Append the CDR to the end of the list */
1150 for (it_cdr = cdr; it_cdr->next; it_cdr = it_cdr->next) {
1151 it_cdr->last = new_cdr;
1152 }
1153 it_cdr->last = new_cdr;
1154 it_cdr->next = new_cdr;
1155
1156 return new_cdr;
1157}
1158
1159/*!
1160 * \internal
1161 * \brief Determine if CDR flag is configured.
1162 *
1163 * \param cdr_flag The configured CDR flag to check.
1164 *
1165 * \retval 0 if the CDR flag is not configured.
1166 * \retval non-zero if the CDR flag is configured.
1167 */
1168static int is_cdr_flag_set(unsigned int cdr_flag)
1169{
1170 struct module_config *mod_cfg;
1171 int flag_set;
1172
1173 mod_cfg = ao2_global_obj_ref(module_configs);
1174 flag_set = mod_cfg && ast_test_flag(&mod_cfg->general->settings, cdr_flag);
1175 ao2_cleanup(mod_cfg);
1176 return flag_set;
1177}
1178
1179/*!
1180 * \brief Return whether or not a channel has changed its state in the dialplan, subject
1181 * to endbeforehexten logic
1182 *
1183 * \param old_snapshot The previous state
1184 * \param new_snapshot The new state
1185 *
1186 * \retval 0 if the state has not changed
1187 * \retval 1 if the state changed
1188 */
1189static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
1190 struct ast_channel_snapshot *new_snapshot)
1191{
1192 /* If we ignore hangup logic, don't indicate that we're executing anything new */
1195 return 0;
1196 }
1197
1198 /* When Party A is originated to an application and the application exits, the stack
1199 * will attempt to clear the application and restore the dummy originate application
1200 * of "AppDialX". Ignore application changes to AppDialX as a result.
1201 */
1202 if (strcmp(new_snapshot->dialplan->appl, old_snapshot->dialplan->appl)
1203 && strncasecmp(new_snapshot->dialplan->appl, "appdial", 7)
1204 && (strcmp(new_snapshot->dialplan->context, old_snapshot->dialplan->context)
1205 || strcmp(new_snapshot->dialplan->exten, old_snapshot->dialplan->exten)
1206 || new_snapshot->dialplan->priority != old_snapshot->dialplan->priority)) {
1207 return 1;
1208 }
1209
1210 return 0;
1211}
1212
1213/*!
1214 * \brief Return whether or not a \ref ast_channel_snapshot is for a channel
1215 * that was created as the result of a dial operation
1216 *
1217 * \retval 0 the channel was not created as the result of a dial
1218 * \retval 1 the channel was created as the result of a dial
1219 */
1220static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
1221{
1222 return (ast_test_flag(&snapshot->flags, AST_FLAG_OUTGOING)
1223 && !(ast_test_flag(&snapshot->flags, AST_FLAG_ORIGINATED)));
1224}
1225
1226/*!
1227 * \brief Given two CDR snapshots, figure out who should be Party A for the
1228 * resulting CDR
1229 * \param left One of the snapshots
1230 * \param right The other snapshot
1231 * \return The snapshot that won
1232 */
1234{
1235 /* Check whether or not the party is dialed. A dialed party is never the
1236 * Party A with a party that was not dialed.
1237 */
1238 if (!snapshot_is_dialed(left->snapshot) && snapshot_is_dialed(right->snapshot)) {
1239 return left;
1240 } else if (snapshot_is_dialed(left->snapshot) && !snapshot_is_dialed(right->snapshot)) {
1241 return right;
1242 }
1243
1244 /* Try the Party A flag */
1246 return left;
1248 return right;
1249 }
1250
1251 /* Neither party is dialed and neither has the Party A flag - defer to
1252 * creation time */
1253 if (left->snapshot->base->creationtime.tv_sec < right->snapshot->base->creationtime.tv_sec) {
1254 return left;
1255 } else if (left->snapshot->base->creationtime.tv_sec > right->snapshot->base->creationtime.tv_sec) {
1256 return right;
1257 } else if (left->snapshot->base->creationtime.tv_usec > right->snapshot->base->creationtime.tv_usec) {
1258 return right;
1259 } else {
1260 /* Okay, fine, take the left one */
1261 return left;
1262 }
1263}
1264
1265/*!
1266 * Compute the duration for a \ref cdr_object
1267 */
1268static long cdr_object_get_duration(struct cdr_object *cdr)
1269{
1270 return (long)(ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->start) / 1000);
1271}
1272
1273/*!
1274 * \brief Compute the billsec for a \ref cdr_object
1275 */
1276static long cdr_object_get_billsec(struct cdr_object *cdr)
1277{
1278 long int ms;
1279
1280 if (ast_tvzero(cdr->answer)) {
1281 return 0;
1282 }
1283
1284 ms = ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->answer);
1285 if (ms % 1000 >= 500
1287 ms = (ms / 1000) + 1;
1288 } else {
1289 ms = ms / 1000;
1290 }
1291
1292 return ms;
1293}
1294
1295/*!
1296 * \internal
1297 * \brief Set a variable on a CDR object
1298 *
1299 * \param headp The header pointer to the variable to set
1300 * \param name The name of the variable
1301 * \param value The value of the variable
1302 */
1303static void set_variable(struct varshead *headp, const char *name, const char *value)
1304{
1305 struct ast_var_t *newvariable;
1306
1307 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1308 if (!strcasecmp(ast_var_name(newvariable), name)) {
1310 ast_var_delete(newvariable);
1311 break;
1312 }
1313 }
1315
1316 if (value && (newvariable = ast_var_assign(name, value))) {
1317 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1318 }
1319}
1320
1321/*!
1322 * \brief Create a chain of \ref ast_cdr objects from a chain of \ref cdr_object
1323 * suitable for consumption by the registered CDR backends
1324 * \param cdr The \ref cdr_object to convert to a public record
1325 * \return A chain of \ref ast_cdr objects on success
1326 * \retval NULL on failure
1327 */
1329{
1330 struct ast_cdr *pub_cdr = NULL, *cdr_prev = NULL;
1331 struct cdr_object *it_cdr;
1332 struct ast_var_t *it_var, *it_copy_var;
1333 struct ast_channel_snapshot *party_a;
1334 struct ast_channel_snapshot *party_b;
1335
1336 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1337 struct ast_cdr *cdr_copy;
1338
1339 /* Don't create records for CDRs where the party A was a dialed channel */
1340 if (snapshot_is_dialed(it_cdr->party_a.snapshot) && !it_cdr->party_b.snapshot) {
1341 ast_debug(1, "CDR for %s is dialed and has no Party B; discarding\n",
1342 it_cdr->party_a.snapshot->base->name);
1343 continue;
1344 }
1345
1346 cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
1347 if (!cdr_copy) {
1348 ast_free(pub_cdr);
1349 return NULL;
1350 }
1351
1352 party_a = it_cdr->party_a.snapshot;
1353 party_b = it_cdr->party_b.snapshot;
1354
1355 /* Party A */
1356 ast_assert(party_a != NULL);
1357 ast_copy_string(cdr_copy->accountcode, party_a->base->accountcode, sizeof(cdr_copy->accountcode));
1358 cdr_copy->amaflags = party_a->amaflags;
1359 ast_copy_string(cdr_copy->channel, party_a->base->name, sizeof(cdr_copy->channel));
1360 ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller->name, party_a->caller->number, "");
1361 ast_copy_string(cdr_copy->src, party_a->caller->number, sizeof(cdr_copy->src));
1362 ast_copy_string(cdr_copy->uniqueid, party_a->base->uniqueid, sizeof(cdr_copy->uniqueid));
1363 ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
1364 ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
1365 ast_copy_string(cdr_copy->dst, it_cdr->exten, sizeof(cdr_copy->dst));
1366 ast_copy_string(cdr_copy->dcontext, it_cdr->context, sizeof(cdr_copy->dcontext));
1367 ast_copy_string(cdr_copy->tenantid, it_cdr->tenantid, sizeof(cdr_copy->tenantid));
1368
1369 /* Party B */
1370 if (party_b) {
1371 ast_copy_string(cdr_copy->dstchannel, party_b->base->name, sizeof(cdr_copy->dstchannel));
1372 ast_copy_string(cdr_copy->peeraccount, party_b->base->accountcode, sizeof(cdr_copy->peeraccount));
1373 if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
1374 snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
1375 }
1376 ast_copy_string(cdr_copy->peertenantid, party_b->base->tenantid, sizeof(cdr_copy->peertenantid));
1377 }
1378 if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) {
1379 ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield));
1380 }
1381
1382 /* Timestamps/durations */
1383 cdr_copy->start = it_cdr->start;
1384 cdr_copy->answer = it_cdr->answer;
1385 cdr_copy->end = it_cdr->end;
1386 cdr_copy->billsec = cdr_object_get_billsec(it_cdr);
1387 cdr_copy->duration = cdr_object_get_duration(it_cdr);
1388
1389 /* Flags and IDs */
1390 ast_copy_flags(cdr_copy, &it_cdr->flags, AST_FLAGS_ALL);
1391 ast_copy_string(cdr_copy->linkedid, it_cdr->linkedid, sizeof(cdr_copy->linkedid));
1392 cdr_copy->disposition = it_cdr->disposition;
1393 cdr_copy->sequence = it_cdr->sequence;
1394
1395 /* Variables */
1396 copy_variables(&cdr_copy->varshead, &it_cdr->party_a.variables);
1397 AST_LIST_TRAVERSE(&it_cdr->party_b.variables, it_var, entries) {
1398 int found = 0;
1399 struct ast_var_t *newvariable;
1400 AST_LIST_TRAVERSE(&cdr_copy->varshead, it_copy_var, entries) {
1401 if (!strcasecmp(ast_var_name(it_var), ast_var_name(it_copy_var))) {
1402 found = 1;
1403 break;
1404 }
1405 }
1406 if (!found && (newvariable = ast_var_assign(ast_var_name(it_var), ast_var_value(it_var)))) {
1407 AST_LIST_INSERT_TAIL(&cdr_copy->varshead, newvariable, entries);
1408 }
1409 }
1410
1411 if (!pub_cdr) {
1412 pub_cdr = cdr_copy;
1413 cdr_prev = pub_cdr;
1414 } else {
1415 cdr_prev->next = cdr_copy;
1416 cdr_prev = cdr_copy;
1417 }
1418 }
1419
1420 return pub_cdr;
1421}
1422
1423/*!
1424 * \brief Dispatch a CDR.
1425 * \param cdr The \ref cdr_object to dispatch
1426 *
1427 * This will create a \ref ast_cdr object and publish it to the various backends
1428 */
1429static void cdr_object_dispatch(struct cdr_object *cdr)
1430{
1431 struct ast_cdr *pub_cdr;
1432
1433 CDR_DEBUG("%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
1434 cdr->party_a.snapshot->base->name,
1435 cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<none>");
1436 pub_cdr = cdr_object_create_public_records(cdr);
1437 cdr_detach(pub_cdr);
1438}
1439
1440/*!
1441 * \brief Set the disposition on a \ref cdr_object based on a hangupcause code
1442 * \param cdr The \ref cdr_object
1443 * \param hangupcause The Asterisk hangup cause code
1444 */
1445static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
1446{
1447 /* Change the disposition based on the hang up cause */
1448 switch (hangupcause) {
1449 case AST_CAUSE_BUSY:
1451 break;
1455 } else {
1457 }
1458 break;
1462 break;
1466 break;
1467 default:
1468 break;
1469 }
1470}
1471
1472/*!
1473 * \brief Finalize a CDR.
1474 *
1475 * This function is safe to call multiple times. Note that you can call this
1476 * explicitly before going to the finalized state if there's a chance the CDR
1477 * will be re-activated, in which case the \p cdr's end time should be
1478 * cleared. This function is implicitly called when a CDR transitions to the
1479 * finalized state and right before it is dispatched
1480 *
1481 * \param cdr The CDR to finalize
1482 */
1483static void cdr_object_finalize(struct cdr_object *cdr)
1484{
1485 if (!ast_tvzero(cdr->end)) {
1486 return;
1487 }
1488 cdr->end = cdr->lastevent;
1489
1490 if (cdr->disposition == AST_CDR_NULL) {
1491 if (!ast_tvzero(cdr->answer)) {
1493 } else if (cdr->party_a.snapshot->hangup->cause) {
1495 } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangup->cause) {
1497 } else {
1499 }
1500 }
1501
1502 /* tv_usec is suseconds_t, which could be int or long */
1503 ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dur %.3f bill %.3f dispo %s\n",
1504 cdr->party_a.snapshot->base->name,
1505 (long)cdr->start.tv_sec,
1506 (long)cdr->start.tv_usec,
1507 (long)cdr->answer.tv_sec,
1508 (long)cdr->answer.tv_usec,
1509 (long)cdr->end.tv_sec,
1510 (long)cdr->end.tv_usec,
1511 (double)ast_tvdiff_ms(cdr->end, cdr->start) / 1000.0,
1512 (double)ast_tvdiff_ms(cdr->end, cdr->answer) / 1000.0,
1514}
1515
1516/*!
1517 * \brief Check to see if a CDR needs to move to the finalized state because
1518 * its Party A hungup.
1519 */
1521{
1525 }
1526
1528 && cdr->fn_table != &finalized_state_fn_table) {
1530 }
1531}
1532
1533/*!
1534 * \brief Check to see if a CDR needs to be answered based on its Party A.
1535 * Note that this is safe to call as much as you want - we won't answer twice
1536 */
1538{
1539 if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
1540 cdr->answer = cdr->lastevent;
1541 /* tv_usec is suseconds_t, which could be int or long */
1542 CDR_DEBUG("%p - Set answered time to %ld.%06ld\n", cdr,
1543 (long)cdr->answer.tv_sec,
1544 (long)cdr->answer.tv_usec);
1545 }
1546}
1547
1548/*! \brief Set Caller ID information on a CDR */
1549static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
1550{
1551 if (!old_snapshot->snapshot) {
1552 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
1553 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
1554 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
1555 return;
1556 }
1557 if (strcmp(old_snapshot->snapshot->caller->dnid, new_snapshot->caller->dnid)) {
1558 set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
1559 }
1560 if (strcmp(old_snapshot->snapshot->caller->subaddr, new_snapshot->caller->subaddr)) {
1561 set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
1562 }
1563 if (strcmp(old_snapshot->snapshot->caller->dialed_subaddr, new_snapshot->caller->dialed_subaddr)) {
1564 set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
1565 }
1566}
1567
1568/*!
1569 * \brief Swap an old \ref cdr_object_snapshot's \ref ast_channel_snapshot for
1570 * a new \ref ast_channel_snapshot
1571 * \param old_snapshot The old \ref cdr_object_snapshot
1572 * \param new_snapshot The new \ref ast_channel_snapshot for old_snapshot
1573 */
1574static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot,
1575 struct ast_channel_snapshot *new_snapshot)
1576{
1577 cdr_object_update_cid(old_snapshot, new_snapshot);
1578 ao2_t_replace(old_snapshot->snapshot, new_snapshot, "Swap CDR shapshot");
1579}
1580
1581/* BASE METHOD IMPLEMENTATIONS */
1582
1583static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1584{
1585 ast_assert(strcasecmp(snapshot->base->name, cdr->party_a.snapshot->base->name) == 0);
1586
1587 /* Finalize the CDR if we're in hangup logic and we're set to do so */
1591 return 0;
1592 }
1593
1594 /*
1595 * Only record the context and extension if we aren't in a subroutine, or if
1596 * we are executing hangup logic.
1597 */
1600 if (strcmp(cdr->context, snapshot->dialplan->context)) {
1601 ast_string_field_set(cdr, context, snapshot->dialplan->context);
1602 }
1603 if (strcmp(cdr->exten, snapshot->dialplan->exten)) {
1604 ast_string_field_set(cdr, exten, snapshot->dialplan->exten);
1605 }
1606 }
1607
1608 cdr_object_swap_snapshot(&cdr->party_a, snapshot);
1609
1610 /* When Party A is originated to an application and the application exits, the stack
1611 * will attempt to clear the application and restore the dummy originate application
1612 * of "AppDialX". Prevent that, and any other application changes we might not want
1613 * here.
1614 */
1616 && !ast_strlen_zero(snapshot->dialplan->appl)
1617 && (strncasecmp(snapshot->dialplan->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))) {
1618 if (strcmp(cdr->appl, snapshot->dialplan->appl)) {
1619 ast_string_field_set(cdr, appl, snapshot->dialplan->appl);
1620 }
1621 if (strcmp(cdr->data, snapshot->dialplan->data)) {
1622 ast_string_field_set(cdr, data, snapshot->dialplan->data);
1623 }
1624
1625 /* Dial (app_dial) is a special case. Because pre-dial handlers, which
1626 * execute before the dial begins, will alter the application/data to
1627 * something people typically don't want to see, if we see a channel enter
1628 * into Dial here, we set the appl/data accordingly and lock it.
1629 */
1630 if (!strcmp(snapshot->dialplan->appl, "Dial")) {
1632 }
1633 }
1634
1635 if (strcmp(cdr->linkedid, snapshot->peer->linkedid)) {
1636 ast_string_field_set(cdr, linkedid, snapshot->peer->linkedid);
1637 }
1640
1641 return 0;
1642}
1643
1645{
1646 return 0;
1647}
1648
1649static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1650{
1651 return 0;
1652}
1653
1655{
1656 /* Base process bridge enter simply indicates that we can't handle it */
1657 return BRIDGE_ENTER_NEED_CDR;
1658}
1659
1660static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
1661{
1662 char park_info[128];
1663
1664 ast_assert(!strcasecmp(parking_info->parkee->base->name, cdr->party_a.snapshot->base->name));
1665
1666 /* Update Party A information regardless */
1667 cdr->fn_table->process_party_a(cdr, parking_info->parkee);
1668
1669 /* Fake out where we're parked */
1670 ast_string_field_set(cdr, appl, "Park");
1671 snprintf(park_info, sizeof(park_info), "%s:%u", parking_info->parkinglot, parking_info->parkingspace);
1672 ast_string_field_set(cdr, data, park_info);
1673
1674 /* Prevent any further changes to the App/Data fields for this record */
1676
1677 return 0;
1678}
1679
1680/* SINGLE STATE */
1681
1683{
1684 cdr->start = cdr->lastevent;
1686}
1687
1688static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1689{
1690 /* This should never happen! */
1692 ast_assert(0);
1693 return;
1694}
1695
1697{
1698 if (caller && !strcasecmp(cdr->party_a.snapshot->base->name, caller->base->name)) {
1699 base_process_party_a(cdr, caller);
1700 CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
1701 cdr->party_a.snapshot->base->name);
1702 cdr_object_swap_snapshot(&cdr->party_b, peer);
1703 cdr_all_relink(cdr);
1704 CDR_DEBUG("%p - Updated Party B %s snapshot\n", cdr,
1705 cdr->party_b.snapshot->base->name);
1706
1707 /* If we have two parties, lock the application that caused the
1708 * two parties to be associated. This prevents mid-call event
1709 * gosubs from perturbing the CDR application/data
1710 */
1712 } else if (!strcasecmp(cdr->party_a.snapshot->base->name, peer->base->name)) {
1713 /* We're the entity being dialed, i.e., outbound origination */
1714 base_process_party_a(cdr, peer);
1715 CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
1716 cdr->party_a.snapshot->base->name);
1717 }
1718
1720 return 0;
1721}
1722
1723/*!
1724 * \brief Handle a comparison between our \ref cdr_object and a \ref cdr_object
1725 * already in the bridge while in the Single state. The goal of this is to find
1726 * a Party B for our CDR.
1727 *
1728 * \param cdr Our \ref cdr_object in the Single state
1729 * \param cand_cdr The \ref cdr_object already in the Bridge state
1730 *
1731 * \retval 0 The cand_cdr had a Party A or Party B that we could use as our
1732 * Party B
1733 * \retval 1 No party in the cand_cdr could be used as our Party B
1734 */
1736 struct cdr_object *cand_cdr)
1737{
1738 struct cdr_object_snapshot *party_a;
1739
1740 /* Don't match on ourselves */
1741 if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
1742 return 1;
1743 }
1744
1745 /* Try the candidate CDR's Party A first */
1746 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
1747 if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1748 CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1749 cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name);
1750 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1751 cdr_all_relink(cdr);
1752 if (!cand_cdr->party_b.snapshot) {
1753 /* We just stole them - finalize their CDR. Note that this won't
1754 * transition their state, it just sets the end time and the
1755 * disposition - if we need to re-activate them later, we can.
1756 */
1757 cdr_object_finalize(cand_cdr);
1758 }
1759 return 0;
1760 }
1761
1762 /* Try their Party B, unless it's us */
1763 if (!cand_cdr->party_b.snapshot
1764 || !strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name)) {
1765 return 1;
1766 }
1767 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
1768 if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1769 CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1770 cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name);
1771 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
1772 cdr_all_relink(cdr);
1773 return 0;
1774 }
1775
1776 return 1;
1777}
1778
1780{
1781 struct ao2_iterator it_cdrs;
1782 char *channel_id;
1783 int success = 0;
1784
1785 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1786
1787 if (ao2_container_count(bridge->channels) == 1) {
1788 /* No one in the bridge yet but us! */
1791 }
1792
1793 for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
1794 !success && (channel_id = ao2_iterator_next(&it_cdrs));
1795 ao2_ref(channel_id, -1)) {
1796 struct cdr_object *cand_cdr_master;
1797 struct cdr_object *cand_cdr;
1798
1799 cand_cdr_master = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
1800 if (!cand_cdr_master) {
1801 continue;
1802 }
1803
1804 ao2_lock(cand_cdr_master);
1805 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1806 /* Skip any records that are not in a bridge or in this bridge.
1807 * I'm not sure how that would happen, but it pays to be careful. */
1808 if (cand_cdr->fn_table != &bridge_state_fn_table ||
1809 strcmp(cdr->bridge, cand_cdr->bridge)) {
1810 continue;
1811 }
1812
1813 if (single_state_bridge_enter_comparison(cdr, cand_cdr)) {
1814 continue;
1815 }
1816 /* We successfully got a party B - break out */
1817 success = 1;
1818 break;
1819 }
1820 ao2_unlock(cand_cdr_master);
1821 ao2_cleanup(cand_cdr_master);
1822 }
1823 ao2_iterator_destroy(&it_cdrs);
1824
1825 /* We always transition state, even if we didn't get a peer */
1827
1828 /* Success implies that we have a Party B */
1829 if (success) {
1831 }
1832
1834}
1835
1837{
1839 return 0;
1840}
1841
1842
1843/* DIAL STATE */
1844
1845static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1846{
1847 ast_assert(snapshot != NULL);
1849 && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
1850
1851 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1852
1853 /* If party B hangs up, finalize this CDR */
1856 }
1857}
1858
1859static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1860{
1861 /* Don't process a begin dial here. A party A already in the dial state will
1862 * who receives a dial begin for something else will be handled by the
1863 * message router callback and will add a new CDR for the party A */
1864 return 1;
1865}
1866
1867/*!
1868 * \internal
1869 * \brief Convert a dial status to a CDR disposition
1870 */
1871static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
1872{
1873 if (!strcmp(dial_status, "ANSWER")) {
1874 return AST_CDR_ANSWERED;
1875 } else if (!strcmp(dial_status, "BUSY")) {
1876 return AST_CDR_BUSY;
1877 } else if (!strcmp(dial_status, "CANCEL") || !strcmp(dial_status, "NOANSWER")) {
1878 return AST_CDR_NOANSWER;
1879 } else if (!strcmp(dial_status, "CONGESTION")) {
1881 return AST_CDR_FAILED;
1882 } else {
1883 return AST_CDR_CONGESTION;
1884 }
1885 } else if (!strcmp(dial_status, "FAILED")) {
1886 return AST_CDR_FAILED;
1887 }
1888 return AST_CDR_FAILED;
1889}
1890
1891static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1892{
1893 struct ast_channel_snapshot *party_a;
1894
1895 if (caller) {
1896 party_a = caller;
1897 } else {
1898 party_a = peer;
1899 }
1900 ast_assert(!strcasecmp(cdr->party_a.snapshot->base->name, party_a->base->name));
1901 cdr_object_swap_snapshot(&cdr->party_a, party_a);
1902
1903 if (cdr->party_b.snapshot) {
1904 if (strcasecmp(cdr->party_b.snapshot->base->name, peer->base->name)) {
1905 /* Not the status for this CDR - defer back to the message router */
1906 return 1;
1907 }
1909 }
1910
1911 /* Set the disposition based on the dial string. */
1912 cdr->disposition = dial_status_to_disposition(dial_status);
1913 if (cdr->disposition == AST_CDR_ANSWERED) {
1914 /* Switch to dial pending to wait and see what the caller does */
1916 } else {
1918 }
1919
1920 return 0;
1921}
1922
1924{
1925 int success = 0;
1926
1927 ast_string_field_set(cdr, bridge, bridge->uniqueid);
1928
1929 /* Get parties in the bridge */
1930 if (ao2_container_count(bridge->channels) == 1) {
1931 /* No one in the bridge yet but us! */
1934 }
1935
1936 /* If we don't have a Party B (originated channel), skip it */
1937 if (cdr->party_b.snapshot) {
1938 struct ao2_iterator it_cdrs;
1939 char *channel_id;
1940
1941 for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
1942 !success && (channel_id = ao2_iterator_next(&it_cdrs));
1943 ao2_ref(channel_id, -1)) {
1944 struct cdr_object *cand_cdr_master;
1945 struct cdr_object *cand_cdr;
1946
1947 cand_cdr_master = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
1948 if (!cand_cdr_master) {
1949 continue;
1950 }
1951
1952 ao2_lock(cand_cdr_master);
1953 for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1954 /* Skip any records that are not in a bridge or in this bridge.
1955 * I'm not sure how that would happen, but it pays to be careful. */
1956 if (cand_cdr->fn_table != &bridge_state_fn_table
1957 || strcmp(cdr->bridge, cand_cdr->bridge)) {
1958 continue;
1959 }
1960
1961 /* Skip any records that aren't our Party B */
1962 if (strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
1963 continue;
1964 }
1965 cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1966 /* If they have a Party B, they joined up with someone else as their
1967 * Party A. Don't finalize them as they're active. Otherwise, we
1968 * have stolen them so they need to be finalized.
1969 */
1970 if (!cand_cdr->party_b.snapshot) {
1971 cdr_object_finalize(cand_cdr);
1972 }
1973 success = 1;
1974 break;
1975 }
1976 ao2_unlock(cand_cdr_master);
1977 ao2_cleanup(cand_cdr_master);
1978 }
1979 ao2_iterator_destroy(&it_cdrs);
1980 }
1981
1982 /* We always transition state, even if we didn't get a peer */
1984
1985 /* Success implies that we have a Party B */
1986 if (success) {
1988 }
1990}
1991
1992/* DIALED PENDING STATE */
1993
1995{
1996 /* If we get a CEP change, we're executing dialplan. If we have a Party B
1997 * that means we need a new CDR; otherwise, switch us over to single.
1998 */
1999 if (snapshot_cep_changed(cdr->party_a.snapshot, snapshot)) {
2000 if (cdr->party_b.snapshot) {
2002 cdr->fn_table->process_party_a(cdr, snapshot);
2003 return 1;
2004 } else {
2005 /* The CDR does not need to be reinitialized when transitioning
2006 * to its single state as this would overwrite the start time,
2007 * causing potentially both the answer and the start time to be
2008 * the same which is incorrect.
2009 */
2011 cdr->fn_table->process_party_a(cdr, snapshot);
2012 return 0;
2013 }
2014 }
2015 base_process_party_a(cdr, snapshot);
2016 return 0;
2017}
2018
2020{
2022 return cdr->fn_table->process_bridge_enter(cdr, bridge, channel);
2023}
2024
2026{
2027 if (cdr->party_b.snapshot) {
2028 /* We can't handle this as we have a Party B - ask for a new one */
2029 return 1;
2030 }
2032 return 0;
2033}
2034
2036{
2038
2039 /* Ask for a new CDR */
2040 return 1;
2041}
2042
2043/* BRIDGE STATE */
2044
2045static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
2046{
2048 && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
2049
2050 cdr_object_swap_snapshot(&cdr->party_b, snapshot);
2051
2052 /* If party B hangs up, finalize this CDR */
2055 }
2056}
2057
2059{
2060 if (strcmp(cdr->bridge, bridge->uniqueid)) {
2061 return 1;
2062 }
2063 if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)
2064 && cdr->party_b.snapshot
2065 && strcasecmp(cdr->party_b.snapshot->base->name, channel->base->name)) {
2066 return 1;
2067 }
2069
2070 return 0;
2071}
2072
2073/* PARKED STATE */
2074
2076{
2077 if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)) {
2078 return 1;
2079 }
2081
2082 return 0;
2083}
2084
2085/* FINALIZED STATE */
2086
2088{
2090}
2091
2092static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
2093{
2096 return 0;
2097 }
2098
2099 /* Indicate that, if possible, we should get a new CDR */
2100 return 1;
2101}
2102
2103/*!
2104 * \internal
2105 * \brief Filter channel snapshots by technology
2106 */
2108{
2109 return snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL;
2110}
2111
2112/*!
2113 * \internal
2114 * \brief Filter a channel snapshot update
2115 */
2117 struct ast_channel_snapshot *new_snapshot)
2118{
2119 int ret = 0;
2120
2121 /* Drop cache updates from certain channel technologies */
2122 if (old_snapshot) {
2123 ret |= filter_channel_snapshot(old_snapshot);
2124 }
2125 if (new_snapshot) {
2126 ret |= filter_channel_snapshot(new_snapshot);
2127 }
2128
2129 return ret;
2130}
2131
2132static int dial_status_end(const char *dialstatus)
2133{
2134 return (strcmp(dialstatus, "RINGING") &&
2135 strcmp(dialstatus, "PROCEEDING") &&
2136 strcmp(dialstatus, "PROGRESS"));
2137}
2138
2139/* TOPIC ROUTER CALLBACKS */
2140
2141/*!
2142 * \brief Handler for Stasis-Core dial messages
2143 * \param data Passed on
2144 * \param sub The stasis subscription for this message callback
2145 * \param message The message
2146 */
2148{
2149 struct cdr_object *cdr;
2152 struct ast_channel_snapshot *peer;
2153 struct cdr_object *it_cdr;
2154 struct ast_json *dial_status_blob;
2155 const char *dial_status = NULL;
2156 int res = 1;
2157
2158 caller = ast_multi_channel_blob_get_channel(payload, "caller");
2159 peer = ast_multi_channel_blob_get_channel(payload, "peer");
2160 if (!peer && !caller) {
2161 return;
2162 }
2163
2164 if (peer && filter_channel_snapshot(peer)) {
2165 return;
2166 }
2167
2168 if (caller && filter_channel_snapshot(caller)) {
2169 return;
2170 }
2171
2172 dial_status_blob = ast_json_object_get(ast_multi_channel_blob_get_json(payload), "dialstatus");
2173 if (dial_status_blob) {
2174 dial_status = ast_json_string_get(dial_status_blob);
2175 }
2176
2177 CDR_DEBUG("Dial %s message for %s, %s: %u.%08u\n",
2178 ast_strlen_zero(dial_status) ? "Begin" : "End",
2179 caller ? caller->base->name : "(none)",
2180 peer ? peer->base->name : "(none)",
2181 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2182 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2183
2184 /* Figure out who is running this show */
2185 if (caller) {
2187 } else {
2189 }
2190 if (!cdr) {
2191 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->base->name : peer->base->name);
2192 ast_assert(0);
2193 return;
2194 }
2195
2196 ao2_lock(cdr);
2197 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2199 if (ast_strlen_zero(dial_status)) {
2200 if (!it_cdr->fn_table->process_dial_begin) {
2201 continue;
2202 }
2204 CDR_DEBUG("%p - Ignoring Dial Begin message\n", it_cdr);
2205 continue;
2206 }
2207 CDR_DEBUG("%p - Processing Dial Begin message for channel %s, peer %s\n",
2208 it_cdr,
2209 caller ? caller->base->name : "(none)",
2210 peer ? peer->base->name : "(none)");
2211 res &= it_cdr->fn_table->process_dial_begin(it_cdr,
2212 caller,
2213 peer);
2214 } else if (dial_status_end(dial_status)) {
2215 if (!it_cdr->fn_table->process_dial_end) {
2216 continue;
2217 }
2219 /* Set the disposition, and do nothing else. */
2220 it_cdr->disposition = dial_status_to_disposition(dial_status);
2221 CDR_DEBUG("%p - Setting disposition and that's it (%s)\n", it_cdr, dial_status);
2222 continue;
2223 }
2224 CDR_DEBUG("%p - Processing Dial End message for channel %s, peer %s\n",
2225 it_cdr,
2226 caller ? caller->base->name : "(none)",
2227 peer ? peer->base->name : "(none)");
2228 it_cdr->fn_table->process_dial_end(it_cdr,
2229 caller,
2230 peer,
2231 dial_status);
2232 }
2233 }
2234
2235 /* If we're ignoring dial changes, don't allow multiple CDRs for this channel. */
2236 if (!dial_changes_ignored) {
2237 /* If no CDR handled a dial begin message, make a new one */
2238 if (res && ast_strlen_zero(dial_status)) {
2239 struct cdr_object *new_cdr;
2240
2242 if (new_cdr) {
2243 new_cdr->fn_table->process_dial_begin(new_cdr, caller, peer);
2244 }
2245 }
2246 }
2247
2248 ao2_unlock(cdr);
2249 ao2_cleanup(cdr);
2250}
2251
2252static int cdr_object_finalize_party_b(void *obj, void *arg, void *data, int flags)
2253{
2254 struct cdr_object *cdr = obj;
2255
2256 if (!strcasecmp(cdr->party_b_name, arg)) {
2257#ifdef AST_DEVMODE
2258 struct ast_channel_snapshot *party_b = data;
2259
2260 /*
2261 * For sanity's sake we also assert the party_b snapshot
2262 * is consistent with the key.
2263 */
2265 && !strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name));
2266#endif
2267
2268 /* Don't transition to the finalized state - let the Party A do
2269 * that when its ready
2270 */
2272 }
2273 return 0;
2274}
2275
2276static int cdr_object_update_party_b(void *obj, void *arg, void *data, int flags)
2277{
2278 struct cdr_object *cdr = obj;
2279
2280 if (cdr->fn_table->process_party_b
2281 && !strcasecmp(cdr->party_b_name, arg)) {
2282 struct ast_channel_snapshot *party_b = data;
2283
2284 /*
2285 * For sanity's sake we also check the party_b snapshot
2286 * for consistency with the key. The callback needs and
2287 * asserts the snapshot to be this way.
2288 */
2289 if (!cdr->party_b.snapshot
2290 || strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name)) {
2292 "CDR for Party A %s(%s) has inconsistent Party B %s name. Message can be ignored but this shouldn't happen.\n",
2293 cdr->linkedid,
2294 cdr->party_a.snapshot->base->name,
2295 cdr->party_b_name);
2296 return 0;
2297 }
2298
2299 cdr->fn_table->process_party_b(cdr, party_b);
2300 }
2301 return 0;
2302}
2303
2304/*! \brief Determine if we need to add a new CDR based on snapshots */
2305static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot,
2306 struct ast_channel_snapshot *new_snapshot)
2307{
2308 /* If we're dead, we don't need a new CDR */
2309 if (!new_snapshot
2312 return 0;
2313 }
2314
2315 /* Auto-fall through will increment the priority but have no application */
2316 if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
2317 return 0;
2318 }
2319
2320 if (old_snapshot && !snapshot_cep_changed(old_snapshot, new_snapshot)) {
2321 return 0;
2322 }
2323
2324 return 1;
2325}
2326
2327/*!
2328 * \brief Handler for channel snapshot update messages
2329 * \param data Passed on
2330 * \param sub The stasis subscription for this message callback
2331 * \param message The message
2332 */
2334{
2335 struct cdr_object *cdr;
2337 struct cdr_object *it_cdr;
2338
2339 if (filter_channel_snapshot_message(update->old_snapshot, update->new_snapshot)) {
2340 return;
2341 }
2342
2343 if (update->new_snapshot && !update->old_snapshot) {
2344 struct module_config *mod_cfg = NULL;
2345
2347 if (!cdr) {
2348 return;
2349 }
2350 mod_cfg = ao2_global_obj_ref(module_configs);
2351 cdr->is_root = 1;
2353
2354 /* If CDR should be disabled unless enabled on a per-channel basis, then disable
2355 CDR, right from the get go */
2356 if (mod_cfg) {
2358 ast_debug(3, "Disable CDR by default\n");
2360 }
2361 ao2_cleanup(mod_cfg);
2362 }
2363 } else {
2364 cdr = ao2_find(active_cdrs_master, update->new_snapshot->base->uniqueid, OBJ_SEARCH_KEY);
2365 }
2366
2367 /* Handle Party A */
2368 if (!cdr) {
2369 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->base->name);
2370 ast_assert(0);
2371 } else {
2372 int all_reject = 1;
2373
2374 ao2_lock(cdr);
2375 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2377 if (!it_cdr->fn_table->process_party_a) {
2378 continue;
2379 }
2380 all_reject &= it_cdr->fn_table->process_party_a(it_cdr, update->new_snapshot);
2381 }
2382 if (all_reject && check_new_cdr_needed(update->old_snapshot, update->new_snapshot)) {
2383 /* We're not hung up and we have a new snapshot - we need a new CDR */
2384 struct cdr_object *new_cdr;
2385
2387 if (new_cdr) {
2388 new_cdr->fn_table->process_party_a(new_cdr, update->new_snapshot);
2389 }
2390 }
2391 ao2_unlock(cdr);
2392 }
2393
2394 if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2395 ao2_lock(cdr);
2396 CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->base->name);
2397 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2399 cdr_object_finalize(it_cdr);
2400 }
2402 ao2_unlock(cdr);
2403
2404 cdr_all_unlink(cdr);
2406 }
2407
2408 /* Handle Party B */
2409 if (update->new_snapshot) {
2411 cdr_object_update_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2412 }
2413
2414 if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2416 cdr_object_finalize_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2417 }
2418
2419 ao2_cleanup(cdr);
2420}
2421
2425 const struct timeval *lastevent;
2426};
2427
2428/*! \brief Callback used to notify CDRs of a Party B leaving the bridge */
2429static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, void *data, int flags)
2430{
2431 struct cdr_object *cdr = obj;
2432 struct bridge_leave_data *leave_data = data;
2433
2434 if (cdr->fn_table == &bridge_state_fn_table
2435 && !strcmp(cdr->bridge, leave_data->bridge->uniqueid)
2436 && !strcasecmp(cdr->party_b_name, arg)) {
2437 /*
2438 * For sanity's sake we also assert the party_b snapshot
2439 * is consistent with the key.
2440 */
2442 && !strcasecmp(cdr->party_b.snapshot->base->name, leave_data->channel->base->name));
2443
2444 /* It is our Party B, in our bridge. Set the last event and let the handler
2445 * transition our CDR appropriately when we leave the bridge.
2446 */
2447 cdr->lastevent = *leave_data->lastevent;
2449 }
2450 return 0;
2451}
2452
2453/*! \brief Filter bridge messages based on bridge technology */
2455{
2456 /* Ignore holding bridge technology messages. We treat this simply as an application
2457 * that a channel enters into.
2458 */
2459 if (!strcmp(bridge->technology, "holding_bridge") && strcmp(bridge->subclass, "parking")) {
2460 return 1;
2461 }
2462 return 0;
2463}
2464
2465/*!
2466 * \brief Handler for when a channel leaves a bridge
2467 * \param data Passed on
2468 * \param sub The stasis subscription for this message callback
2469 * \param message The message - hopefully a bridge one!
2470 */
2472 struct stasis_message *message)
2473{
2475 struct ast_bridge_snapshot *bridge = update->bridge;
2476 struct ast_channel_snapshot *channel = update->channel;
2477 struct cdr_object *cdr;
2478 struct cdr_object *it_cdr;
2479 struct bridge_leave_data leave_data = {
2480 .bridge = bridge,
2481 .channel = channel,
2482 .lastevent = stasis_message_timestamp(message)
2483 };
2484 int left_bridge = 0;
2485
2487 return;
2488 }
2489
2491 return;
2492 }
2493
2494 CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n",
2495 channel->base->name,
2496 (unsigned int)leave_data.lastevent->tv_sec,
2497 (unsigned int)leave_data.lastevent->tv_usec);
2498
2500 if (!cdr) {
2501 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2502 ast_assert(0);
2503 return;
2504 }
2505
2506 /* Party A */
2507 ao2_lock(cdr);
2508 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2509 it_cdr->lastevent = *leave_data.lastevent;
2510 if (!it_cdr->fn_table->process_bridge_leave) {
2511 continue;
2512 }
2513 CDR_DEBUG("%p - Processing Bridge Leave for %s\n",
2514 it_cdr, channel->base->name);
2515 if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
2516 ast_string_field_set(it_cdr, bridge, "");
2517 left_bridge = 1;
2518 }
2519 }
2520 ao2_unlock(cdr);
2521
2522 /* Party B */
2523 if (left_bridge
2524 && strcmp(bridge->subclass, "parking")) {
2526 cdr_object_party_b_left_bridge_cb, (char *) leave_data.channel->base->name,
2527 &leave_data);
2528 }
2529
2530 ao2_cleanup(cdr);
2531}
2532
2533/*!
2534 * \internal
2535 * \brief Create a new CDR, append it to an existing CDR, and update its snapshots
2536 *
2537 * \note The new CDR will be automatically transitioned to the bridge state
2538 */
2540 struct cdr_object_snapshot *party_b)
2541{
2542 struct cdr_object *new_cdr;
2543
2544 new_cdr = cdr_object_create_and_append(cdr, &cdr->lastevent);
2545 if (!new_cdr) {
2546 return;
2547 }
2549 cdr_all_relink(new_cdr);
2551 ast_string_field_set(new_cdr, bridge, cdr->bridge);
2553 CDR_DEBUG("%p - Party A %s has new Party B %s\n",
2554 new_cdr, new_cdr->party_a.snapshot->base->name,
2556}
2557
2558/*!
2559 * \brief Process a single \c bridge_candidate
2560 *
2561 * When a CDR enters a bridge, it needs to make pairings with everyone else
2562 * that it is not currently paired with. This function determines, for the
2563 * CDR for the channel that entered the bridge and the CDR for every other
2564 * channel currently in the bridge, who is Party A and makes new CDRs.
2565 *
2566 * \param cdr The \ref cdr_object being processed
2567 * \param base_cand_cdr The \ref cdr_object that is a candidate
2568 *
2569 */
2570static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
2571{
2572 struct cdr_object_snapshot *party_a;
2573 struct cdr_object *cand_cdr;
2574
2575 ao2_lock(base_cand_cdr);
2576
2577 for (cand_cdr = base_cand_cdr; cand_cdr; cand_cdr = cand_cdr->next) {
2578 /* Skip any records that are not in this bridge */
2579 if (strcmp(cand_cdr->bridge, cdr->bridge)) {
2580 continue;
2581 }
2582
2583 /* If the candidate is us or someone we've taken on, pass on by */
2584 if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)
2585 || (cdr->party_b.snapshot
2586 && !strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name))) {
2587 break;
2588 }
2589
2590 party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
2591 /* We're party A - make a new CDR, append it to us, and set the candidate as
2592 * Party B */
2593 if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2594 bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);
2595 break;
2596 }
2597
2598 /* We're Party B. Check if we can add ourselves immediately or if we need
2599 * a new CDR for them (they already have a Party B) */
2600 if (cand_cdr->party_b.snapshot
2601 && strcasecmp(cand_cdr->party_b.snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2602 bridge_candidate_add_to_cdr(cand_cdr, &cdr->party_a);
2603 } else {
2604 CDR_DEBUG("%p - Party A %s has new Party B %s\n",
2605 cand_cdr, cand_cdr->party_a.snapshot->base->name,
2606 cdr->party_a.snapshot->base->name);
2607 cdr_object_snapshot_copy(&cand_cdr->party_b, &cdr->party_a);
2608 cdr_all_relink(cand_cdr);
2609 /* It's possible that this joined at one point and was never chosen
2610 * as party A. Clear their end time, as it would be set in such a
2611 * case.
2612 */
2613 memset(&cand_cdr->end, 0, sizeof(cand_cdr->end));
2614 }
2615
2616 break;
2617 }
2618
2619 ao2_unlock(base_cand_cdr);
2620}
2621
2622/*!
2623 * \brief Handle creating bridge pairings for the \ref cdr_object that just
2624 * entered a bridge
2625 * \param cdr The \ref cdr_object that just entered the bridge
2626 * \param bridge The \ref ast_bridge_snapshot representing the bridge it just entered
2627 */
2629{
2630 struct ao2_iterator it_channels;
2631 char *channel_id;
2632
2633 it_channels = ao2_iterator_init(bridge->channels, 0);
2634 while ((channel_id = ao2_iterator_next(&it_channels))) {
2635 struct cdr_object *cand_cdr;
2636
2637 cand_cdr = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
2638 if (cand_cdr) {
2639 bridge_candidate_process(cdr, cand_cdr);
2640 ao2_ref(cand_cdr, -1);
2641 }
2642
2643 ao2_ref(channel_id, -1);
2644 }
2645 ao2_iterator_destroy(&it_channels);
2646}
2647
2648/*! \brief Handle entering into a parking bridge
2649 * \param cdr The CDR to operate on
2650 * \param bridge The bridge the channel just entered
2651 * \param channel The channel snapshot
2652 * \param event_time
2653 */
2656 struct ast_channel_snapshot *channel,
2657 const struct timeval *event_time)
2658{
2659 int res = 1;
2660 struct cdr_object *it_cdr;
2661 struct cdr_object *new_cdr;
2662
2663 ao2_lock(cdr);
2664
2665 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2666 it_cdr->lastevent = *event_time;
2667
2669 res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
2670 }
2671 if (it_cdr->fn_table->process_party_a) {
2672 CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2673 channel->base->name);
2674 it_cdr->fn_table->process_party_a(it_cdr, channel);
2675 }
2676 }
2677
2678 if (res) {
2679 /* No one handled it - we need a new one! */
2680 new_cdr = cdr_object_create_and_append(cdr, event_time);
2681 if (new_cdr) {
2682 /* Let the single state transition us to Parked */
2684 new_cdr->fn_table->process_parking_bridge_enter(new_cdr, bridge, channel);
2685 }
2686 }
2687 ao2_unlock(cdr);
2688}
2689
2690/*! \brief Handle a bridge enter message for a 'normal' bridge
2691 * \param cdr The CDR to operate on
2692 * \param bridge The bridge the channel just entered
2693 * \param channel The channel snapshot
2694 * \param event_time
2695 */
2698 struct ast_channel_snapshot *channel,
2699 const struct timeval *event_time)
2700{
2702 struct cdr_object *it_cdr;
2703 struct cdr_object *new_cdr;
2704 struct cdr_object *handled_cdr = NULL;
2705
2706 ao2_lock(cdr);
2707
2708try_again:
2709 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2710 it_cdr->lastevent = *event_time;
2711
2712 if (it_cdr->fn_table->process_party_a) {
2713 CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2714 channel->base->name);
2715 it_cdr->fn_table->process_party_a(it_cdr, channel);
2716 }
2717
2718 /* Notify all states that they have entered a bridge */
2719 if (it_cdr->fn_table->process_bridge_enter) {
2720 CDR_DEBUG("%p - Processing bridge enter for %s\n", it_cdr,
2721 channel->base->name);
2722 result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
2723 switch (result) {
2725 /* Fall through */
2727 if (!handled_cdr) {
2728 handled_cdr = it_cdr;
2729 }
2730 break;
2732 /* Pass */
2733 break;
2735 /* We didn't win on any - end this CDR. If someone else comes in later
2736 * that is Party B to this CDR, it can re-activate this CDR.
2737 */
2738 if (!handled_cdr) {
2739 handled_cdr = it_cdr;
2740 }
2742 break;
2743 }
2744 }
2745 }
2746
2747 /* Create the new matchings, but only for either:
2748 * * The first CDR in the chain that handled it. This avoids issues with
2749 * forked CDRs.
2750 * * If no one handled it, the last CDR in the chain. This would occur if
2751 * a CDR joined a bridge and it wasn't Party A for anyone. We still need
2752 * to make pairings with everyone in the bridge.
2753 */
2754 if (handled_cdr) {
2755 handle_bridge_pairings(handled_cdr, bridge);
2756 } else {
2757 /* Nothing handled it - we need a new one! */
2758 new_cdr = cdr_object_create_and_append(cdr, event_time);
2759 if (new_cdr) {
2760 /* This is guaranteed to succeed: the new CDR is created in the single state
2761 * and will be able to handle the bridge enter message
2762 */
2763 goto try_again;
2764 }
2765 }
2766 ao2_unlock(cdr);
2767}
2768
2769/*!
2770 * \internal
2771 * \brief Handler for Stasis-Core bridge enter messages
2772 * \param data Passed on
2773 * \param sub The stasis subscription for this message callback
2774 * \param message The message - hopefully a bridge one!
2775 */
2777 struct stasis_message *message)
2778{
2780 struct ast_bridge_snapshot *bridge = update->bridge;
2781 struct ast_channel_snapshot *channel = update->channel;
2782 struct cdr_object *cdr;
2783
2785 return;
2786 }
2787
2788 if (filter_channel_snapshot(channel)) {
2789 return;
2790 }
2791
2792 CDR_DEBUG("Bridge Enter message for channel %s: %u.%08u\n",
2793 channel->base->name,
2794 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2795 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2796
2798 if (!cdr) {
2799 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2800 ast_assert(0);
2801 return;
2802 }
2803
2804 if (!strcmp(bridge->subclass, "parking")) {
2806 } else {
2808 }
2809 ao2_cleanup(cdr);
2810}
2811
2812/*!
2813 * \brief Handler for when a channel is parked
2814 * \param data Passed on
2815 * \param sub The stasis subscription for this message callback
2816 * \param message The message about who got parked
2817 * */
2819 struct stasis_message *message)
2820{
2822 struct ast_channel_snapshot *channel = payload->parkee;
2823 struct cdr_object *cdr;
2824 int unhandled = 1;
2825 struct cdr_object *it_cdr;
2826
2827 /* Anything other than getting parked will be handled by other updates */
2828 if (payload->event_type != PARKED_CALL) {
2829 return;
2830 }
2831
2832 /* No one got parked? */
2833 if (!channel) {
2834 return;
2835 }
2836
2837 if (filter_channel_snapshot(channel)) {
2838 return;
2839 }
2840
2841 CDR_DEBUG("Parked Call message for channel %s: %u.%08u\n",
2842 channel->base->name,
2843 (unsigned int)stasis_message_timestamp(message)->tv_sec,
2844 (unsigned int)stasis_message_timestamp(message)->tv_usec);
2845
2847 if (!cdr) {
2848 ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2849 ast_assert(0);
2850 return;
2851 }
2852
2853 ao2_lock(cdr);
2854
2855 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2857 if (it_cdr->fn_table->process_parked_channel) {
2858 unhandled &= it_cdr->fn_table->process_parked_channel(it_cdr, payload);
2859 }
2860 }
2861
2862 if (unhandled) {
2863 /* Nothing handled the messgae - we need a new one! */
2864 struct cdr_object *new_cdr;
2865
2867 if (new_cdr) {
2868 /* As the new CDR is created in the single state, it is guaranteed
2869 * to have a function for the parked call message and will handle
2870 * the message */
2871 new_cdr->fn_table->process_parked_channel(new_cdr, payload);
2872 }
2873 }
2874
2875 ao2_unlock(cdr);
2876
2877 ao2_cleanup(cdr);
2878}
2879
2880/*!
2881 * \brief Handler for a synchronization message
2882 * \param data Passed on
2883 * \param sub The stasis subscription for this message callback
2884 * \param message A blank ao2 object
2885 * */
2887 struct stasis_message *message)
2888{
2889 return;
2890}
2891
2893{
2894 struct ast_cdr_config *general;
2895 struct module_config *mod_cfg;
2896
2897 mod_cfg = ao2_global_obj_ref(module_configs);
2898 if (!mod_cfg) {
2899 return NULL;
2900 }
2901 general = ao2_bump(mod_cfg->general);
2902 ao2_cleanup(mod_cfg);
2903 return general;
2904}
2905
2907{
2908 struct module_config *mod_cfg;
2909
2910 if (!config) {
2911 return;
2912 }
2913
2914 mod_cfg = ao2_global_obj_ref(module_configs);
2915 if (!mod_cfg) {
2916 return;
2917 }
2918
2919 ao2_replace(mod_cfg->general, config);
2920
2921 cdr_set_debug_mode(mod_cfg);
2923
2924 ao2_cleanup(mod_cfg);
2925}
2926
2928{
2930}
2931
2933{
2934 int success = -1;
2935 struct cdr_beitem *i = NULL;
2936
2938 AST_RWLIST_TRAVERSE(&be_list, i, list) {
2939 if (!strcasecmp(name, i->name)) {
2940 ast_debug(3, "Suspending CDR backend %s\n", i->name);
2941 i->suspended = 1;
2942 success = 0;
2943 }
2944 }
2946
2947 return success;
2948}
2949
2951{
2952 int success = -1;
2953 struct cdr_beitem *i = NULL;
2954
2956 AST_RWLIST_TRAVERSE(&be_list, i, list) {
2957 if (!strcasecmp(name, i->name)) {
2958 ast_debug(3, "Unsuspending CDR backend %s\n", i->name);
2959 i->suspended = 0;
2960 success = 0;
2961 }
2962 }
2964
2965 return success;
2966}
2967
2968static int cdr_generic_register(struct be_list *generic_list, const char *name, const char *desc, ast_cdrbe be)
2969{
2970 struct cdr_beitem *i;
2971 struct cdr_beitem *cur;
2972
2973 if (!name) {
2974 return -1;
2975 }
2976
2977 if (!be) {
2978 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
2979
2980 return -1;
2981 }
2982
2983 i = ast_calloc(1, sizeof(*i));
2984 if (!i) {
2985 return -1;
2986 }
2987
2988 i->be = be;
2989 ast_copy_string(i->name, name, sizeof(i->name));
2990 ast_copy_string(i->desc, desc, sizeof(i->desc));
2991
2992 AST_RWLIST_WRLOCK(generic_list);
2993 AST_RWLIST_TRAVERSE(generic_list, cur, list) {
2994 if (!strcasecmp(name, cur->name)) {
2995 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
2996 AST_RWLIST_UNLOCK(generic_list);
2997 ast_free(i);
2998
2999 return -1;
3000 }
3001 }
3002
3003 AST_RWLIST_INSERT_HEAD(generic_list, i, list);
3004 AST_RWLIST_UNLOCK(generic_list);
3005
3006 return 0;
3007}
3008
3009int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
3010{
3012}
3013
3014int ast_cdr_modifier_register(const char *name, const char *desc, ast_cdrbe be)
3015{
3016 return cdr_generic_register((struct be_list *)&mo_list, name, desc, be);
3017}
3018
3019static int ast_cdr_generic_unregister(struct be_list *generic_list, const char *name)
3020{
3021 struct cdr_beitem *match = NULL;
3022 int active_count;
3023
3024 AST_RWLIST_WRLOCK(generic_list);
3025 AST_RWLIST_TRAVERSE(generic_list, match, list) {
3026 if (!strcasecmp(name, match->name)) {
3027 break;
3028 }
3029 }
3030
3031 if (!match) {
3032 AST_RWLIST_UNLOCK(generic_list);
3033 return 0;
3034 }
3035
3037
3038 if (!match->suspended && active_count != 0) {
3039 AST_RWLIST_UNLOCK(generic_list);
3040 ast_log(AST_LOG_WARNING, "Unable to unregister CDR backend %s; %d CDRs are still active\n",
3041 name, active_count);
3042 return -1;
3043 }
3044
3045 AST_RWLIST_REMOVE(generic_list, match, list);
3046 AST_RWLIST_UNLOCK(generic_list);
3047
3048 ast_verb(5, "Unregistered '%s' CDR backend\n", name);
3049 ast_free(match);
3050
3051 return 0;
3052}
3053
3054int ast_cdr_unregister(const char *name)
3055{
3057}
3058
3060{
3061 return ast_cdr_generic_unregister((struct be_list *)&mo_list, name);
3062}
3063
3064struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
3065{
3066 struct ast_cdr *newcdr;
3067
3068 if (!cdr) {
3069 return NULL;
3070 }
3071 newcdr = ast_cdr_alloc();
3072 if (!newcdr) {
3073 return NULL;
3074 }
3075
3076 *newcdr = *cdr;
3078 copy_variables(&newcdr->varshead, &cdr->varshead);
3079 newcdr->next = NULL;
3080
3081 return newcdr;
3082}
3083
3084static const char *cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
3085{
3086 struct ast_var_t *variables;
3087
3088 if (ast_strlen_zero(name)) {
3089 return NULL;
3090 }
3091
3092 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
3093 if (!strcasecmp(name, ast_var_name(variables))) {
3094 return ast_var_value(variables);
3095 }
3096 }
3097
3098 return NULL;
3099}
3100
3101static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
3102{
3103 if (fmt == NULL) { /* raw mode */
3104 snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec);
3105 } else {
3106 buf[0] = '\0';/* Ensure the buffer is initialized. */
3107 if (when.tv_sec) {
3108 struct ast_tm tm;
3109
3110 ast_localtime(&when, &tm, NULL);
3111 ast_strftime(buf, bufsize, fmt, &tm);
3112 }
3113 }
3114}
3115
3116void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
3117{
3118 const char *fmt = "%Y-%m-%d %T";
3119 const char *varbuf;
3120
3121 if (!cdr) {
3122 return;
3123 }
3124
3125 *ret = NULL;
3126
3127 if (!strcasecmp(name, "clid")) {
3128 ast_copy_string(workspace, cdr->clid, workspacelen);
3129 } else if (!strcasecmp(name, "src")) {
3130 ast_copy_string(workspace, cdr->src, workspacelen);
3131 } else if (!strcasecmp(name, "dst")) {
3132 ast_copy_string(workspace, cdr->dst, workspacelen);
3133 } else if (!strcasecmp(name, "dcontext")) {
3134 ast_copy_string(workspace, cdr->dcontext, workspacelen);
3135 } else if (!strcasecmp(name, "channel")) {
3136 ast_copy_string(workspace, cdr->channel, workspacelen);
3137 } else if (!strcasecmp(name, "dstchannel")) {
3138 ast_copy_string(workspace, cdr->dstchannel, workspacelen);
3139 } else if (!strcasecmp(name, "lastapp")) {
3140 ast_copy_string(workspace, cdr->lastapp, workspacelen);
3141 } else if (!strcasecmp(name, "lastdata")) {
3142 ast_copy_string(workspace, cdr->lastdata, workspacelen);
3143 } else if (!strcasecmp(name, "start")) {
3144 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
3145 } else if (!strcasecmp(name, "answer")) {
3146 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
3147 } else if (!strcasecmp(name, "end")) {
3148 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
3149 } else if (!strcasecmp(name, "duration")) {
3150 snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
3151 } else if (!strcasecmp(name, "billsec")) {
3152 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);
3153 } else if (!strcasecmp(name, "disposition")) {
3154 if (raw) {
3155 snprintf(workspace, workspacelen, "%ld", cdr->disposition);
3156 } else {
3157 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
3158 }
3159 } else if (!strcasecmp(name, "amaflags")) {
3160 if (raw) {
3161 snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
3162 } else {
3163 ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
3164 }
3165 } else if (!strcasecmp(name, "accountcode")) {
3166 ast_copy_string(workspace, cdr->accountcode, workspacelen);
3167 } else if (!strcasecmp(name, "peeraccount")) {
3168 ast_copy_string(workspace, cdr->peeraccount, workspacelen);
3169 } else if (!strcasecmp(name, "uniqueid")) {
3170 ast_copy_string(workspace, cdr->uniqueid, workspacelen);
3171 } else if (!strcasecmp(name, "linkedid")) {
3172 ast_copy_string(workspace, cdr->linkedid, workspacelen);
3173 } else if (!strcasecmp(name, "tenantid")) {
3174 ast_copy_string(workspace, cdr->tenantid, workspacelen);
3175 } else if (!strcasecmp(name, "peertenantid")) {
3176 ast_copy_string(workspace, cdr->peertenantid, workspacelen);
3177 } else if (!strcasecmp(name, "userfield")) {
3178 ast_copy_string(workspace, cdr->userfield, workspacelen);
3179 } else if (!strcasecmp(name, "sequence")) {
3180 snprintf(workspace, workspacelen, "%d", cdr->sequence);
3181 } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
3182 ast_copy_string(workspace, varbuf, workspacelen);
3183 } else {
3184 workspace[0] = '\0';
3185 }
3186
3187 if (!ast_strlen_zero(workspace)) {
3188 *ret = workspace;
3189 }
3190}
3191
3192/*!
3193 * \internal
3194 * \brief Callback that finds all CDRs that reference a particular channel by name
3195 */
3196static int cdr_object_select_all_by_name_cb(void *obj, void *arg, int flags)
3197{
3198 struct cdr_object *cdr = obj;
3199 const char *name = arg;
3200
3201 if (!strcasecmp(cdr->party_a.snapshot->base->name, name) ||
3202 (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->base->name, name))) {
3203 return CMP_MATCH;
3204 }
3205 return 0;
3206}
3207
3208/*!
3209 * \internal
3210 * \brief Callback that finds a CDR by channel name
3211 */
3212static int cdr_object_get_by_name_cb(void *obj, void *arg, int flags)
3213{
3214 struct cdr_object *cdr = obj;
3215 const char *name = arg;
3216
3217 if (!strcasecmp(cdr->party_a.snapshot->base->name, name)) {
3218 return CMP_MATCH;
3219 }
3220 return 0;
3221}
3222
3223/* Read Only CDR variables */
3224static const char * const cdr_readonly_vars[] = {
3225 "clid",
3226 "src",
3227 "dst",
3228 "dcontext",
3229 "channel",
3230 "dstchannel",
3231 "lastapp",
3232 "lastdata",
3233 "start",
3234 "answer",
3235 "end",
3236 "duration",
3237 "billsec",
3238 "disposition",
3239 "amaflags",
3240 "accountcode",
3241 "uniqueid",
3242 "linkedid",
3243 "tenantid",
3244 "userfield",
3245 "sequence",
3246 NULL
3247};
3248
3249int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
3250{
3251 struct cdr_object *cdr;
3252 struct cdr_object *it_cdr;
3253 struct ao2_iterator *it_cdrs;
3254 char *arg = ast_strdupa(channel_name);
3255 int x;
3256
3257 for (x = 0; cdr_readonly_vars[x]; x++) {
3258 if (!strcasecmp(name, cdr_readonly_vars[x])) {
3259 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
3260 return -1;
3261 }
3262 }
3263
3265 if (!it_cdrs) {
3266 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3267 return -1;
3268 }
3269
3270 for (; (cdr = ao2_iterator_next(it_cdrs)); ao2_unlock(cdr), ao2_cleanup(cdr)) {
3271 ao2_lock(cdr);
3272 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3273 struct varshead *headp = NULL;
3274
3275 if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3276 continue;
3277 }
3278 if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->base->name)) {
3279 headp = &it_cdr->party_a.variables;
3280 } else if (it_cdr->party_b.snapshot
3281 && !strcasecmp(channel_name, it_cdr->party_b.snapshot->base->name)) {
3282 headp = &it_cdr->party_b.variables;
3283 }
3284 if (headp) {
3285 set_variable(headp, name, value);
3286 }
3287 }
3288 }
3289 ao2_iterator_destroy(it_cdrs);
3290
3291 return 0;
3292}
3293
3294/*!
3295 * \brief Format a variable on a \ref cdr_object
3296 */
3297static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
3298{
3299 struct ast_var_t *variable;
3300
3301 AST_LIST_TRAVERSE(&cdr->party_a.variables, variable, entries) {
3302 if (!strcasecmp(name, ast_var_name(variable))) {
3303 ast_copy_string(value, ast_var_value(variable), length);
3304 return;
3305 }
3306 }
3307
3308 *value = '\0';
3309}
3310
3311/*!
3312 * \brief Format one of the standard properties on a \ref cdr_object
3313 */
3314static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
3315{
3316 struct ast_channel_snapshot *party_a = cdr_obj->party_a.snapshot;
3317 struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;
3318
3319 if (!strcasecmp(name, "clid")) {
3320 ast_callerid_merge(value, length, party_a->caller->name, party_a->caller->number, "");
3321 } else if (!strcasecmp(name, "src")) {
3322 ast_copy_string(value, party_a->caller->number, length);
3323 } else if (!strcasecmp(name, "dst")) {
3324 ast_copy_string(value, party_a->dialplan->exten, length);
3325 } else if (!strcasecmp(name, "dcontext")) {
3326 ast_copy_string(value, party_a->dialplan->context, length);
3327 } else if (!strcasecmp(name, "channel")) {
3328 ast_copy_string(value, party_a->base->name, length);
3329 } else if (!strcasecmp(name, "dstchannel")) {
3330 if (party_b) {
3331 ast_copy_string(value, party_b->base->name, length);
3332 } else {
3333 ast_copy_string(value, "", length);
3334 }
3335 } else if (!strcasecmp(name, "lastapp")) {
3336 ast_copy_string(value, party_a->dialplan->appl, length);
3337 } else if (!strcasecmp(name, "lastdata")) {
3338 ast_copy_string(value, party_a->dialplan->data, length);
3339 } else if (!strcasecmp(name, "start")) {
3340 cdr_get_tv(cdr_obj->start, NULL, value, length);
3341 } else if (!strcasecmp(name, "answer")) {
3342 cdr_get_tv(cdr_obj->answer, NULL, value, length);
3343 } else if (!strcasecmp(name, "end")) {
3344 cdr_get_tv(cdr_obj->end, NULL, value, length);
3345 } else if (!strcasecmp(name, "duration")) {
3346 snprintf(value, length, "%ld", cdr_object_get_duration(cdr_obj));
3347 } else if (!strcasecmp(name, "billsec")) {
3348 snprintf(value, length, "%ld", cdr_object_get_billsec(cdr_obj));
3349 } else if (!strcasecmp(name, "disposition")) {
3350 snprintf(value, length, "%u", cdr_obj->disposition);
3351 } else if (!strcasecmp(name, "amaflags")) {
3352 snprintf(value, length, "%d", party_a->amaflags);
3353 } else if (!strcasecmp(name, "accountcode")) {
3354 ast_copy_string(value, party_a->base->accountcode, length);
3355 } else if (!strcasecmp(name, "peeraccount")) {
3356 if (party_b) {
3357 ast_copy_string(value, party_b->base->accountcode, length);
3358 } else {
3359 ast_copy_string(value, "", length);
3360 }
3361 } else if (!strcasecmp(name, "uniqueid")) {
3362 ast_copy_string(value, party_a->base->uniqueid, length);
3363 } else if (!strcasecmp(name, "linkedid")) {
3364 ast_copy_string(value, cdr_obj->linkedid, length);
3365 } else if (!strcasecmp(name, "tenantid")) {
3366 ast_copy_string(value, party_a->base->tenantid, length);
3367 } else if (!strcasecmp(name, "peertenantid")) {
3368 if (party_b) {
3369 ast_copy_string(value, party_b->base->tenantid, length);
3370 } else {
3371 ast_copy_string(value, "", length);
3372 }
3373 } else if (!strcasecmp(name, "userfield")) {
3374 ast_copy_string(value, cdr_obj->party_a.userfield, length);
3375 } else if (!strcasecmp(name, "sequence")) {
3376 snprintf(value, length, "%u", cdr_obj->sequence);
3377 } else {
3378 return 1;
3379 }
3380
3381 return 0;
3382}
3383
3384/*! \internal
3385 * \brief Look up and retrieve a CDR object by channel name
3386 * \param name The name of the channel
3387 * \retval NULL on error
3388 * \return The \ref cdr_object for the channel on success, with the reference
3389 * count bumped by one.
3390 */
3391static struct cdr_object *cdr_object_get_by_name(const char *name)
3392{
3393 char *param;
3394
3395 if (ast_strlen_zero(name)) {
3396 return NULL;
3397 }
3398
3399 param = ast_strdupa(name);
3401}
3402
3403int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
3404{
3405 struct cdr_object *cdr;
3406 struct cdr_object *cdr_obj;
3407
3408 if (ast_strlen_zero(name)) {
3409 return 1;
3410 }
3411
3412 cdr = cdr_object_get_by_name(channel_name);
3413 if (!cdr) {
3414 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3415 return 1;
3416 }
3417
3418 ao2_lock(cdr);
3419
3420 cdr_obj = cdr->last;
3421 if (cdr_object_format_property(cdr_obj, name, value, length)) {
3422 /* Property failed; attempt variable */
3423 cdr_object_format_var_internal(cdr_obj, name, value, length);
3424 }
3425
3426 ao2_unlock(cdr);
3427
3428 ao2_cleanup(cdr);
3429 return 0;
3430}
3431
3432int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
3433{
3434 struct cdr_object *cdr;
3435 struct cdr_object *it_cdr;
3436 struct ast_var_t *variable;
3437 const char *var;
3438 char workspace[256];
3439 int total = 0, x = 0, i;
3440
3441 cdr = cdr_object_get_by_name(channel_name);
3442 if (!cdr) {
3444 ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3445 }
3446 return 0;
3447 }
3448
3450
3451 ao2_lock(cdr);
3452 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3453 if (++x > 1) {
3454 ast_str_append(buf, 0, "\n");
3455 }
3456
3457 AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
3458 if (!(var = ast_var_name(variable))) {
3459 continue;
3460 }
3461
3462 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
3463 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3464 break;
3465 }
3466
3467 total++;
3468 }
3469
3470 for (i = 0; cdr_readonly_vars[i]; i++) {
3471 if (cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace))) {
3472 /* Unhandled read-only CDR variable. */
3473 ast_assert(0);
3474 continue;
3475 }
3476
3477 if (!ast_strlen_zero(workspace)
3478 && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
3479 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3480 break;
3481 }
3482 total++;
3483 }
3484 }
3485 ao2_unlock(cdr);
3486 ao2_cleanup(cdr);
3487 return total;
3488}
3489
3490void ast_cdr_free(struct ast_cdr *cdr)
3491{
3492 while (cdr) {
3493 struct ast_cdr *next = cdr->next;
3494
3495 free_variables(&cdr->varshead);
3496 ast_free(cdr);
3497 cdr = next;
3498 }
3499}
3500
3502{
3503 struct ast_cdr *x;
3504
3505 x = ast_calloc(1, sizeof(*x));
3506 return x;
3507}
3508
3510{
3511 switch (disposition) {
3512 case AST_CDR_NULL:
3513 return "NO ANSWER"; /* by default, for backward compatibility */
3514 case AST_CDR_NOANSWER:
3515 return "NO ANSWER";
3516 case AST_CDR_FAILED:
3517 return "FAILED";
3518 case AST_CDR_BUSY:
3519 return "BUSY";
3520 case AST_CDR_ANSWERED:
3521 return "ANSWERED";
3522 case AST_CDR_CONGESTION:
3523 return "CONGESTION";
3524 }
3525 return "UNKNOWN";
3526}
3527
3529 const char *channel_name;
3530 const char *userfield;
3531};
3532
3533/*! \brief Callback used to update the userfield on Party B on all CDRs */
3534static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, void *data, int flags)
3535{
3536 struct cdr_object *cdr = obj;
3537
3538 if ((cdr->fn_table != &finalized_state_fn_table || !cdr->next)
3539 && !strcasecmp(cdr->party_b_name, arg)) {
3540 struct party_b_userfield_update *info = data;
3541
3542 /*
3543 * For sanity's sake we also assert the party_b snapshot
3544 * is consistent with the key.
3545 */
3547 && !strcasecmp(cdr->party_b.snapshot->base->name, info->channel_name));
3548
3549 ast_copy_string(cdr->party_b.userfield, info->userfield,
3550 sizeof(cdr->party_b.userfield));
3551 }
3552
3553 return 0;
3554}
3555
3556void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
3557{
3558 struct cdr_object *cdr;
3559 struct party_b_userfield_update party_b_info = {
3561 .userfield = userfield,
3562 };
3563 struct cdr_object *it_cdr;
3564
3565 /* Handle Party A */
3566 cdr = cdr_object_get_by_name(channel_name);
3567 if (cdr) {
3568 ao2_lock(cdr);
3569 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3570 if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3571 continue;
3572 }
3573 ast_copy_string(it_cdr->party_a.userfield, userfield,
3574 sizeof(it_cdr->party_a.userfield));
3575 }
3576 ao2_unlock(cdr);
3577 }
3578
3579 /* Handle Party B */
3582 &party_b_info);
3583
3584 ao2_cleanup(cdr);
3585}
3586
3587static void post_cdr(struct ast_cdr *cdr)
3588{
3589 struct module_config *mod_cfg;
3590 struct cdr_beitem *i;
3591
3592 mod_cfg = ao2_global_obj_ref(module_configs);
3593 if (!mod_cfg) {
3594 return;
3595 }
3596
3597 for (; cdr ; cdr = cdr->next) {
3598 /* For people, who don't want to see unanswered single-channel events */
3599 if (!ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) &&
3602 ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel);
3603 continue;
3604 }
3605
3606 /* Modify CDR's */
3608 AST_RWLIST_TRAVERSE(&mo_list, i, list) {
3609 i->be(cdr);
3610 }
3612
3614 continue;
3615 }
3617 AST_RWLIST_TRAVERSE(&be_list, i, list) {
3618 if (!i->suspended) {
3619 i->be(cdr);
3620 }
3621 }
3623 }
3624 ao2_cleanup(mod_cfg);
3625}
3626
3627int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
3628{
3629 struct cdr_object *cdr;
3630 struct cdr_object *it_cdr;
3631
3632 cdr = cdr_object_get_by_name(channel_name);
3633 if (!cdr) {
3634 return -1;
3635 }
3636
3637 ao2_lock(cdr);
3638 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3639 if (it_cdr->fn_table == &finalized_state_fn_table) {
3640 continue;
3641 }
3642 /* Note: in general, set the flags on both the CDR record as well as the
3643 * Party A. Sometimes all we have is the Party A to look at.
3644 */
3645 ast_set_flag(&it_cdr->flags, option);
3646 ast_set_flag(&it_cdr->party_a, option);
3647 }
3648 ao2_unlock(cdr);
3649
3650 ao2_cleanup(cdr);
3651 return 0;
3652}
3653
3654int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
3655{
3656 struct cdr_object *cdr;
3657 struct cdr_object *it_cdr;
3658
3659 cdr = cdr_object_get_by_name(channel_name);
3660 if (!cdr) {
3661 return -1;
3662 }
3663
3664 ao2_lock(cdr);
3665 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3666 if (it_cdr->fn_table == &finalized_state_fn_table) {
3667 continue;
3668 }
3669 ast_clear_flag(&it_cdr->flags, option);
3670 }
3671 ao2_unlock(cdr);
3672
3673 ao2_cleanup(cdr);
3674 return 0;
3675}
3676
3677int ast_cdr_reset(const char *channel_name, int keep_variables)
3678{
3679 struct cdr_object *cdr;
3680 struct ast_var_t *vardata;
3681 struct cdr_object *it_cdr;
3682
3683 cdr = cdr_object_get_by_name(channel_name);
3684 if (!cdr) {
3685 return -1;
3686 }
3687
3688 ao2_lock(cdr);
3689 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3690 /* clear variables */
3691 if (!keep_variables) {
3692 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
3693 ast_var_delete(vardata);
3694 }
3695 if (cdr->party_b.snapshot) {
3696 while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
3697 ast_var_delete(vardata);
3698 }
3699 }
3700 }
3701
3702 /* Reset to initial state */
3703 memset(&it_cdr->start, 0, sizeof(it_cdr->start));
3704 memset(&it_cdr->end, 0, sizeof(it_cdr->end));
3705 memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
3706 it_cdr->start = ast_tvnow();
3707 it_cdr->lastevent = it_cdr->start;
3709 }
3710 ao2_unlock(cdr);
3711
3712 ao2_cleanup(cdr);
3713 return 0;
3714}
3715
3716int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
3717{
3718 RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3719 struct cdr_object *new_cdr;
3720 struct cdr_object *it_cdr;
3721 struct cdr_object *cdr_obj;
3722
3723 if (!cdr) {
3724 return -1;
3725 }
3726
3727 {
3728 SCOPED_AO2LOCK(lock, cdr);
3729 struct timeval now = ast_tvnow();
3730
3731 cdr_obj = cdr->last;
3732 if (cdr_obj->fn_table == &finalized_state_fn_table) {
3733 /* If the last CDR in the chain is finalized, don't allow a fork -
3734 * things are already dying at this point
3735 */
3736 return -1;
3737 }
3738
3739 /* Copy over the basic CDR information. The Party A information is
3740 * copied over automatically as part of the append
3741 */
3742 ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->base->name);
3743 new_cdr = cdr_object_create_and_append(cdr, &now);
3744 if (!new_cdr) {
3745 return -1;
3746 }
3747 new_cdr->fn_table = cdr_obj->fn_table;
3748 ast_string_field_set(new_cdr, bridge, cdr->bridge);
3749 ast_string_field_set(new_cdr, appl, cdr->appl);
3750 ast_string_field_set(new_cdr, data, cdr->data);
3751 ast_string_field_set(new_cdr, context, cdr->context);
3752 ast_string_field_set(new_cdr, exten, cdr->exten);
3753 new_cdr->flags = cdr->flags;
3754 /* Explicitly clear the AST_CDR_LOCK_APP flag - we want
3755 * the application to be changed on the new CDR if the
3756 * dialplan demands it
3757 */
3759
3760 /* If there's a Party B, copy it over as well */
3761 if (cdr_obj->party_b.snapshot) {
3762 new_cdr->party_b.snapshot = cdr_obj->party_b.snapshot;
3763 ao2_ref(new_cdr->party_b.snapshot, +1);
3764 cdr_all_relink(new_cdr);
3765 strcpy(new_cdr->party_b.userfield, cdr_obj->party_b.userfield);
3766 new_cdr->party_b.flags = cdr_obj->party_b.flags;
3768 copy_variables(&new_cdr->party_b.variables, &cdr_obj->party_b.variables);
3769 }
3770 }
3771 new_cdr->start = cdr_obj->start;
3772 new_cdr->answer = cdr_obj->answer;
3773 new_cdr->lastevent = ast_tvnow();
3774
3775 /* Modify the times based on the flags passed in */
3777 && new_cdr->party_a.snapshot->state == AST_STATE_UP) {
3778 new_cdr->answer = ast_tvnow();
3779 }
3781 new_cdr->answer = ast_tvnow();
3782 new_cdr->start = ast_tvnow();
3783 }
3784
3785 /* Create and append, by default, copies over the variables */
3787 free_variables(&new_cdr->party_a.variables);
3788 }
3789
3790 /* Finalize any current CDRs */
3792 for (it_cdr = cdr; it_cdr != new_cdr; it_cdr = it_cdr->next) {
3793 if (it_cdr->fn_table == &finalized_state_fn_table) {
3794 continue;
3795 }
3796 /* Force finalization on the CDR. This will bypass any checks for
3797 * end before 'h' extension.
3798 */
3799 cdr_object_finalize(it_cdr);
3801 }
3802 }
3803 }
3804
3805 return 0;
3806}
3807
3808/*! \note Don't call without cdr_batch_lock */
3809static void reset_batch(void)
3810{
3811 batch->size = 0;
3812 batch->head = NULL;
3813 batch->tail = NULL;
3814}
3815
3816/*! \note Don't call without cdr_batch_lock */
3817static int init_batch(void)
3818{
3819 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
3820 if (!(batch = ast_malloc(sizeof(*batch))))
3821 return -1;
3822
3823 reset_batch();
3824
3825 return 0;
3826}
3827
3828static void *do_batch_backend_process(void *data)
3829{
3830 struct cdr_batch_item *processeditem;
3831 struct cdr_batch_item *batchitem = data;
3832
3833 /* Push each CDR into storage mechanism(s) and free all the memory */
3834 while (batchitem) {
3835 post_cdr(batchitem->cdr);
3836 ast_cdr_free(batchitem->cdr);
3837 processeditem = batchitem;
3838 batchitem = batchitem->next;
3839 ast_free(processeditem);
3840 }
3841
3842 return NULL;
3843}
3844
3845static void cdr_submit_batch(int do_shutdown)
3846{
3847 struct module_config *mod_cfg;
3848 struct cdr_batch_item *oldbatchitems = NULL;
3849 pthread_t batch_post_thread = AST_PTHREADT_NULL;
3850
3851 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
3852 if (!batch || !batch->head) {
3853 return;
3854 }
3855
3856 /* move the old CDRs aside, and prepare a new CDR batch */
3858 oldbatchitems = batch->head;
3859 reset_batch();
3861
3862 mod_cfg = ao2_global_obj_ref(module_configs);
3863
3864 /* if configured, spawn a new thread to post these CDRs,
3865 also try to save as much as possible if we are shutting down safely */
3866 if (!mod_cfg
3868 || do_shutdown) {
3869 ast_debug(1, "CDR single-threaded batch processing begins now\n");
3870 do_batch_backend_process(oldbatchitems);
3871 } else {
3872 if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
3873 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
3874 do_batch_backend_process(oldbatchitems);
3875 } else {
3876 ast_debug(1, "CDR multi-threaded batch processing begins now\n");
3877 }
3878 }
3879
3880 ao2_cleanup(mod_cfg);
3881}
3882
3883static int submit_scheduled_batch(const void *data)
3884{
3885 struct module_config *mod_cfg;
3886 int nextms;
3887
3889
3890 mod_cfg = ao2_global_obj_ref(module_configs);
3891 if (!mod_cfg) {
3892 return 0;
3893 }
3894
3895 /* Calculate the next scheduled interval */
3896 nextms = mod_cfg->general->batch_settings.time * 1000;
3897
3898 ao2_cleanup(mod_cfg);
3899
3900 return nextms;
3901}
3902
3903/*! Do not hold the batch lock while calling this function */
3904static void start_batch_mode(void)
3905{
3906 /* Prevent two deletes from happening at the same time */
3908 /* this is okay since we are not being called from within the scheduler */
3910 /* schedule the submission to occur ASAP (1 ms) */
3913
3914 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
3918}
3919
3920static void cdr_detach(struct ast_cdr *cdr)
3921{
3922 struct cdr_batch_item *newtail;
3923 int curr;
3924 RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3925 int submit_batch = 0;
3926
3927 if (!cdr) {
3928 return;
3929 }
3930
3931 /* maybe they disabled CDR stuff completely, so just drop it */
3932 if (!mod_cfg || !ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
3933 ast_debug(1, "Dropping CDR !\n");
3935 return;
3936 }
3937
3938 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
3939 if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
3940 post_cdr(cdr);
3942 return;
3943 }
3944
3945 /* otherwise, each CDR gets put into a batch list (at the end) */
3946 ast_debug(1, "CDR detaching from this thread\n");
3947
3948 /* we'll need a new tail for every CDR */
3949 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
3950 post_cdr(cdr);
3952 return;
3953 }
3954
3955 /* don't traverse a whole list (just keep track of the tail) */
3957 if (!batch)
3958 init_batch();
3959 if (!batch->head) {
3960 /* new batch is empty, so point the head at the new tail */
3961 batch->head = newtail;
3962 } else {
3963 /* already got a batch with something in it, so just append a new tail */
3964 batch->tail->next = newtail;
3965 }
3966 newtail->cdr = cdr;
3967 batch->tail = newtail;
3968 curr = batch->size++;
3969
3970 /* if we have enough stuff to post, then do it */
3971 if (curr >= (mod_cfg->general->batch_settings.size - 1)) {
3972 submit_batch = 1;
3973 }
3975
3976 /* Don't submit a batch with cdr_batch_lock held */
3977 if (submit_batch) {
3979 }
3980}
3981
3982static void *do_cdr(void *data)
3983{
3984 struct timespec timeout;
3985 int schedms;
3986 int numevents = 0;
3987
3988 for (;;) {
3989 struct timeval now;
3990 schedms = ast_sched_wait(sched);
3991 /* this shouldn't happen, but provide a 1 second default just in case */
3992 if (schedms < 0)
3993 schedms = 1000;
3994 now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
3995 timeout.tv_sec = now.tv_sec;
3996 timeout.tv_nsec = now.tv_usec * 1000;
3997 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
4000 numevents = ast_sched_runq(sched);
4002 ast_debug(2, "Processed %d CDR batches from the run queue\n", numevents);
4003 }
4004
4005 return NULL;
4006}
4007
4008static char *handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4009{
4010 struct module_config *mod_cfg;
4011
4012 switch (cmd) {
4013 case CLI_INIT:
4014 e->command = "cdr set debug [on|off]";
4015 e->usage = "Enable or disable extra debugging in the CDR Engine. Note\n"
4016 "that this will dump debug information to the VERBOSE setting\n"
4017 "and should only be used when debugging information from the\n"
4018 "CDR engine is needed.\n";
4019 return NULL;
4020 case CLI_GENERATE:
4021 return NULL;
4022 }
4023
4024 if (a->argc != 4) {
4025 return CLI_SHOWUSAGE;
4026 }
4027
4028 mod_cfg = ao2_global_obj_ref(module_configs);
4029 if (!mod_cfg) {
4030 ast_cli(a->fd, "Could not set CDR debugging mode\n");
4031 return CLI_SUCCESS;
4032 }
4033 if (!strcasecmp(a->argv[3], "on")
4034 && !ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
4036 ast_cli(a->fd, "CDR debugging enabled\n");
4037 } else if (!strcasecmp(a->argv[3], "off")
4038 && ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
4040 ast_cli(a->fd, "CDR debugging disabled\n");
4041 }
4042 cdr_set_debug_mode(mod_cfg);
4043 ao2_cleanup(mod_cfg);
4044
4045 return CLI_SUCCESS;
4046}
4047
4048/*! \brief Complete user input for 'cdr show' */
4049static char *cli_complete_show(struct ast_cli_args *a)
4050{
4051 int wordlen = strlen(a->word);
4052 struct ao2_iterator it_cdrs;
4053 struct cdr_object *cdr;
4054
4056 while ((cdr = ao2_iterator_next(&it_cdrs))) {
4057 if (!strncasecmp(a->word, cdr->party_a.snapshot->base->name, wordlen)) {
4059 ao2_ref(cdr, -1);
4060 break;
4061 }
4062 }
4063 ao2_ref(cdr, -1);
4064 }
4065 ao2_iterator_destroy(&it_cdrs);
4066
4067 return NULL;
4068}
4069
4071{
4072 struct ao2_iterator it_cdrs;
4073 struct cdr_object *cdr;
4074 char start_time_buffer[64];
4075 char answer_time_buffer[64];
4076 char end_time_buffer[64];
4077
4078#define TITLE_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
4079#define FORMAT_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
4080
4081 ast_cli(a->fd, "\n");
4082 ast_cli(a->fd, "Channels with Call Detail Record (CDR) Information\n");
4083 ast_cli(a->fd, "--------------------------------------------------\n");
4084 ast_cli(a->fd, TITLE_STRING, "Channel", "Dst. Channel", "LastApp", "Start", "Answer", "End", "Billsec", "Duration");
4085
4087 for (; (cdr = ao2_iterator_next(&it_cdrs)); ao2_cleanup(cdr)) {
4088 struct cdr_object *it_cdr;
4089 struct timeval start_time = { 0, };
4090 struct timeval answer_time = { 0, };
4091 struct timeval end_time = { 0, };
4092
4093 SCOPED_AO2LOCK(lock, cdr);
4094
4095 /* Calculate the start, end, answer, billsec, and duration over the
4096 * life of all of the CDR entries
4097 */
4098 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4099 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
4100 continue;
4101 }
4102 if (ast_tvzero(start_time)) {
4103 start_time = it_cdr->start;
4104 }
4105 if (!ast_tvzero(it_cdr->answer) && ast_tvzero(answer_time)) {
4106 answer_time = it_cdr->answer;
4107 }
4108 }
4109
4110 /* If there was no start time, then all CDRs were for a dialed channel; skip */
4111 if (ast_tvzero(start_time)) {
4112 continue;
4113 }
4114 it_cdr = cdr->last;
4115
4116 end_time = ast_tvzero(it_cdr->end) ? ast_tvnow() : it_cdr->end;
4117 cdr_get_tv(start_time, "%T", start_time_buffer, sizeof(start_time_buffer));
4118 cdr_get_tv(answer_time, "%T", answer_time_buffer, sizeof(answer_time_buffer));
4119 cdr_get_tv(end_time, "%T", end_time_buffer, sizeof(end_time_buffer));
4121 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
4122 it_cdr->appl,
4123 start_time_buffer,
4124 answer_time_buffer,
4125 end_time_buffer,
4126 ast_tvzero(answer_time) ? 0 : (long)ast_tvdiff_ms(end_time, answer_time) / 1000,
4127 (long)ast_tvdiff_ms(end_time, start_time) / 1000);
4128 }
4129 ao2_iterator_destroy(&it_cdrs);
4130#undef FORMAT_STRING
4131#undef TITLE_STRING
4132}
4133
4134static void cli_show_channel(struct ast_cli_args *a)
4135{
4136 struct cdr_object *it_cdr;
4137 char clid[64];
4138 char start_time_buffer[64];
4139 char answer_time_buffer[64];
4140 char end_time_buffer[64];
4141 const char *channel_name = a->argv[3];
4142 struct cdr_object *cdr;
4143
4144#define TITLE_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
4145#define FORMAT_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
4146
4147 cdr = cdr_object_get_by_name(channel_name);
4148 if (!cdr) {
4149 ast_cli(a->fd, "Unknown channel: %s\n", channel_name);
4150 return;
4151 }
4152
4153 ast_cli(a->fd, "\n");
4154 ast_cli(a->fd, "Call Detail Record (CDR) Information for %s\n", channel_name);
4155 ast_cli(a->fd, "--------------------------------------------------\n");
4156 ast_cli(a->fd, TITLE_STRING, "AccountCode", "CallerID", "Dst. Channel", "LastApp", "Data", "Start", "Answer", "End", "Billsec", "Duration");
4157
4158 ao2_lock(cdr);
4159 for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4160 struct timeval end;
4161
4162 if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
4163 continue;
4164 }
4165 ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller->name, it_cdr->party_a.snapshot->caller->number, "");
4166 if (ast_tvzero(it_cdr->end)) {
4167 end = ast_tvnow();
4168 } else {
4169 end = it_cdr->end;
4170 }
4171 cdr_get_tv(it_cdr->start, "%T", start_time_buffer, sizeof(start_time_buffer));
4172 cdr_get_tv(it_cdr->answer, "%T", answer_time_buffer, sizeof(answer_time_buffer));
4173 cdr_get_tv(end, "%T", end_time_buffer, sizeof(end_time_buffer));
4174 ast_cli(a->fd, FORMAT_STRING,
4175 it_cdr->party_a.snapshot->base->accountcode,
4176 clid,
4177 it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
4178 it_cdr->appl,
4179 it_cdr->data,
4180 start_time_buffer,
4181 answer_time_buffer,
4182 end_time_buffer,
4183 (long)ast_tvdiff_ms(end, it_cdr->answer) / 1000,
4184 (long)ast_tvdiff_ms(end, it_cdr->start) / 1000);
4185 }
4186 ao2_unlock(cdr);
4187
4188 ao2_cleanup(cdr);
4189
4190#undef FORMAT_STRING
4191#undef TITLE_STRING
4192}
4193
4194static char *handle_cli_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4195{
4196 switch (cmd) {
4197 case CLI_INIT:
4198 e->command = "cdr show active";
4199 e->usage =
4200 "Usage: cdr show active [channel]\n"
4201 " Displays a summary of all Call Detail Records when [channel]\n"
4202 " is omitted; displays all of the Call Detail Records\n"
4203 " currently in flight for a given [channel] when [channel] is\n"
4204 " specified.\n\n"
4205 " Note that this will not display Call Detail Records that\n"
4206 " have already been dispatched to a backend storage, nor for\n"
4207 " channels that are no longer active.\n";
4208 return NULL;
4209 case CLI_GENERATE:
4210 return cli_complete_show(a);
4211 }
4212
4213 if (a->argc > 4) {
4214 return CLI_SHOWUSAGE;
4215 } else if (a->argc < 4) {
4217 } else {
4219 }
4220
4221 return CLI_SUCCESS;
4222}
4223
4224static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4225{
4226 struct cdr_beitem *beitem = NULL;
4227 struct module_config *mod_cfg;
4228 int cnt = 0;
4229 long nextbatchtime = 0;
4230
4231 switch (cmd) {
4232 case CLI_INIT:
4233 e->command = "cdr show status";
4234 e->usage =
4235 "Usage: cdr show status\n"
4236 " Displays the Call Detail Record engine system status.\n";
4237 return NULL;
4238 case CLI_GENERATE:
4239 return NULL;
4240 }
4241
4242 if (a->argc > 3) {
4243 return CLI_SHOWUSAGE;
4244 }
4245
4246 mod_cfg = ao2_global_obj_ref(module_configs);
4247 if (!mod_cfg) {
4248 return CLI_FAILURE;
4249 }
4250
4251 ast_cli(a->fd, "\n");
4252 ast_cli(a->fd, "Call Detail Record (CDR) settings\n");
4253 ast_cli(a->fd, "----------------------------------\n");
4254 ast_cli(a->fd, " Logging: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED) ? "Enabled" : "Disabled");
4255 ast_cli(a->fd, " Mode: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE) ? "Batch" : "Simple");
4256 if (ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4257 ast_cli(a->fd, " Log calls by default: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_CHANNEL_DEFAULT_ENABLED) ? "Yes" : "No");
4258 ast_cli(a->fd, " Log unanswered calls: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) ? "Yes" : "No");
4259 ast_cli(a->fd, " Log congestion: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION) ? "Yes" : "No");
4260 ast_cli(a->fd, " Ignore bridging changes: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_STATE_CHANGES) ? "Yes" : "No");
4261 ast_cli(a->fd, " Ignore dial state changes: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_DIAL_CHANGES) ? "Yes" : "No");
4262 if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4263 ast_cli(a->fd, "* Batch Mode Settings\n");
4264 ast_cli(a->fd, " -------------------\n");
4265 if (batch)
4266 cnt = batch->size;
4267 if (cdr_sched > -1)
4268 nextbatchtime = ast_sched_when(sched, cdr_sched);
4269 ast_cli(a->fd, " Safe shutdown: %s\n", ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SAFE_SHUTDOWN) ? "Enabled" : "Disabled");
4270 ast_cli(a->fd, " Threading model: %s\n", ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SCHEDULER_ONLY) ? "Scheduler only" : "Scheduler plus separate threads");
4271 ast_cli(a->fd, " Current batch size: %d record%s\n", cnt, ESS(cnt));
4272 ast_cli(a->fd, " Maximum batch size: %u record%s\n", mod_cfg->general->batch_settings.size, ESS(mod_cfg->general->batch_settings.size));
4273 ast_cli(a->fd, " Maximum batch time: %u second%s\n", mod_cfg->general->batch_settings.time, ESS(mod_cfg->general->batch_settings.time));
4274 ast_cli(a->fd, " Next batch processing time: %ld second%s\n\n", nextbatchtime, ESS(nextbatchtime));
4275 }
4276 ast_cli(a->fd, "* Registered Backends\n");
4277 ast_cli(a->fd, " -------------------\n");
4279 if (AST_RWLIST_EMPTY(&be_list)) {