Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
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"
58 #include "asterisk/linkedlists.h"
59 #include "asterisk/utils.h"
60 #include "asterisk/sched.h"
61 #include "asterisk/config.h"
62 #include "asterisk/cli.h"
63 #include "asterisk/stringfields.h"
65 #include "asterisk/json.h"
66 #include "asterisk/parking.h"
67 #include "asterisk/stasis.h"
71 #include "asterisk/astobj2.h"
72 #include "asterisk/taskprocessor.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">
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. Default is "yes".</para>
97  </description>
98  </configOption>
99  <configOption name="unanswered">
100  <synopsis>Log calls that are never answered and don't set an outgoing party.</synopsis>
101  <description><para>
102  Define whether or not to log unanswered calls that don't involve an outgoing party. Setting
103  this to "yes" will make calls to extensions that don't answer and don't set a side B channel
104  (such as by using the Dial application) receive CDR log entries. If this option is set to
105  "no", then those log entries will not be created. Unanswered calls which get offered to an
106  outgoing line will always receive log entries regardless of this option, and that is the
107  intended behavior.
108  </para>
109  </description>
110  </configOption>
111  <configOption name="congestion">
112  <synopsis>Log congested calls.</synopsis>
113  <description><para>Define whether or not to log congested calls. Setting this to "yes" will
114  report each call that fails to complete due to congestion conditions.</para>
115  </description>
116  </configOption>
117  <configOption name="endbeforehexten">
118  <synopsis>Don't produce CDRs while executing hangup logic</synopsis>
119  <description>
120  <para>As each CDR for a channel is finished, its end time is updated
121  and the CDR is finalized. When a channel is hung up and hangup
122  logic is present (in the form of a hangup handler or the
123  <literal>h</literal> extension), a new CDR is generated for the
124  channel. Any statistics are gathered from this new CDR. By enabling
125  this option, no new CDR is created for the dialplan logic that is
126  executed in <literal>h</literal> extensions or attached hangup handler
127  subroutines. The default value is <literal>yes</literal>, indicating
128  that a CDR will be generated during hangup logic.</para>
129  </description>
130  </configOption>
131  <configOption name="initiatedseconds">
132  <synopsis>Count microseconds for billsec purposes</synopsis>
133  <description><para>Normally, the <literal>billsec</literal> field logged to the CDR backends
134  is simply the end time (hangup time) minus the answer time in seconds. Internally,
135  asterisk stores the time in terms of microseconds and seconds. By setting
136  initiatedseconds to <literal>yes</literal>, you can force asterisk to report any seconds
137  that were initiated (a sort of round up method). Technically, this is
138  when the microsecond part of the end time is greater than the microsecond
139  part of the answer time, then the billsec time is incremented one second.</para>
140  </description>
141  </configOption>
142  <configOption name="batch">
143  <synopsis>Submit CDRs to the backends for processing in batches</synopsis>
144  <description><para>Define the CDR batch mode, where instead of posting the CDR at the end of
145  every call, the data will be stored in a buffer to help alleviate load on the
146  asterisk server.</para>
147  <warning><para>Use of batch mode may result in data loss after unsafe asterisk termination,
148  i.e., software crash, power failure, kill -9, etc.</para>
149  </warning>
150  </description>
151  </configOption>
152  <configOption name="size">
153  <synopsis>The maximum number of CDRs to accumulate before triggering a batch</synopsis>
154  <description><para>Define the maximum number of CDRs to accumulate in the buffer before posting
155  them to the backend engines. batch must be set to <literal>yes</literal>.</para>
156  </description>
157  </configOption>
158  <configOption name="time">
159  <synopsis>The maximum time to accumulate CDRs before triggering a batch</synopsis>
160  <description><para>Define the maximum time to accumulate CDRs before posting them in a batch to the
161  backend engines. If this time limit is reached, then it will post the records, regardless of the value
162  defined for size. batch must be set to <literal>yes</literal>.</para>
163  <note><para>Time is expressed in seconds.</para></note>
164  </description>
165  </configOption>
166  <configOption name="scheduleronly">
167  <synopsis>Post batched CDRs on their own thread instead of the scheduler</synopsis>
168  <description><para>The CDR engine uses the internal asterisk scheduler to determine when to post
169  records. Posting can either occur inside the scheduler thread, or a new
170  thread can be spawned for the submission of every batch. For small batches,
171  it might be acceptable to just use the scheduler thread, so set this to <literal>yes</literal>.
172  For large batches, say anything over size=10, a new thread is recommended, so
173  set this to <literal>no</literal>.</para>
174  </description>
175  </configOption>
176  <configOption name="safeshutdown">
177  <synopsis>Block shutdown of Asterisk until CDRs are submitted</synopsis>
178  <description><para>When shutting down asterisk, you can block until the CDRs are submitted. If
179  you don't, then data will likely be lost. You can always check the size of
180  the CDR batch buffer with the CLI <astcli>cdr status</astcli> command. To enable blocking on
181  submission of CDR data during asterisk shutdown, set this to <literal>yes</literal>.</para>
182  </description>
183  </configOption>
184  </configObject>
185  </configFile>
186  </configInfo>
187  ***/
188 
189 #define DEFAULT_ENABLED "1"
190 #define DEFAULT_BATCHMODE "0"
191 #define DEFAULT_UNANSWERED "0"
192 #define DEFAULT_CONGESTION "0"
193 #define DEFAULT_END_BEFORE_H_EXTEN "1"
194 #define DEFAULT_INITIATED_SECONDS "0"
195 
196 #define DEFAULT_BATCH_SIZE "100"
197 #define MAX_BATCH_SIZE 1000
198 #define DEFAULT_BATCH_TIME "300"
199 #define MAX_BATCH_TIME 86400
200 #define DEFAULT_BATCH_SCHEDULER_ONLY "0"
201 #define DEFAULT_BATCH_SAFE_SHUTDOWN "1"
202 
203 #define cdr_set_debug_mode(mod_cfg) \
204  do { \
205  cdr_debug_enabled = ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG); \
206  } while (0)
207 
208 static int cdr_debug_enabled;
209 
210 #define CDR_DEBUG(fmt, ...) \
211  do { \
212  if (cdr_debug_enabled) { \
213  ast_verbose((fmt), ##__VA_ARGS__); \
214  } \
215  } while (0)
216 
217 static void cdr_detach(struct ast_cdr *cdr);
218 static void cdr_submit_batch(int shutdown);
219 static int cdr_toggle_runtime_options(void);
220 
221 /*! \brief The configuration settings for this module */
223  struct ast_cdr_config *general; /*!< CDR global settings */
224 };
225 
226 /*! \brief The container for the module configuration */
227 static AO2_GLOBAL_OBJ_STATIC(module_configs);
228 
229 /*! \brief The type definition for general options */
230 static struct aco_type general_option = {
231  .type = ACO_GLOBAL,
232  .name = "general",
233  .item_offset = offsetof(struct module_config, general),
234  .category = "general",
235  .category_match = ACO_WHITELIST_EXACT,
236 };
237 
238 /*! Config sections used by existing modules. Do not add to this list. */
239 static const char *ignore_categories[] = {
240  "csv",
241  "custom",
242  "manager",
243  "odbc",
244  "pgsql",
245  "radius",
246  "sqlite",
247  "tds",
248  "mysql",
249  NULL,
250 };
251 
252 static struct aco_type ignore_option = {
253  .type = ACO_IGNORE,
254  .name = "modules",
255  .category = (const char*)ignore_categories,
257 };
258 
259 static void *module_config_alloc(void);
260 static void module_config_destructor(void *obj);
261 static void module_config_post_apply(void);
262 
263 /*! \brief The file definition */
264 static struct aco_file module_file_conf = {
265  .filename = "cdr.conf",
266  .types = ACO_TYPES(&general_option, &ignore_option),
267 };
268 
269 CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc,
270  .files = ACO_FILES(&module_file_conf),
271  .post_apply_config = module_config_post_apply,
272 );
273 
274 static struct aco_type *general_options[] = ACO_TYPES(&general_option);
275 
276 static void module_config_post_apply(void)
277 {
278  struct module_config *mod_cfg;
279 
280  mod_cfg = ao2_global_obj_ref(module_configs);
281  if (!mod_cfg) {
282  return;
283  }
284  cdr_set_debug_mode(mod_cfg);
285  ao2_cleanup(mod_cfg);
286 }
287 
288 /*! \brief Dispose of a module config object */
289 static void module_config_destructor(void *obj)
290 {
291  struct module_config *cfg = obj;
292 
293  if (!cfg) {
294  return;
295  }
296  ao2_ref(cfg->general, -1);
297 }
298 
299 /*! \brief Create a new module config object */
300 static void *module_config_alloc(void)
301 {
302  struct module_config *mod_cfg;
303  struct ast_cdr_config *cdr_config;
304 
305  mod_cfg = ao2_alloc(sizeof(*mod_cfg), module_config_destructor);
306  if (!mod_cfg) {
307  return NULL;
308  }
309 
310  cdr_config = ao2_alloc(sizeof(*cdr_config), NULL);
311  if (!cdr_config) {
312  ao2_ref(cdr_config, -1);
313  return NULL;
314  }
315  mod_cfg->general = cdr_config;
316 
317  return mod_cfg;
318 }
319 
320 /*! \brief Registration object for CDR backends */
321 struct cdr_beitem {
322  char name[20];
323  char desc[80];
326  int suspended:1;
327 };
328 
329 /*! \brief List of registered backends */
331 
332 /*! \brief List of registered modifiers */
334 
335 /*! \brief Queued CDR waiting to be batched */
337  struct ast_cdr *cdr;
339 };
340 
341 /*! \brief The actual batch queue */
342 static struct cdr_batch {
343  int size;
346 } *batch = NULL;
347 
348 /*! \brief The global sequence counter used for CDRs */
349 static int global_cdr_sequence = 0;
350 
351 /*! \brief Scheduler items */
352 static struct ast_sched_context *sched;
353 static int cdr_sched = -1;
355 static pthread_t cdr_thread = AST_PTHREADT_NULL;
356 
357 /*! \brief Lock protecting modifications to the batch queue */
359 
360 /*! \brief These are used to wake up the CDR thread when there's work to do */
363 
364 /*! \brief A container of the active master CDRs indexed by Party A channel uniqueid */
366 
367 /*! \brief A container of all active CDRs with a Party B indexed by Party B channel name */
369 
370 /*! \brief Message router for stasis messages regarding channel state */
372 
373 /*! \brief Our subscription for bridges */
375 
376 /*! \brief Our subscription for channels */
378 
379 /*! \brief Our subscription for parking */
381 
382 /*! \brief The parent topic for all topics we want to aggregate for CDRs */
383 static struct stasis_topic *cdr_topic;
384 
385 /*! \brief A message type used to synchronize with the CDR topic */
386 STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_sync_message_type);
387 
388 struct cdr_object;
389 
390 /*! \brief Return types for \ref process_bridge_enter functions */
392  /*!
393  * The CDR was the only party in the bridge.
394  */
396  /*!
397  * The CDR was able to obtain a Party B from some other party already in the bridge
398  */
400  /*!
401  * The CDR was not able to obtain a Party B
402  */
404  /*!
405  * This CDR can't handle a bridge enter message and a new CDR needs to be created
406  */
408 };
409 
410 /*!
411  * \brief A virtual table used for \ref cdr_object.
412  *
413  * Note that all functions are optional - if a subclass does not need an
414  * implementation, it is safe to leave it NULL.
415  */
417  /*! \brief Name of the subclass */
418  const char *name;
419 
420  /*!
421  * \brief An initialization function. This will be called automatically
422  * when a \ref cdr_object is switched to this type in
423  * \ref cdr_object_transition_state
424  *
425  * \param cdr The \ref cdr_object that was just transitioned
426  */
427  void (* const init_function)(struct cdr_object *cdr);
428 
429  /*!
430  * \brief Process a Party A update for the \ref cdr_object
431  *
432  * \param cdr The \ref cdr_object to process the update
433  * \param snapshot The snapshot for the CDR's Party A
434  * \retval 0 the CDR handled the update or ignored it
435  * \retval 1 the CDR is finalized and a new one should be made to handle it
436  */
437  int (* const process_party_a)(struct cdr_object *cdr,
438  struct ast_channel_snapshot *snapshot);
439 
440  /*!
441  * \brief Process a Party B update for the \ref cdr_object
442  *
443  * \param cdr The \ref cdr_object to process the update
444  * \param snapshot The snapshot for the CDR's Party B
445  */
446  void (* const process_party_b)(struct cdr_object *cdr,
447  struct ast_channel_snapshot *snapshot);
448 
449  /*!
450  * \brief Process the beginning of a dial. A dial message implies one of two
451  * things:
452  * The \ref cdr_object's Party A has been originated
453  * The \ref cdr_object's Party A is dialing its Party B
454  *
455  * \param cdr The \ref cdr_object
456  * \param caller The originator of the dial attempt
457  * \param peer The destination of the dial attempt
458  *
459  * \retval 0 if the parties in the dial were handled by this CDR
460  * \retval 1 if the parties could not be handled by this CDR
461  */
462  int (* const process_dial_begin)(struct cdr_object *cdr,
464  struct ast_channel_snapshot *peer);
465 
466  /*!
467  * \brief Process the end of a dial. At the end of a dial, a CDR can be
468  * transitioned into one of two states - DialedPending
469  * (\ref dialed_pending_state_fn_table) or Finalized
470  * (\ref finalized_state_fn_table).
471  *
472  * \param cdr The \ref cdr_object
473  * \param caller The originator of the dial attempt
474  * \param peer the Destination of the dial attempt
475  * \param dial_status What happened
476  *
477  * \retval 0 if the parties in the dial were handled by this CDR
478  * \retval 1 if the parties could not be handled by this CDR
479  */
480  int (* const process_dial_end)(struct cdr_object *cdr,
482  struct ast_channel_snapshot *peer,
483  const char *dial_status);
484 
485  /*!
486  * \brief Process the entering of a bridge by this CDR. The purpose of this
487  * callback is to have the CDR prepare itself for the bridge and attempt to
488  * find a valid Party B. The act of creating new CDRs based on the entering
489  * of this channel into the bridge is handled by the higher level message
490  * handler.
491  *
492  * Note that this handler is for when a channel enters into a "normal"
493  * bridge, where people actually talk to each other. Parking is its own
494  * thing.
495  *
496  * \param cdr The \ref cdr_object
497  * \param bridge The bridge that the Party A just entered into
498  * \param channel The \ref ast_channel_snapshot for this CDR's Party A
499  *
500  * \retval process_bridge_enter_results Defines whether or not this CDR was able
501  * to fully handle the bridge enter message.
502  */
503  enum process_bridge_enter_results (* const process_bridge_enter)(
504  struct cdr_object *cdr,
505  struct ast_bridge_snapshot *bridge,
506  struct ast_channel_snapshot *channel);
507 
508  /*!
509  * \brief Process entering into a parking bridge.
510  *
511  * \param cdr The \ref cdr_object
512  * \param bridge The parking bridge that Party A just entered into
513  * \param channel The \ref ast_channel_snapshot for this CDR's Party A
514  *
515  * \retval 0 This CDR successfully transitioned itself into the parked state
516  * \retval 1 This CDR couldn't handle the parking transition and we need a
517  * new CDR.
518  */
519  int (* const process_parking_bridge_enter)(struct cdr_object *cdr,
520  struct ast_bridge_snapshot *bridge,
521  struct ast_channel_snapshot *channel);
522 
523  /*!
524  * \brief Process the leaving of a bridge by this CDR.
525  *
526  * \param cdr The \ref cdr_object
527  * \param bridge The bridge that the Party A just left
528  * \param channel The \ref ast_channel_snapshot for this CDR's Party A
529  *
530  * \retval 0 This CDR left successfully
531  * \retval 1 Error
532  */
533  int (* const process_bridge_leave)(struct cdr_object *cdr,
534  struct ast_bridge_snapshot *bridge,
535  struct ast_channel_snapshot *channel);
536 
537  /*!
538  * \brief Process an update informing us that the channel got itself parked
539  *
540  * \param cdr The \ref cdr_object
541  * \param channel The parking information for this CDR's party A
542  *
543  * \retval 0 This CDR successfully parked itself
544  * \retval 1 This CDR couldn't handle the park
545  */
546  int (* const process_parked_channel)(struct cdr_object *cdr,
547  struct ast_parked_call_payload *parking_info);
548 };
549 
550 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
552 static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
553 static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
554 static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info);
555 
556 static void single_state_init_function(struct cdr_object *cdr);
557 static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
558 static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
561 
562 /*!
563  * \brief The virtual table for the Single state.
564  *
565  * A \ref cdr_object starts off in this state. This represents a channel that
566  * has no Party B information itself.
567  *
568  * A \ref cdr_object from this state can go into any of the following states:
569  * * \ref dial_state_fn_table
570  * * \ref bridge_state_fn_table
571  * * \ref finalized_state_fn_table
572  */
574  .name = "Single",
575  .init_function = single_state_init_function,
576  .process_party_a = base_process_party_a,
577  .process_party_b = single_state_process_party_b,
578  .process_dial_begin = single_state_process_dial_begin,
579  .process_dial_end = base_process_dial_end,
580  .process_bridge_enter = single_state_process_bridge_enter,
581  .process_parking_bridge_enter = single_state_process_parking_bridge_enter,
582  .process_bridge_leave = base_process_bridge_leave,
583  .process_parked_channel = base_process_parked_channel,
584 };
585 
586 static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
587 static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
588 static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status);
590 
591 /*!
592  * \brief The virtual table for the Dial state.
593  *
594  * A \ref cdr_object that has begun a dial operation. This state is entered when
595  * the Party A for a CDR is determined to be dialing out to a Party B or when
596  * a CDR is for an originated channel (in which case the Party A information is
597  * the originated channel, and there is no Party B).
598  *
599  * A \ref cdr_object from this state can go in any of the following states:
600  * * \ref dialed_pending_state_fn_table
601  * * \ref bridge_state_fn_table
602  * * \ref finalized_state_fn_table
603  */
605  .name = "Dial",
606  .process_party_a = base_process_party_a,
607  .process_party_b = dial_state_process_party_b,
608  .process_dial_begin = dial_state_process_dial_begin,
609  .process_dial_end = dial_state_process_dial_end,
610  .process_bridge_enter = dial_state_process_bridge_enter,
611  .process_bridge_leave = base_process_bridge_leave,
612 };
613 
614 static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
615 static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer);
617 static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
618 
619 /*!
620  * \brief The virtual table for the Dialed Pending state.
621  *
622  * A \ref cdr_object that has successfully finished a dial operation, but we
623  * don't know what they're going to do yet. It's theoretically possible to dial
624  * a party and then have that party not be bridged with the caller; likewise,
625  * an origination can complete and the channel go off and execute dialplan. The
626  * pending state acts as a bridge between either:
627  * * Entering a bridge
628  * * Getting a new CDR for new dialplan execution
629  * * Switching from being originated to executing dialplan
630  *
631  * A \ref cdr_object from this state can go in any of the following states:
632  * * \ref single_state_fn_table
633  * * \ref dialed_pending_state_fn_table
634  * * \ref bridge_state_fn_table
635  * * \ref finalized_state_fn_table
636  */
638  .name = "DialedPending",
639  .process_party_a = dialed_pending_state_process_party_a,
640  .process_dial_begin = dialed_pending_state_process_dial_begin,
641  .process_bridge_enter = dialed_pending_state_process_bridge_enter,
642  .process_parking_bridge_enter = dialed_pending_state_process_parking_bridge_enter,
643  .process_bridge_leave = base_process_bridge_leave,
644  .process_parked_channel = base_process_parked_channel,
645 };
646 
647 static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
648 static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
649 
650 /*!
651  * \brief The virtual table for the Bridged state
652  *
653  * A \ref cdr_object enters this state when it receives notification that the
654  * channel has entered a bridge.
655  *
656  * A \ref cdr_object from this state can go to:
657  * * \ref finalized_state_fn_table
658  */
660  .name = "Bridged",
661  .process_party_a = base_process_party_a,
662  .process_party_b = bridge_state_process_party_b,
663  .process_bridge_leave = bridge_state_process_bridge_leave,
664  .process_parked_channel = base_process_parked_channel,
665 };
666 
667 static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel);
668 
669 /*!
670  * \brief The virtual table for the Parked state
671  *
672  * Parking is weird. Unlike typical bridges, it has to be treated somewhat
673  * uniquely - a channel in a parking bridge (which is a subclass of a holding
674  * bridge) has to be handled as if the channel went into an application.
675  * However, when the channel comes out, we need a new CDR - unlike the Single
676  * state.
677  */
679  .name = "Parked",
680  .process_party_a = base_process_party_a,
681  .process_bridge_leave = parked_state_process_bridge_leave,
682  .process_parked_channel = base_process_parked_channel,
683 };
684 
685 static void finalized_state_init_function(struct cdr_object *cdr);
686 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot);
687 
688 /*!
689  * \brief The virtual table for the finalized state.
690  *
691  * Once in the finalized state, the CDR is done. No modifications can be made
692  * to the CDR.
693  */
695  .name = "Finalized",
696  .init_function = finalized_state_init_function,
697  .process_party_a = finalized_state_process_party_a,
698  .process_bridge_enter = base_process_bridge_enter,
699 };
700 
701 /*! \brief A wrapper object around a snapshot.
702  * Fields that are mutable by the CDR engine are replicated here.
703  */
705  struct ast_channel_snapshot *snapshot; /*!< The channel snapshot */
706  char userfield[AST_MAX_USER_FIELD]; /*!< Userfield for the channel */
707  unsigned int flags; /*!< Specific flags for this party */
708  struct varshead variables; /*!< CDR variables for the channel */
709 };
710 
711 /*! \brief An in-memory representation of an active CDR */
712 struct cdr_object {
713  struct cdr_object_snapshot party_a; /*!< The Party A information */
714  struct cdr_object_snapshot party_b; /*!< The Party B information */
715  struct cdr_object_fn_table *fn_table; /*!< The current virtual table */
716 
717  enum ast_cdr_disposition disposition; /*!< The disposition of the CDR */
718  struct timeval start; /*!< When this CDR was created */
719  struct timeval answer; /*!< Either when the channel was answered, or when the path between channels was established */
720  struct timeval end; /*!< When this CDR was finalized */
721  struct timeval lastevent; /*!< The time at which the last event was created regarding this CDR */
722  unsigned int sequence; /*!< A monotonically increasing number for each CDR */
723  struct ast_flags flags; /*!< Flags on the CDR */
725  AST_STRING_FIELD(linkedid); /*!< Linked ID. Cached here as it may change out from party A, which must be immutable */
726  AST_STRING_FIELD(uniqueid); /*!< Unique id of party A. Cached here as it is the master CDR container key */
727  AST_STRING_FIELD(name); /*!< Channel name of party A. Cached here as the party A address may change */
728  AST_STRING_FIELD(bridge); /*!< The bridge the party A happens to be in. */
729  AST_STRING_FIELD(appl); /*!< The last accepted application party A was in */
730  AST_STRING_FIELD(data); /*!< The data for the last accepted application party A was in */
731  AST_STRING_FIELD(context); /*!< The accepted context for Party A */
732  AST_STRING_FIELD(exten); /*!< The accepted extension for Party A */
733  AST_STRING_FIELD(party_b_name); /*!< Party B channel name. Cached here as it is the all CDRs container key */
734  );
735  struct cdr_object *next; /*!< The next CDR object in the chain */
736  struct cdr_object *last; /*!< The last CDR object in the chain */
737  int is_root; /*!< True if this is the first CDR in the chain */
738 };
739 
740 /*!
741  * \brief Copy variables from one list to another
742  * \param to_list destination
743  * \param from_list source
744  * \retval The number of copied variables
745  */
746 static int copy_variables(struct varshead *to_list, struct varshead *from_list)
747 {
748  struct ast_var_t *variables;
749  struct ast_var_t *newvariable;
750  const char *var;
751  const char *val;
752  int x = 0;
753 
754  AST_LIST_TRAVERSE(from_list, variables, entries) {
755  var = ast_var_name(variables);
756  if (ast_strlen_zero(var)) {
757  continue;
758  }
759  val = ast_var_value(variables);
760  if (ast_strlen_zero(val)) {
761  continue;
762  }
763  newvariable = ast_var_assign(var, val);
764  if (newvariable) {
765  AST_LIST_INSERT_HEAD(to_list, newvariable, entries);
766  ++x;
767  }
768  }
769 
770  return x;
771 }
772 
773 /*!
774  * \brief Delete all variables from a variable list
775  * \param headp The head pointer to the variable list to delete
776  */
777 static void free_variables(struct varshead *headp)
778 {
779  struct ast_var_t *vardata;
780 
781  while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
782  ast_var_delete(vardata);
783  }
784 }
785 
786 /*!
787  * \brief Copy a snapshot and its details
788  * \param dst The destination
789  * \param src The source
790  */
792 {
793  ao2_t_replace(dst->snapshot, src->snapshot, "CDR snapshot copy");
794  strcpy(dst->userfield, src->userfield);
795  dst->flags = src->flags;
796  copy_variables(&dst->variables, &src->variables);
797 }
798 
799 /*!
800  * \brief Transition a \ref cdr_object to a new state with initiation flag
801  * \param cdr The \ref cdr_object to transition
802  * \param fn_table The \ref cdr_object_fn_table state to go to
803  */
804 static void cdr_object_transition_state_init(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table, int do_init)
805 {
806  CDR_DEBUG("%p - Transitioning CDR for %s from state %s to %s\n",
807  cdr, cdr->party_a.snapshot->base->name,
808  cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
809  cdr->fn_table = fn_table;
810 
811  if (cdr->fn_table->init_function && do_init) {
812  cdr->fn_table->init_function(cdr);
813  }
814 }
815 
816 /*!
817  * \brief Transition a \ref cdr_object to a new state
818  * \param cdr The \ref cdr_object to transition
819  * \param fn_table The \ref cdr_object_fn_table state to go to
820  */
821 static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
822 {
823  cdr_object_transition_state_init(cdr, fn_table, 1);
824 }
825 
826 /*!
827  * \internal
828  * \brief Hash function for master CDR container indexed by Party A uniqueid.
829  */
830 static int cdr_master_hash_fn(const void *obj, const int flags)
831 {
832  const struct cdr_object *cdr;
833  const char *key;
834 
835  switch (flags & OBJ_SEARCH_MASK) {
836  case OBJ_SEARCH_KEY:
837  key = obj;
838  break;
839  case OBJ_SEARCH_OBJECT:
840  cdr = obj;
841  key = cdr->uniqueid;
842  break;
843  default:
844  ast_assert(0);
845  return 0;
846  }
847  return ast_str_case_hash(key);
848 }
849 
850 /*!
851  * \internal
852  * \brief Comparison function for master CDR container indexed by Party A uniqueid.
853  */
854 static int cdr_master_cmp_fn(void *obj, void *arg, int flags)
855 {
856  struct cdr_object *left = obj;
857  struct cdr_object *right = arg;
858  const char *right_key = arg;
859  int cmp;
860 
861  switch (flags & OBJ_SEARCH_MASK) {
862  case OBJ_SEARCH_OBJECT:
863  right_key = right->uniqueid;
864  /* Fall through */
865  case OBJ_SEARCH_KEY:
866  cmp = strcmp(left->uniqueid, right_key);
867  break;
869  /*
870  * We could also use a partial key struct containing a length
871  * so strlen() does not get called for every comparison instead.
872  */
873  cmp = strncmp(left->uniqueid, right_key, strlen(right_key));
874  break;
875  default:
876  /* Sort can only work on something with a full or partial key. */
877  ast_assert(0);
878  cmp = 0;
879  break;
880  }
881  return cmp ? 0 : CMP_MATCH;
882 }
883 
884 /*!
885  * \internal
886  * \brief Hash function for all CDR container indexed by Party B channel name.
887  */
888 static int cdr_all_hash_fn(const void *obj, const int flags)
889 {
890  const struct cdr_object *cdr;
891  const char *key;
892 
893  switch (flags & OBJ_SEARCH_MASK) {
894  case OBJ_SEARCH_KEY:
895  key = obj;
896  break;
897  case OBJ_SEARCH_OBJECT:
898  cdr = obj;
899  key = cdr->party_b_name;
900  break;
901  default:
902  ast_assert(0);
903  return 0;
904  }
905  return ast_str_case_hash(key);
906 }
907 
908 /*!
909  * \internal
910  * \brief Comparison function for all CDR container indexed by Party B channel name.
911  */
912 static int cdr_all_cmp_fn(void *obj, void *arg, int flags)
913 {
914  struct cdr_object *left = obj;
915  struct cdr_object *right = arg;
916  const char *right_key = arg;
917  int cmp;
918 
919  switch (flags & OBJ_SEARCH_MASK) {
920  case OBJ_SEARCH_OBJECT:
921  right_key = right->party_b_name;
922  /* Fall through */
923  case OBJ_SEARCH_KEY:
924  cmp = strcasecmp(left->party_b_name, right_key);
925  break;
927  /*
928  * We could also use a partial key struct containing a length
929  * so strlen() does not get called for every comparison instead.
930  */
931  cmp = strncasecmp(left->party_b_name, right_key, strlen(right_key));
932  break;
933  default:
934  /* Sort can only work on something with a full or partial key. */
935  ast_assert(0);
936  cmp = 0;
937  break;
938  }
939  return cmp ? 0 : CMP_MATCH;
940 }
941 
942 /*!
943  * \internal
944  * \brief Relink the CDR because Party B's snapshot changed.
945  * \since 13.19.0
946  *
947  * \return Nothing
948  */
949 static void cdr_all_relink(struct cdr_object *cdr)
950 {
951  ao2_lock(active_cdrs_all);
952  if (cdr->party_b.snapshot) {
953  if (strcasecmp(cdr->party_b_name, cdr->party_b.snapshot->base->name)) {
954  ao2_unlink_flags(active_cdrs_all, cdr, OBJ_NOLOCK);
956  ao2_link_flags(active_cdrs_all, cdr, OBJ_NOLOCK);
957  }
958  } else {
959  ao2_unlink_flags(active_cdrs_all, cdr, OBJ_NOLOCK);
961  }
962  ao2_unlock(active_cdrs_all);
963 }
964 
965 /*!
966  * \internal
967  * \brief Unlink the master CDR and chained records from the active_cdrs_all container.
968  * \since 13.19.0
969  *
970  * \return Nothing
971  */
972 static void cdr_all_unlink(struct cdr_object *cdr)
973 {
974  struct cdr_object *cur;
975  struct cdr_object *next;
976 
977  ast_assert(cdr->is_root);
978 
979  /* Hold a ref to the root CDR to ensure the list members don't go away on us. */
980  ao2_ref(cdr, +1);
981  ao2_lock(active_cdrs_all);
982  for (cur = cdr; cur; cur = next) {
983  next = cur->next;
984  ao2_unlink_flags(active_cdrs_all, cur, OBJ_NOLOCK);
985  /*
986  * It is safe to still use cur after unlinking because the
987  * root CDR holds a ref to all the CDRs in the list and we
988  * have a ref to the root CDR.
989  */
991  }
992  ao2_unlock(active_cdrs_all);
993  ao2_ref(cdr, -1);
994 }
995 
996 /*!
997  * \brief \ref cdr_object Destructor
998  */
999 static void cdr_object_dtor(void *obj)
1000 {
1001  struct cdr_object *cdr = obj;
1002  struct ast_var_t *it_var;
1003 
1006  while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_a.variables, entries))) {
1007  ast_var_delete(it_var);
1008  }
1009  while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_b.variables, entries))) {
1010  ast_var_delete(it_var);
1011  }
1013 
1014  /* CDR destruction used to work by calling ao2_cleanup(next) and
1015  * allowing the chain to destroy itself neatly. Unfortunately, for
1016  * really long chains, this can result in a stack overflow. So now
1017  * when the root CDR is destroyed, it is responsible for unreffing
1018  * all CDRs in the chain
1019  */
1020  if (cdr->is_root) {
1021  struct cdr_object *curr = cdr->next;
1022  struct cdr_object *next;
1023 
1024  while (curr) {
1025  next = curr->next;
1026  ao2_cleanup(curr);
1027  curr = next;
1028  }
1029  }
1030 }
1031 
1032 /*!
1033  * \brief \ref cdr_object constructor
1034  * \param chan The \ref ast_channel_snapshot that is the CDR's Party A
1035  *
1036  * This implicitly sets the state of the newly created CDR to the Single state
1037  * (\ref single_state_fn_table)
1038  */
1039 static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
1040 {
1041  struct cdr_object *cdr;
1042 
1043  ast_assert(chan != NULL);
1044 
1045  cdr = ao2_alloc(sizeof(*cdr), cdr_object_dtor);
1046  if (!cdr) {
1047  return NULL;
1048  }
1049  cdr->last = cdr;
1050  if (ast_string_field_init(cdr, 64)) {
1051  ao2_cleanup(cdr);
1052  return NULL;
1053  }
1055  ast_string_field_set(cdr, name, chan->base->name);
1057  cdr->disposition = AST_CDR_NULL;
1059  cdr->lastevent = *event_time;
1060 
1061  cdr->party_a.snapshot = chan;
1062  ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
1063 
1064  CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->base->name);
1065 
1066  cdr_object_transition_state(cdr, &single_state_fn_table);
1067 
1068  return cdr;
1069 }
1070 
1071 /*!
1072  * \brief Create a new \ref cdr_object and append it to an existing chain
1073  * \param cdr The \ref cdr_object to append to
1074  */
1075 static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
1076 {
1077  struct cdr_object *new_cdr;
1078  struct cdr_object *it_cdr;
1079  struct cdr_object *cdr_last;
1080 
1081  cdr_last = cdr->last;
1082  new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot, event_time);
1083  if (!new_cdr) {
1084  return NULL;
1085  }
1086  new_cdr->disposition = AST_CDR_NULL;
1087 
1088  /* Copy over the linkedid, as it may have changed */
1089  ast_string_field_set(new_cdr, linkedid, cdr_last->linkedid);
1090  ast_string_field_set(new_cdr, appl, cdr_last->appl);
1091  ast_string_field_set(new_cdr, data, cdr_last->data);
1092  ast_string_field_set(new_cdr, context, cdr_last->context);
1093  ast_string_field_set(new_cdr, exten, cdr_last->exten);
1094 
1095  /*
1096  * If the current CDR says to disable all future ones,
1097  * keep the disable chain going
1098  */
1099  if (ast_test_flag(&cdr_last->flags, AST_CDR_FLAG_DISABLE_ALL)) {
1101  }
1102 
1103  /* Copy over other Party A information */
1104  cdr_object_snapshot_copy(&new_cdr->party_a, &cdr_last->party_a);
1105 
1106  /* Append the CDR to the end of the list */
1107  for (it_cdr = cdr; it_cdr->next; it_cdr = it_cdr->next) {
1108  it_cdr->last = new_cdr;
1109  }
1110  it_cdr->last = new_cdr;
1111  it_cdr->next = new_cdr;
1112 
1113  return new_cdr;
1114 }
1115 
1116 /*!
1117  * \internal
1118  * \brief Determine if CDR flag is configured.
1119  *
1120  * \param cdr_flag The configured CDR flag to check.
1121  *
1122  * \retval 0 if the CDR flag is not configured.
1123  * \retval non-zero if the CDR flag is configured.
1124  *
1125  * \return Nothing
1126  */
1127 static int is_cdr_flag_set(unsigned int cdr_flag)
1128 {
1129  struct module_config *mod_cfg;
1130  int flag_set;
1131 
1132  mod_cfg = ao2_global_obj_ref(module_configs);
1133  flag_set = mod_cfg && ast_test_flag(&mod_cfg->general->settings, cdr_flag);
1134  ao2_cleanup(mod_cfg);
1135  return flag_set;
1136 }
1137 
1138 /*!
1139  * \brief Return whether or not a channel has changed its state in the dialplan, subject
1140  * to endbeforehexten logic
1141  *
1142  * \param old_snapshot The previous state
1143  * \param new_snapshot The new state
1144  *
1145  * \retval 0 if the state has not changed
1146  * \retval 1 if the state changed
1147  */
1148 static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
1149  struct ast_channel_snapshot *new_snapshot)
1150 {
1151  /* If we ignore hangup logic, don't indicate that we're executing anything new */
1154  return 0;
1155  }
1156 
1157  /* When Party A is originated to an application and the application exits, the stack
1158  * will attempt to clear the application and restore the dummy originate application
1159  * of "AppDialX". Ignore application changes to AppDialX as a result.
1160  */
1161  if (strcmp(new_snapshot->dialplan->appl, old_snapshot->dialplan->appl)
1162  && strncasecmp(new_snapshot->dialplan->appl, "appdial", 7)
1163  && (strcmp(new_snapshot->dialplan->context, old_snapshot->dialplan->context)
1164  || strcmp(new_snapshot->dialplan->exten, old_snapshot->dialplan->exten)
1165  || new_snapshot->dialplan->priority != old_snapshot->dialplan->priority)) {
1166  return 1;
1167  }
1168 
1169  return 0;
1170 }
1171 
1172 /*!
1173  * \brief Return whether or not a \ref ast_channel_snapshot is for a channel
1174  * that was created as the result of a dial operation
1175  *
1176  * \retval 0 the channel was not created as the result of a dial
1177  * \retval 1 the channel was created as the result of a dial
1178  */
1179 static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
1180 {
1181  return (ast_test_flag(&snapshot->flags, AST_FLAG_OUTGOING)
1182  && !(ast_test_flag(&snapshot->flags, AST_FLAG_ORIGINATED)));
1183 }
1184 
1185 /*!
1186  * \brief Given two CDR snapshots, figure out who should be Party A for the
1187  * resulting CDR
1188  * \param left One of the snapshots
1189  * \param right The other snapshot
1190  * \retval The snapshot that won
1191  */
1193 {
1194  /* Check whether or not the party is dialed. A dialed party is never the
1195  * Party A with a party that was not dialed.
1196  */
1197  if (!snapshot_is_dialed(left->snapshot) && snapshot_is_dialed(right->snapshot)) {
1198  return left;
1199  } else if (snapshot_is_dialed(left->snapshot) && !snapshot_is_dialed(right->snapshot)) {
1200  return right;
1201  }
1202 
1203  /* Try the Party A flag */
1205  return left;
1206  } else if (!ast_test_flag(right, AST_CDR_FLAG_PARTY_A) && ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
1207  return right;
1208  }
1209 
1210  /* Neither party is dialed and neither has the Party A flag - defer to
1211  * creation time */
1212  if (left->snapshot->base->creationtime.tv_sec < right->snapshot->base->creationtime.tv_sec) {
1213  return left;
1214  } else if (left->snapshot->base->creationtime.tv_sec > right->snapshot->base->creationtime.tv_sec) {
1215  return right;
1216  } else if (left->snapshot->base->creationtime.tv_usec > right->snapshot->base->creationtime.tv_usec) {
1217  return right;
1218  } else {
1219  /* Okay, fine, take the left one */
1220  return left;
1221  }
1222 }
1223 
1224 /*!
1225  * Compute the duration for a \ref cdr_object
1226  */
1227 static long cdr_object_get_duration(struct cdr_object *cdr)
1228 {
1229  return (long)(ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->start) / 1000);
1230 }
1231 
1232 /*!
1233  * \brief Compute the billsec for a \ref cdr_object
1234  */
1235 static long cdr_object_get_billsec(struct cdr_object *cdr)
1236 {
1237  long int ms;
1238 
1239  if (ast_tvzero(cdr->answer)) {
1240  return 0;
1241  }
1242 
1243  ms = ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->answer);
1244  if (ms % 1000 >= 500
1246  ms = (ms / 1000) + 1;
1247  } else {
1248  ms = ms / 1000;
1249  }
1250 
1251  return ms;
1252 }
1253 
1254 /*!
1255  * \internal
1256  * \brief Set a variable on a CDR object
1257  *
1258  * \param headp The header pointer to the variable to set
1259  * \param name The name of the variable
1260  * \param value The value of the variable
1261  */
1262 static void set_variable(struct varshead *headp, const char *name, const char *value)
1263 {
1264  struct ast_var_t *newvariable;
1265 
1266  AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1267  if (!strcasecmp(ast_var_name(newvariable), name)) {
1269  ast_var_delete(newvariable);
1270  break;
1271  }
1272  }
1274 
1275  if (value && (newvariable = ast_var_assign(name, value))) {
1276  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1277  }
1278 }
1279 
1280 /*!
1281  * \brief Create a chain of \ref ast_cdr objects from a chain of \ref cdr_object
1282  * suitable for consumption by the registered CDR backends
1283  * \param cdr The \ref cdr_object to convert to a public record
1284  * \retval A chain of \ref ast_cdr objects on success
1285  * \retval NULL on failure
1286  */
1288 {
1289  struct ast_cdr *pub_cdr = NULL, *cdr_prev = NULL;
1290  struct cdr_object *it_cdr;
1291  struct ast_var_t *it_var, *it_copy_var;
1292  struct ast_channel_snapshot *party_a;
1293  struct ast_channel_snapshot *party_b;
1294 
1295  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1296  struct ast_cdr *cdr_copy;
1297 
1298  /* Don't create records for CDRs where the party A was a dialed channel */
1299  if (snapshot_is_dialed(it_cdr->party_a.snapshot) && !it_cdr->party_b.snapshot) {
1300  ast_debug(1, "CDR for %s is dialed and has no Party B; discarding\n",
1301  it_cdr->party_a.snapshot->base->name);
1302  continue;
1303  }
1304 
1305  cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
1306  if (!cdr_copy) {
1307  ast_free(pub_cdr);
1308  return NULL;
1309  }
1310 
1311  party_a = it_cdr->party_a.snapshot;
1312  party_b = it_cdr->party_b.snapshot;
1313 
1314  /* Party A */
1315  ast_assert(party_a != NULL);
1316  ast_copy_string(cdr_copy->accountcode, party_a->base->accountcode, sizeof(cdr_copy->accountcode));
1317  cdr_copy->amaflags = party_a->amaflags;
1318  ast_copy_string(cdr_copy->channel, party_a->base->name, sizeof(cdr_copy->channel));
1319  ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller->name, party_a->caller->number, "");
1320  ast_copy_string(cdr_copy->src, party_a->caller->number, sizeof(cdr_copy->src));
1321  ast_copy_string(cdr_copy->uniqueid, party_a->base->uniqueid, sizeof(cdr_copy->uniqueid));
1322  ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
1323  ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
1324  ast_copy_string(cdr_copy->dst, it_cdr->exten, sizeof(cdr_copy->dst));
1325  ast_copy_string(cdr_copy->dcontext, it_cdr->context, sizeof(cdr_copy->dcontext));
1326 
1327  /* Party B */
1328  if (party_b) {
1329  ast_copy_string(cdr_copy->dstchannel, party_b->base->name, sizeof(cdr_copy->dstchannel));
1330  ast_copy_string(cdr_copy->peeraccount, party_b->base->accountcode, sizeof(cdr_copy->peeraccount));
1331  if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
1332  snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
1333  }
1334  }
1335  if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) {
1336  ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield));
1337  }
1338 
1339  /* Timestamps/durations */
1340  cdr_copy->start = it_cdr->start;
1341  cdr_copy->answer = it_cdr->answer;
1342  cdr_copy->end = it_cdr->end;
1343  cdr_copy->billsec = cdr_object_get_billsec(it_cdr);
1344  cdr_copy->duration = cdr_object_get_duration(it_cdr);
1345 
1346  /* Flags and IDs */
1347  ast_copy_flags(cdr_copy, &it_cdr->flags, AST_FLAGS_ALL);
1348  ast_copy_string(cdr_copy->linkedid, it_cdr->linkedid, sizeof(cdr_copy->linkedid));
1349  cdr_copy->disposition = it_cdr->disposition;
1350  cdr_copy->sequence = it_cdr->sequence;
1351 
1352  /* Variables */
1353  copy_variables(&cdr_copy->varshead, &it_cdr->party_a.variables);
1354  AST_LIST_TRAVERSE(&it_cdr->party_b.variables, it_var, entries) {
1355  int found = 0;
1356  struct ast_var_t *newvariable;
1357  AST_LIST_TRAVERSE(&cdr_copy->varshead, it_copy_var, entries) {
1358  if (!strcasecmp(ast_var_name(it_var), ast_var_name(it_copy_var))) {
1359  found = 1;
1360  break;
1361  }
1362  }
1363  if (!found && (newvariable = ast_var_assign(ast_var_name(it_var), ast_var_value(it_var)))) {
1364  AST_LIST_INSERT_TAIL(&cdr_copy->varshead, newvariable, entries);
1365  }
1366  }
1367 
1368  if (!pub_cdr) {
1369  pub_cdr = cdr_copy;
1370  cdr_prev = pub_cdr;
1371  } else {
1372  cdr_prev->next = cdr_copy;
1373  cdr_prev = cdr_copy;
1374  }
1375  }
1376 
1377  return pub_cdr;
1378 }
1379 
1380 /*!
1381  * \brief Dispatch a CDR.
1382  * \param cdr The \ref cdr_object to dispatch
1383  *
1384  * This will create a \ref ast_cdr object and publish it to the various backends
1385  */
1386 static void cdr_object_dispatch(struct cdr_object *cdr)
1387 {
1388  struct ast_cdr *pub_cdr;
1389 
1390  CDR_DEBUG("%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
1391  cdr->party_a.snapshot->base->name,
1392  cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<none>");
1393  pub_cdr = cdr_object_create_public_records(cdr);
1394  cdr_detach(pub_cdr);
1395 }
1396 
1397 /*!
1398  * \brief Set the disposition on a \ref cdr_object based on a hangupcause code
1399  * \param cdr The \ref cdr_object
1400  * \param hangupcause The Asterisk hangup cause code
1401  */
1402 static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
1403 {
1404  /* Change the disposition based on the hang up cause */
1405  switch (hangupcause) {
1406  case AST_CAUSE_BUSY:
1407  cdr->disposition = AST_CDR_BUSY;
1408  break;
1409  case AST_CAUSE_CONGESTION:
1411  cdr->disposition = AST_CDR_FAILED;
1412  } else {
1414  }
1415  break;
1418  cdr->disposition = AST_CDR_FAILED;
1419  break;
1421  case AST_CAUSE_NO_ANSWER:
1423  break;
1424  default:
1425  break;
1426  }
1427 }
1428 
1429 /*!
1430  * \brief Finalize a CDR.
1431  *
1432  * This function is safe to call multiple times. Note that you can call this
1433  * explicitly before going to the finalized state if there's a chance the CDR
1434  * will be re-activated, in which case the \ref cdr_object's end time should be
1435  * cleared. This function is implicitly called when a CDR transitions to the
1436  * finalized state and right before it is dispatched
1437  *
1438  * \param cdr_object The CDR to finalize
1439  */
1440 static void cdr_object_finalize(struct cdr_object *cdr)
1441 {
1442  if (!ast_tvzero(cdr->end)) {
1443  return;
1444  }
1445  cdr->end = cdr->lastevent;
1446 
1447  if (cdr->disposition == AST_CDR_NULL) {
1448  if (!ast_tvzero(cdr->answer)) {
1450  } else if (cdr->party_a.snapshot->hangup->cause) {
1452  } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangup->cause) {
1454  } else {
1455  cdr->disposition = AST_CDR_FAILED;
1456  }
1457  }
1458 
1459  /* tv_usec is suseconds_t, which could be int or long */
1460  ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dur %.3f bill %.3f dispo %s\n",
1461  cdr->party_a.snapshot->base->name,
1462  (long)cdr->start.tv_sec,
1463  (long)cdr->start.tv_usec,
1464  (long)cdr->answer.tv_sec,
1465  (long)cdr->answer.tv_usec,
1466  (long)cdr->end.tv_sec,
1467  (long)cdr->end.tv_usec,
1468  (double)ast_tvdiff_ms(cdr->end, cdr->start) / 1000.0,
1469  (double)ast_tvdiff_ms(cdr->end, cdr->answer) / 1000.0,
1471 }
1472 
1473 /*!
1474  * \brief Check to see if a CDR needs to move to the finalized state because
1475  * its Party A hungup.
1476  */
1478 {
1481  cdr_object_finalize(cdr);
1482  }
1483 
1485  && cdr->fn_table != &finalized_state_fn_table) {
1486  cdr_object_transition_state(cdr, &finalized_state_fn_table);
1487  }
1488 }
1489 
1490 /*!
1491  * \brief Check to see if a CDR needs to be answered based on its Party A.
1492  * Note that this is safe to call as much as you want - we won't answer twice
1493  */
1495 {
1496  if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
1497  cdr->answer = cdr->lastevent;
1498  /* tv_usec is suseconds_t, which could be int or long */
1499  CDR_DEBUG("%p - Set answered time to %ld.%06ld\n", cdr,
1500  (long)cdr->answer.tv_sec,
1501  (long)cdr->answer.tv_usec);
1502  }
1503 }
1504 
1505 /* \brief Set Caller ID information on a CDR */
1506 static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
1507 {
1508  if (!old_snapshot->snapshot) {
1509  set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
1510  set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
1511  set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
1512  return;
1513  }
1514  if (strcmp(old_snapshot->snapshot->caller->dnid, new_snapshot->caller->dnid)) {
1515  set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
1516  }
1517  if (strcmp(old_snapshot->snapshot->caller->subaddr, new_snapshot->caller->subaddr)) {
1518  set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
1519  }
1520  if (strcmp(old_snapshot->snapshot->caller->dialed_subaddr, new_snapshot->caller->dialed_subaddr)) {
1521  set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
1522  }
1523 }
1524 
1525 /*!
1526  * \brief Swap an old \ref cdr_object_snapshot's \ref ast_channel_snapshot for
1527  * a new \ref ast_channel_snapshot
1528  * \param old_snapshot The old \ref cdr_object_snapshot
1529  * \param new_snapshot The new \ref ast_channel_snapshot for old_snapshot
1530  */
1531 static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot,
1532  struct ast_channel_snapshot *new_snapshot)
1533 {
1534  cdr_object_update_cid(old_snapshot, new_snapshot);
1535  ao2_t_replace(old_snapshot->snapshot, new_snapshot, "Swap CDR shapshot");
1536 }
1537 
1538 /* BASE METHOD IMPLEMENTATIONS */
1539 
1540 static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1541 {
1542  ast_assert(strcasecmp(snapshot->base->name, cdr->party_a.snapshot->base->name) == 0);
1543 
1544  /* Finalize the CDR if we're in hangup logic and we're set to do so */
1547  cdr_object_finalize(cdr);
1548  return 0;
1549  }
1550 
1551  /*
1552  * Only record the context and extension if we aren't in a subroutine, or if
1553  * we are executing hangup logic.
1554  */
1555  if (!ast_test_flag(&snapshot->flags, AST_FLAG_SUBROUTINE_EXEC)
1557  if (strcmp(cdr->context, snapshot->dialplan->context)) {
1558  ast_string_field_set(cdr, context, snapshot->dialplan->context);
1559  }
1560  if (strcmp(cdr->exten, snapshot->dialplan->exten)) {
1561  ast_string_field_set(cdr, exten, snapshot->dialplan->exten);
1562  }
1563  }
1564 
1565  cdr_object_swap_snapshot(&cdr->party_a, snapshot);
1566 
1567  /* When Party A is originated to an application and the application exits, the stack
1568  * will attempt to clear the application and restore the dummy originate application
1569  * of "AppDialX". Prevent that, and any other application changes we might not want
1570  * here.
1571  */
1572  if (!ast_test_flag(&cdr->flags, AST_CDR_LOCK_APP)
1573  && !ast_strlen_zero(snapshot->dialplan->appl)
1574  && (strncasecmp(snapshot->dialplan->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))) {
1575  if (strcmp(cdr->appl, snapshot->dialplan->appl)) {
1576  ast_string_field_set(cdr, appl, snapshot->dialplan->appl);
1577  }
1578  if (strcmp(cdr->data, snapshot->dialplan->data)) {
1579  ast_string_field_set(cdr, data, snapshot->dialplan->data);
1580  }
1581 
1582  /* Dial (app_dial) is a special case. Because pre-dial handlers, which
1583  * execute before the dial begins, will alter the application/data to
1584  * something people typically don't want to see, if we see a channel enter
1585  * into Dial here, we set the appl/data accordingly and lock it.
1586  */
1587  if (!strcmp(snapshot->dialplan->appl, "Dial")) {
1589  }
1590  }
1591 
1592  if (strcmp(cdr->linkedid, snapshot->peer->linkedid)) {
1593  ast_string_field_set(cdr, linkedid, snapshot->peer->linkedid);
1594  }
1597 
1598  return 0;
1599 }
1600 
1601 static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
1602 {
1603  return 0;
1604 }
1605 
1606 static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1607 {
1608  return 0;
1609 }
1610 
1612 {
1613  /* Base process bridge enter simply indicates that we can't handle it */
1614  return BRIDGE_ENTER_NEED_CDR;
1615 }
1616 
1617 static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
1618 {
1619  char park_info[128];
1620 
1621  ast_assert(!strcasecmp(parking_info->parkee->base->name, cdr->party_a.snapshot->base->name));
1622 
1623  /* Update Party A information regardless */
1624  cdr->fn_table->process_party_a(cdr, parking_info->parkee);
1625 
1626  /* Fake out where we're parked */
1627  ast_string_field_set(cdr, appl, "Park");
1628  snprintf(park_info, sizeof(park_info), "%s:%u", parking_info->parkinglot, parking_info->parkingspace);
1629  ast_string_field_set(cdr, data, park_info);
1630 
1631  /* Prevent any further changes to the App/Data fields for this record */
1633 
1634  return 0;
1635 }
1636 
1637 /* SINGLE STATE */
1638 
1639 static void single_state_init_function(struct cdr_object *cdr)
1640 {
1641  cdr->start = cdr->lastevent;
1643 }
1644 
1645 static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1646 {
1647  /* This should never happen! */
1648  ast_assert(cdr->party_b.snapshot == NULL);
1649  ast_assert(0);
1650  return;
1651 }
1652 
1653 static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1654 {
1655  if (caller && !strcasecmp(cdr->party_a.snapshot->base->name, caller->base->name)) {
1656  base_process_party_a(cdr, caller);
1657  CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
1658  cdr->party_a.snapshot->base->name);
1659  cdr_object_swap_snapshot(&cdr->party_b, peer);
1660  cdr_all_relink(cdr);
1661  CDR_DEBUG("%p - Updated Party B %s snapshot\n", cdr,
1662  cdr->party_b.snapshot->base->name);
1663 
1664  /* If we have two parties, lock the application that caused the
1665  * two parties to be associated. This prevents mid-call event
1666  * macros/gosubs from perturbing the CDR application/data
1667  */
1669  } else if (!strcasecmp(cdr->party_a.snapshot->base->name, peer->base->name)) {
1670  /* We're the entity being dialed, i.e., outbound origination */
1671  base_process_party_a(cdr, peer);
1672  CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
1673  cdr->party_a.snapshot->base->name);
1674  }
1675 
1676  cdr_object_transition_state(cdr, &dial_state_fn_table);
1677  return 0;
1678 }
1679 
1680 /*!
1681  * \brief Handle a comparison between our \ref cdr_object and a \ref cdr_object
1682  * already in the bridge while in the Single state. The goal of this is to find
1683  * a Party B for our CDR.
1684  *
1685  * \param cdr Our \ref cdr_object in the Single state
1686  * \param cand_cdr The \ref cdr_object already in the Bridge state
1687  *
1688  * \retval 0 The cand_cdr had a Party A or Party B that we could use as our
1689  * Party B
1690  * \retval 1 No party in the cand_cdr could be used as our Party B
1691  */
1693  struct cdr_object *cand_cdr)
1694 {
1695  struct cdr_object_snapshot *party_a;
1696 
1697  /* Don't match on ourselves */
1698  if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
1699  return 1;
1700  }
1701 
1702  /* Try the candidate CDR's Party A first */
1703  party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
1704  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1705  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1706  cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name);
1707  cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1708  cdr_all_relink(cdr);
1709  if (!cand_cdr->party_b.snapshot) {
1710  /* We just stole them - finalize their CDR. Note that this won't
1711  * transition their state, it just sets the end time and the
1712  * disposition - if we need to re-activate them later, we can.
1713  */
1714  cdr_object_finalize(cand_cdr);
1715  }
1716  return 0;
1717  }
1718 
1719  /* Try their Party B, unless it's us */
1720  if (!cand_cdr->party_b.snapshot
1721  || !strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name)) {
1722  return 1;
1723  }
1724  party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
1725  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1726  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1727  cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name);
1728  cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
1729  cdr_all_relink(cdr);
1730  return 0;
1731  }
1732 
1733  return 1;
1734 }
1735 
1737 {
1738  struct ao2_iterator it_cdrs;
1739  char *channel_id;
1740  int success = 0;
1741 
1742  ast_string_field_set(cdr, bridge, bridge->uniqueid);
1743 
1744  if (ao2_container_count(bridge->channels) == 1) {
1745  /* No one in the bridge yet but us! */
1746  cdr_object_transition_state(cdr, &bridge_state_fn_table);
1747  return BRIDGE_ENTER_ONLY_PARTY;
1748  }
1749 
1750  for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
1751  !success && (channel_id = ao2_iterator_next(&it_cdrs));
1752  ao2_ref(channel_id, -1)) {
1753  struct cdr_object *cand_cdr_master;
1754  struct cdr_object *cand_cdr;
1755 
1756  cand_cdr_master = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
1757  if (!cand_cdr_master) {
1758  continue;
1759  }
1760 
1761  ao2_lock(cand_cdr_master);
1762  for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1763  /* Skip any records that are not in a bridge or in this bridge.
1764  * I'm not sure how that would happen, but it pays to be careful. */
1765  if (cand_cdr->fn_table != &bridge_state_fn_table ||
1766  strcmp(cdr->bridge, cand_cdr->bridge)) {
1767  continue;
1768  }
1769 
1770  if (single_state_bridge_enter_comparison(cdr, cand_cdr)) {
1771  continue;
1772  }
1773  /* We successfully got a party B - break out */
1774  success = 1;
1775  break;
1776  }
1777  ao2_unlock(cand_cdr_master);
1778  ao2_cleanup(cand_cdr_master);
1779  }
1780  ao2_iterator_destroy(&it_cdrs);
1781 
1782  /* We always transition state, even if we didn't get a peer */
1783  cdr_object_transition_state(cdr, &bridge_state_fn_table);
1784 
1785  /* Success implies that we have a Party B */
1786  if (success) {
1788  }
1789 
1790  return BRIDGE_ENTER_NO_PARTY_B;
1791 }
1792 
1794 {
1795  cdr_object_transition_state(cdr, &parked_state_fn_table);
1796  return 0;
1797 }
1798 
1799 
1800 /* DIAL STATE */
1801 
1802 static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
1803 {
1804  ast_assert(snapshot != NULL);
1806  && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
1807 
1808  cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1809 
1810  /* If party B hangs up, finalize this CDR */
1812  cdr_object_transition_state(cdr, &finalized_state_fn_table);
1813  }
1814 }
1815 
1816 static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
1817 {
1818  /* Don't process a begin dial here. A party A already in the dial state will
1819  * who receives a dial begin for something else will be handled by the
1820  * message router callback and will add a new CDR for the party A */
1821  return 1;
1822 }
1823 
1824 /*!
1825  * \internal
1826  * \brief Convert a dial status to a CDR disposition
1827  */
1828 static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
1829 {
1830  if (!strcmp(dial_status, "ANSWER")) {
1831  return AST_CDR_ANSWERED;
1832  } else if (!strcmp(dial_status, "BUSY")) {
1833  return AST_CDR_BUSY;
1834  } else if (!strcmp(dial_status, "CANCEL") || !strcmp(dial_status, "NOANSWER")) {
1835  return AST_CDR_NOANSWER;
1836  } else if (!strcmp(dial_status, "CONGESTION")) {
1838  return AST_CDR_FAILED;
1839  } else {
1840  return AST_CDR_CONGESTION;
1841  }
1842  } else if (!strcmp(dial_status, "FAILED")) {
1843  return AST_CDR_FAILED;
1844  }
1845  return AST_CDR_FAILED;
1846 }
1847 
1848 static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
1849 {
1850  struct ast_channel_snapshot *party_a;
1851 
1852  if (caller) {
1853  party_a = caller;
1854  } else {
1855  party_a = peer;
1856  }
1857  ast_assert(!strcasecmp(cdr->party_a.snapshot->base->name, party_a->base->name));
1858  cdr_object_swap_snapshot(&cdr->party_a, party_a);
1859 
1860  if (cdr->party_b.snapshot) {
1861  if (strcasecmp(cdr->party_b.snapshot->base->name, peer->base->name)) {
1862  /* Not the status for this CDR - defer back to the message router */
1863  return 1;
1864  }
1865  cdr_object_swap_snapshot(&cdr->party_b, peer);
1866  }
1867 
1868  /* Set the disposition based on the dial string. */
1869  cdr->disposition = dial_status_to_disposition(dial_status);
1870  if (cdr->disposition == AST_CDR_ANSWERED) {
1871  /* Switch to dial pending to wait and see what the caller does */
1872  cdr_object_transition_state(cdr, &dialed_pending_state_fn_table);
1873  } else {
1874  cdr_object_transition_state(cdr, &finalized_state_fn_table);
1875  }
1876 
1877  return 0;
1878 }
1879 
1881 {
1882  int success = 0;
1883 
1884  ast_string_field_set(cdr, bridge, bridge->uniqueid);
1885 
1886  /* Get parties in the bridge */
1887  if (ao2_container_count(bridge->channels) == 1) {
1888  /* No one in the bridge yet but us! */
1889  cdr_object_transition_state(cdr, &bridge_state_fn_table);
1890  return BRIDGE_ENTER_ONLY_PARTY;
1891  }
1892 
1893  /* If we don't have a Party B (originated channel), skip it */
1894  if (cdr->party_b.snapshot) {
1895  struct ao2_iterator it_cdrs;
1896  char *channel_id;
1897 
1898  for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
1899  !success && (channel_id = ao2_iterator_next(&it_cdrs));
1900  ao2_ref(channel_id, -1)) {
1901  struct cdr_object *cand_cdr_master;
1902  struct cdr_object *cand_cdr;
1903 
1904  cand_cdr_master = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
1905  if (!cand_cdr_master) {
1906  continue;
1907  }
1908 
1909  ao2_lock(cand_cdr_master);
1910  for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1911  /* Skip any records that are not in a bridge or in this bridge.
1912  * I'm not sure how that would happen, but it pays to be careful. */
1913  if (cand_cdr->fn_table != &bridge_state_fn_table
1914  || strcmp(cdr->bridge, cand_cdr->bridge)) {
1915  continue;
1916  }
1917 
1918  /* Skip any records that aren't our Party B */
1919  if (strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
1920  continue;
1921  }
1922  cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1923  /* If they have a Party B, they joined up with someone else as their
1924  * Party A. Don't finalize them as they're active. Otherwise, we
1925  * have stolen them so they need to be finalized.
1926  */
1927  if (!cand_cdr->party_b.snapshot) {
1928  cdr_object_finalize(cand_cdr);
1929  }
1930  success = 1;
1931  break;
1932  }
1933  ao2_unlock(cand_cdr_master);
1934  ao2_cleanup(cand_cdr_master);
1935  }
1936  ao2_iterator_destroy(&it_cdrs);
1937  }
1938 
1939  /* We always transition state, even if we didn't get a peer */
1940  cdr_object_transition_state(cdr, &bridge_state_fn_table);
1941 
1942  /* Success implies that we have a Party B */
1943  if (success) {
1945  }
1946  return BRIDGE_ENTER_NO_PARTY_B;
1947 }
1948 
1949 /* DIALED PENDING STATE */
1950 
1952 {
1953  /* If we get a CEP change, we're executing dialplan. If we have a Party B
1954  * that means we need a new CDR; otherwise, switch us over to single.
1955  */
1956  if (snapshot_cep_changed(cdr->party_a.snapshot, snapshot)) {
1957  if (cdr->party_b.snapshot) {
1958  cdr_object_transition_state(cdr, &finalized_state_fn_table);
1959  cdr->fn_table->process_party_a(cdr, snapshot);
1960  return 1;
1961  } else {
1962  /* The CDR does not need to be reinitialized when transitioning
1963  * to its single state as this would overwrite the start time,
1964  * causing potentially both the answer and the start time to be
1965  * the same which is incorrect.
1966  */
1967  cdr_object_transition_state_init(cdr, &single_state_fn_table, 0);
1968  cdr->fn_table->process_party_a(cdr, snapshot);
1969  return 0;
1970  }
1971  }
1972  base_process_party_a(cdr, snapshot);
1973  return 0;
1974 }
1975 
1977 {
1978  cdr_object_transition_state(cdr, &dial_state_fn_table);
1979  return cdr->fn_table->process_bridge_enter(cdr, bridge, channel);
1980 }
1981 
1983 {
1984  if (cdr->party_b.snapshot) {
1985  /* We can't handle this as we have a Party B - ask for a new one */
1986  return 1;
1987  }
1988  cdr_object_transition_state(cdr, &parked_state_fn_table);
1989  return 0;
1990 }
1991 
1993 {
1994  cdr_object_transition_state(cdr, &finalized_state_fn_table);
1995 
1996  /* Ask for a new CDR */
1997  return 1;
1998 }
1999 
2000 /* BRIDGE STATE */
2001 
2002 static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
2003 {
2005  && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
2006 
2007  cdr_object_swap_snapshot(&cdr->party_b, snapshot);
2008 
2009  /* If party B hangs up, finalize this CDR */
2011  cdr_object_transition_state(cdr, &finalized_state_fn_table);
2012  }
2013 }
2014 
2015 static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
2016 {
2017  if (strcmp(cdr->bridge, bridge->uniqueid)) {
2018  return 1;
2019  }
2020  if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)
2021  && cdr->party_b.snapshot
2022  && strcasecmp(cdr->party_b.snapshot->base->name, channel->base->name)) {
2023  return 1;
2024  }
2025  cdr_object_transition_state(cdr, &finalized_state_fn_table);
2026 
2027  return 0;
2028 }
2029 
2030 /* PARKED STATE */
2031 
2032 static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
2033 {
2034  if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)) {
2035  return 1;
2036  }
2037  cdr_object_transition_state(cdr, &finalized_state_fn_table);
2038 
2039  return 0;
2040 }
2041 
2042 /* FINALIZED STATE */
2043 
2045 {
2046  cdr_object_finalize(cdr);
2047 }
2048 
2049 static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
2050 {
2053  return 0;
2054  }
2055 
2056  /* Indicate that, if possible, we should get a new CDR */
2057  return 1;
2058 }
2059 
2060 /*!
2061  * \internal
2062  * \brief Filter channel snapshots by technology
2063  */
2064 static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
2065 {
2066  return snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL;
2067 }
2068 
2069 /*!
2070  * \internal
2071  * \brief Filter a channel snapshot update
2072  */
2074  struct ast_channel_snapshot *new_snapshot)
2075 {
2076  int ret = 0;
2077 
2078  /* Drop cache updates from certain channel technologies */
2079  if (old_snapshot) {
2080  ret |= filter_channel_snapshot(old_snapshot);
2081  }
2082  if (new_snapshot) {
2083  ret |= filter_channel_snapshot(new_snapshot);
2084  }
2085 
2086  return ret;
2087 }
2088 
2089 static int dial_status_end(const char *dialstatus)
2090 {
2091  return (strcmp(dialstatus, "RINGING") &&
2092  strcmp(dialstatus, "PROCEEDING") &&
2093  strcmp(dialstatus, "PROGRESS"));
2094 }
2095 
2096 /* TOPIC ROUTER CALLBACKS */
2097 
2098 /*!
2099  * \brief Handler for Stasis-Core dial messages
2100  * \param data Passed on
2101  * \param sub The stasis subscription for this message callback
2102  * \param topic The topic this message was published for
2103  * \param message The message
2104  */
2106 {
2107  struct cdr_object *cdr;
2108  struct ast_multi_channel_blob *payload = stasis_message_data(message);
2109  struct ast_channel_snapshot *caller;
2110  struct ast_channel_snapshot *peer;
2111  struct cdr_object *it_cdr;
2112  struct ast_json *dial_status_blob;
2113  const char *dial_status = NULL;
2114  int res = 1;
2115 
2116  caller = ast_multi_channel_blob_get_channel(payload, "caller");
2117  peer = ast_multi_channel_blob_get_channel(payload, "peer");
2118  if (!peer && !caller) {
2119  return;
2120  }
2121 
2122  if (peer && filter_channel_snapshot(peer)) {
2123  return;
2124  }
2125 
2126  if (caller && filter_channel_snapshot(caller)) {
2127  return;
2128  }
2129 
2130  dial_status_blob = ast_json_object_get(ast_multi_channel_blob_get_json(payload), "dialstatus");
2131  if (dial_status_blob) {
2132  dial_status = ast_json_string_get(dial_status_blob);
2133  }
2134 
2135  CDR_DEBUG("Dial %s message for %s, %s: %u.%08u\n",
2136  ast_strlen_zero(dial_status) ? "Begin" : "End",
2137  caller ? caller->base->name : "(none)",
2138  peer ? peer->base->name : "(none)",
2139  (unsigned int)stasis_message_timestamp(message)->tv_sec,
2140  (unsigned int)stasis_message_timestamp(message)->tv_usec);
2141 
2142  /* Figure out who is running this show */
2143  if (caller) {
2144  cdr = ao2_find(active_cdrs_master, caller->base->uniqueid, OBJ_SEARCH_KEY);
2145  } else {
2146  cdr = ao2_find(active_cdrs_master, peer->base->uniqueid, OBJ_SEARCH_KEY);
2147  }
2148  if (!cdr) {
2149  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->base->name : peer->base->name);
2150  ast_assert(0);
2151  return;
2152  }
2153 
2154  ao2_lock(cdr);
2155  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2156  it_cdr->lastevent = *stasis_message_timestamp(message);
2157  if (ast_strlen_zero(dial_status)) {
2158  if (!it_cdr->fn_table->process_dial_begin) {
2159  continue;
2160  }
2161  CDR_DEBUG("%p - Processing Dial Begin message for channel %s, peer %s\n",
2162  it_cdr,
2163  caller ? caller->base->name : "(none)",
2164  peer ? peer->base->name : "(none)");
2165  res &= it_cdr->fn_table->process_dial_begin(it_cdr,
2166  caller,
2167  peer);
2168  } else if (dial_status_end(dial_status)) {
2169  if (!it_cdr->fn_table->process_dial_end) {
2170  continue;
2171  }
2172  CDR_DEBUG("%p - Processing Dial End message for channel %s, peer %s\n",
2173  it_cdr,
2174  caller ? caller->base->name : "(none)",
2175  peer ? peer->base->name : "(none)");
2176  it_cdr->fn_table->process_dial_end(it_cdr,
2177  caller,
2178  peer,
2179  dial_status);
2180  }
2181  }
2182 
2183  /* If no CDR handled a dial begin message, make a new one */
2184  if (res && ast_strlen_zero(dial_status)) {
2185  struct cdr_object *new_cdr;
2186 
2187  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
2188  if (new_cdr) {
2189  new_cdr->fn_table->process_dial_begin(new_cdr, caller, peer);
2190  }
2191  }
2192  ao2_unlock(cdr);
2193  ao2_cleanup(cdr);
2194 }
2195 
2196 static int cdr_object_finalize_party_b(void *obj, void *arg, void *data, int flags)
2197 {
2198  struct cdr_object *cdr = obj;
2199 
2200  if (!strcasecmp(cdr->party_b_name, arg)) {
2201 #ifdef AST_DEVMODE
2202  struct ast_channel_snapshot *party_b = data;
2203 
2204  /*
2205  * For sanity's sake we also assert the party_b snapshot
2206  * is consistent with the key.
2207  */
2209  && !strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name));
2210 #endif
2211 
2212  /* Don't transition to the finalized state - let the Party A do
2213  * that when its ready
2214  */
2215  cdr_object_finalize(cdr);
2216  }
2217  return 0;
2218 }
2219 
2220 static int cdr_object_update_party_b(void *obj, void *arg, void *data, int flags)
2221 {
2222  struct cdr_object *cdr = obj;
2223 
2224  if (cdr->fn_table->process_party_b
2225  && !strcasecmp(cdr->party_b_name, arg)) {
2226  struct ast_channel_snapshot *party_b = data;
2227 
2228  /*
2229  * For sanity's sake we also check the party_b snapshot
2230  * for consistency with the key. The callback needs and
2231  * asserts the snapshot to be this way.
2232  */
2233  if (!cdr->party_b.snapshot
2234  || strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name)) {
2236  "CDR for Party A %s(%s) has inconsistent Party B %s name. Message can be ignored but this shouldn't happen.\n",
2237  cdr->linkedid,
2238  cdr->party_a.snapshot->base->name,
2239  cdr->party_b_name);
2240  return 0;
2241  }
2242 
2243  cdr->fn_table->process_party_b(cdr, party_b);
2244  }
2245  return 0;
2246 }
2247 
2248 /*! \brief Determine if we need to add a new CDR based on snapshots */
2249 static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot,
2250  struct ast_channel_snapshot *new_snapshot)
2251 {
2252  /* If we're dead, we don't need a new CDR */
2253  if (!new_snapshot
2256  return 0;
2257  }
2258 
2259  /* Auto-fall through will increment the priority but have no application */
2260  if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
2261  return 0;
2262  }
2263 
2264  if (old_snapshot && !snapshot_cep_changed(old_snapshot, new_snapshot)) {
2265  return 0;
2266  }
2267 
2268  return 1;
2269 }
2270 
2271 /*!
2272  * \brief Handler for channel snapshot update messages
2273  * \param data Passed on
2274  * \param sub The stasis subscription for this message callback
2275  * \param topic The topic this message was published for
2276  * \param message The message
2277  */
2279 {
2280  struct cdr_object *cdr;
2282  struct cdr_object *it_cdr;
2283 
2285  return;
2286  }
2287 
2288  if (update->new_snapshot && !update->old_snapshot) {
2289  cdr = cdr_object_alloc(update->new_snapshot, stasis_message_timestamp(message));
2290  if (!cdr) {
2291  return;
2292  }
2293  cdr->is_root = 1;
2294  ao2_link(active_cdrs_master, cdr);
2295  } else {
2296  cdr = ao2_find(active_cdrs_master, update->new_snapshot->base->uniqueid, OBJ_SEARCH_KEY);
2297  }
2298 
2299  /* Handle Party A */
2300  if (!cdr) {
2301  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->base->name);
2302  ast_assert(0);
2303  } else {
2304  int all_reject = 1;
2305 
2306  ao2_lock(cdr);
2307  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2308  it_cdr->lastevent = *stasis_message_timestamp(message);
2309  if (!it_cdr->fn_table->process_party_a) {
2310  continue;
2311  }
2312  all_reject &= it_cdr->fn_table->process_party_a(it_cdr, update->new_snapshot);
2313  }
2314  if (all_reject && check_new_cdr_needed(update->old_snapshot, update->new_snapshot)) {
2315  /* We're not hung up and we have a new snapshot - we need a new CDR */
2316  struct cdr_object *new_cdr;
2317 
2318  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
2319  if (new_cdr) {
2320  new_cdr->fn_table->process_party_a(new_cdr, update->new_snapshot);
2321  }
2322  }
2323  ao2_unlock(cdr);
2324  }
2325 
2326  if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2327  ao2_lock(cdr);
2328  CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->base->name);
2329  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2330  it_cdr->lastevent = *stasis_message_timestamp(message);
2331  cdr_object_finalize(it_cdr);
2332  }
2333  cdr_object_dispatch(cdr);
2334  ao2_unlock(cdr);
2335 
2336  cdr_all_unlink(cdr);
2337  ao2_unlink(active_cdrs_master, cdr);
2338  }
2339 
2340  /* Handle Party B */
2341  if (update->new_snapshot) {
2343  cdr_object_update_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2344  }
2345 
2346  if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2348  cdr_object_finalize_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2349  }
2350 
2351  ao2_cleanup(cdr);
2352 }
2353 
2357  const struct timeval *lastevent;
2358 };
2359 
2360 /*! \brief Callback used to notify CDRs of a Party B leaving the bridge */
2361 static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, void *data, int flags)
2362 {
2363  struct cdr_object *cdr = obj;
2364  struct bridge_leave_data *leave_data = data;
2365 
2366  if (cdr->fn_table == &bridge_state_fn_table
2367  && !strcmp(cdr->bridge, leave_data->bridge->uniqueid)
2368  && !strcasecmp(cdr->party_b_name, arg)) {
2369  /*
2370  * For sanity's sake we also assert the party_b snapshot
2371  * is consistent with the key.
2372  */
2374  && !strcasecmp(cdr->party_b.snapshot->base->name, leave_data->channel->base->name));
2375 
2376  /* It is our Party B, in our bridge. Set the last event and let the handler
2377  * transition our CDR appropriately when we leave the bridge.
2378  */
2379  cdr->lastevent = *leave_data->lastevent;
2380  cdr_object_finalize(cdr);
2381  }
2382  return 0;
2383 }
2384 
2385 /*! \brief Filter bridge messages based on bridge technology */
2387 {
2388  /* Ignore holding bridge technology messages. We treat this simply as an application
2389  * that a channel enters into.
2390  */
2391  if (!strcmp(bridge->technology, "holding_bridge") && strcmp(bridge->subclass, "parking")) {
2392  return 1;
2393  }
2394  return 0;
2395 }
2396 
2397 /*!
2398  * \brief Handler for when a channel leaves a bridge
2399  * \param data Passed on
2400  * \param sub The stasis subscription for this message callback
2401  * \param topic The topic this message was published for
2402  * \param message The message - hopefully a bridge one!
2403  */
2404 static void handle_bridge_leave_message(void *data, struct stasis_subscription *sub,
2405  struct stasis_message *message)
2406 {
2407  struct ast_bridge_blob *update = stasis_message_data(message);
2408  struct ast_bridge_snapshot *bridge = update->bridge;
2409  struct ast_channel_snapshot *channel = update->channel;
2410  struct cdr_object *cdr;
2411  struct cdr_object *it_cdr;
2412  struct bridge_leave_data leave_data = {
2413  .bridge = bridge,
2414  .channel = channel,
2415  .lastevent = stasis_message_timestamp(message)
2416  };
2417  int left_bridge = 0;
2418 
2419  if (filter_bridge_messages(bridge)) {
2420  return;
2421  }
2422 
2423  if (filter_channel_snapshot(channel)) {
2424  return;
2425  }
2426 
2427  CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n",
2428  channel->base->name,
2429  (unsigned int)leave_data.lastevent->tv_sec,
2430  (unsigned int)leave_data.lastevent->tv_usec);
2431 
2432  cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);
2433  if (!cdr) {
2434  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2435  ast_assert(0);
2436  return;
2437  }
2438 
2439  /* Party A */
2440  ao2_lock(cdr);
2441  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2442  it_cdr->lastevent = *leave_data.lastevent;
2443  if (!it_cdr->fn_table->process_bridge_leave) {
2444  continue;
2445  }
2446  CDR_DEBUG("%p - Processing Bridge Leave for %s\n",
2447  it_cdr, channel->base->name);
2448  if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
2449  ast_string_field_set(it_cdr, bridge, "");
2450  left_bridge = 1;
2451  }
2452  }
2453  ao2_unlock(cdr);
2454 
2455  /* Party B */
2456  if (left_bridge
2457  && strcmp(bridge->subclass, "parking")) {
2459  cdr_object_party_b_left_bridge_cb, (char *) leave_data.channel->base->name,
2460  &leave_data);
2461  }
2462 
2463  ao2_cleanup(cdr);
2464 }
2465 
2466 /*!
2467  * \internal
2468  * \brief Create a new CDR, append it to an existing CDR, and update its snapshots
2469  *
2470  * \note The new CDR will be automatically transitioned to the bridge state
2471  */
2472 static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
2473  struct cdr_object_snapshot *party_b)
2474 {
2475  struct cdr_object *new_cdr;
2476 
2477  new_cdr = cdr_object_create_and_append(cdr, &cdr->lastevent);
2478  if (!new_cdr) {
2479  return;
2480  }
2481  cdr_object_snapshot_copy(&new_cdr->party_b, party_b);
2482  cdr_all_relink(new_cdr);
2484  ast_string_field_set(new_cdr, bridge, cdr->bridge);
2485  cdr_object_transition_state(new_cdr, &bridge_state_fn_table);
2486  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
2487  new_cdr, new_cdr->party_a.snapshot->base->name,
2488  party_b->snapshot->base->name);
2489 }
2490 
2491 /*!
2492  * \brief Process a single \ref bridge_candidate
2493  *
2494  * When a CDR enters a bridge, it needs to make pairings with everyone else
2495  * that it is not currently paired with. This function determines, for the
2496  * CDR for the channel that entered the bridge and the CDR for every other
2497  * channel currently in the bridge, who is Party A and makes new CDRs.
2498  *
2499  * \param cdr The \ref cdr_obj being processed
2500  * \param cand_cdr The \ref cdr_object that is a candidate
2501  *
2502  */
2503 static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
2504 {
2505  struct cdr_object_snapshot *party_a;
2506  struct cdr_object *cand_cdr;
2507 
2508  ao2_lock(base_cand_cdr);
2509 
2510  for (cand_cdr = base_cand_cdr; cand_cdr; cand_cdr = cand_cdr->next) {
2511  /* Skip any records that are not in this bridge */
2512  if (strcmp(cand_cdr->bridge, cdr->bridge)) {
2513  continue;
2514  }
2515 
2516  /* If the candidate is us or someone we've taken on, pass on by */
2517  if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)
2518  || (cdr->party_b.snapshot
2519  && !strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name))) {
2520  break;
2521  }
2522 
2523  party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
2524  /* We're party A - make a new CDR, append it to us, and set the candidate as
2525  * Party B */
2526  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2527  bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);
2528  break;
2529  }
2530 
2531  /* We're Party B. Check if we can add ourselves immediately or if we need
2532  * a new CDR for them (they already have a Party B) */
2533  if (cand_cdr->party_b.snapshot
2534  && strcasecmp(cand_cdr->party_b.snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2535  bridge_candidate_add_to_cdr(cand_cdr, &cdr->party_a);
2536  } else {
2537  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
2538  cand_cdr, cand_cdr->party_a.snapshot->base->name,
2539  cdr->party_a.snapshot->base->name);
2540  cdr_object_snapshot_copy(&cand_cdr->party_b, &cdr->party_a);
2541  cdr_all_relink(cand_cdr);
2542  /* It's possible that this joined at one point and was never chosen
2543  * as party A. Clear their end time, as it would be set in such a
2544  * case.
2545  */
2546  memset(&cand_cdr->end, 0, sizeof(cand_cdr->end));
2547  }
2548 
2549  break;
2550  }
2551 
2552  ao2_unlock(base_cand_cdr);
2553 }
2554 
2555 /*!
2556  * \brief Handle creating bridge pairings for the \ref cdr_object that just
2557  * entered a bridge
2558  * \param cdr The \ref cdr_object that just entered the bridge
2559  * \param bridge The \ref ast_bridge_snapshot representing the bridge it just entered
2560  */
2561 static void handle_bridge_pairings(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge)
2562 {
2563  struct ao2_iterator it_channels;
2564  char *channel_id;
2565 
2566  it_channels = ao2_iterator_init(bridge->channels, 0);
2567  while ((channel_id = ao2_iterator_next(&it_channels))) {
2568  struct cdr_object *cand_cdr;
2569 
2570  cand_cdr = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
2571  if (cand_cdr) {
2572  bridge_candidate_process(cdr, cand_cdr);
2573  ao2_ref(cand_cdr, -1);
2574  }
2575 
2576  ao2_ref(channel_id, -1);
2577  }
2578  ao2_iterator_destroy(&it_channels);
2579 }
2580 
2581 /*! \brief Handle entering into a parking bridge
2582  * \param cdr The CDR to operate on
2583  * \param bridge The bridge the channel just entered
2584  * \param channel The channel snapshot
2585  */
2587  struct ast_bridge_snapshot *bridge,
2588  struct ast_channel_snapshot *channel,
2589  const struct timeval *event_time)
2590 {
2591  int res = 1;
2592  struct cdr_object *it_cdr;
2593  struct cdr_object *new_cdr;
2594 
2595  ao2_lock(cdr);
2596 
2597  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2598  it_cdr->lastevent = *event_time;
2599 
2600  if (it_cdr->fn_table->process_parking_bridge_enter) {
2601  res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
2602  }
2603  if (it_cdr->fn_table->process_party_a) {
2604  CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2605  channel->base->name);
2606  it_cdr->fn_table->process_party_a(it_cdr, channel);
2607  }
2608  }
2609 
2610  if (res) {
2611  /* No one handled it - we need a new one! */
2612  new_cdr = cdr_object_create_and_append(cdr, event_time);
2613  if (new_cdr) {
2614  /* Let the single state transition us to Parked */
2615  cdr_object_transition_state(new_cdr, &single_state_fn_table);
2616  new_cdr->fn_table->process_parking_bridge_enter(new_cdr, bridge, channel);
2617  }
2618  }
2619  ao2_unlock(cdr);
2620 }
2621 
2622 /*! \brief Handle a bridge enter message for a 'normal' bridge
2623  * \param cdr The CDR to operate on
2624  * \param bridge The bridge the channel just entered
2625  * \param channel The channel snapshot
2626  */
2628  struct ast_bridge_snapshot *bridge,
2629  struct ast_channel_snapshot *channel,
2630  const struct timeval *event_time)
2631 {
2633  struct cdr_object *it_cdr;
2634  struct cdr_object *new_cdr;
2635  struct cdr_object *handled_cdr = NULL;
2636 
2637  ao2_lock(cdr);
2638 
2639 try_again:
2640  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2641  it_cdr->lastevent = *event_time;
2642 
2643  if (it_cdr->fn_table->process_party_a) {
2644  CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2645  channel->base->name);
2646  it_cdr->fn_table->process_party_a(it_cdr, channel);
2647  }
2648 
2649  /* Notify all states that they have entered a bridge */
2650  if (it_cdr->fn_table->process_bridge_enter) {
2651  CDR_DEBUG("%p - Processing bridge enter for %s\n", it_cdr,
2652  channel->base->name);
2653  result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
2654  switch (result) {
2656  /* Fall through */
2658  if (!handled_cdr) {
2659  handled_cdr = it_cdr;
2660  }
2661  break;
2662  case BRIDGE_ENTER_NEED_CDR:
2663  /* Pass */
2664  break;
2666  /* We didn't win on any - end this CDR. If someone else comes in later
2667  * that is Party B to this CDR, it can re-activate this CDR.
2668  */
2669  if (!handled_cdr) {
2670  handled_cdr = it_cdr;
2671  }
2672  cdr_object_finalize(cdr);
2673  break;
2674  }
2675  }
2676  }
2677 
2678  /* Create the new matchings, but only for either:
2679  * * The first CDR in the chain that handled it. This avoids issues with
2680  * forked CDRs.
2681  * * If no one handled it, the last CDR in the chain. This would occur if
2682  * a CDR joined a bridge and it wasn't Party A for anyone. We still need
2683  * to make pairings with everyone in the bridge.
2684  */
2685  if (handled_cdr) {
2686  handle_bridge_pairings(handled_cdr, bridge);
2687  } else {
2688  /* Nothing handled it - we need a new one! */
2689  new_cdr = cdr_object_create_and_append(cdr, event_time);
2690  if (new_cdr) {
2691  /* This is guaranteed to succeed: the new CDR is created in the single state
2692  * and will be able to handle the bridge enter message
2693  */
2694  goto try_again;
2695  }
2696  }
2697  ao2_unlock(cdr);
2698 }
2699 
2700 /*!
2701  * \internal
2702  * \brief Handler for Stasis-Core bridge enter messages
2703  * \param data Passed on
2704  * \param sub The stasis subscription for this message callback
2705  * \param topic The topic this message was published for
2706  * \param message The message - hopefully a bridge one!
2707  */
2709  struct stasis_message *message)
2710 {
2711  struct ast_bridge_blob *update = stasis_message_data(message);
2712  struct ast_bridge_snapshot *bridge = update->bridge;
2713  struct ast_channel_snapshot *channel = update->channel;
2714  struct cdr_object *cdr;
2715 
2716  if (filter_bridge_messages(bridge)) {
2717  return;
2718  }
2719 
2720  if (filter_channel_snapshot(channel)) {
2721  return;
2722  }
2723 
2724  CDR_DEBUG("Bridge Enter message for channel %s: %u.%08u\n",
2725  channel->base->name,
2726  (unsigned int)stasis_message_timestamp(message)->tv_sec,
2727  (unsigned int)stasis_message_timestamp(message)->tv_usec);
2728 
2729  cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);
2730  if (!cdr) {
2731  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2732  ast_assert(0);
2733  return;
2734  }
2735 
2736  if (!strcmp(bridge->subclass, "parking")) {
2737  handle_parking_bridge_enter_message(cdr, bridge, channel, stasis_message_timestamp(message));
2738  } else {
2739  handle_standard_bridge_enter_message(cdr, bridge, channel, stasis_message_timestamp(message));
2740  }
2741  ao2_cleanup(cdr);
2742 }
2743 
2744 /*!
2745  * \brief Handler for when a channel is parked
2746  * \param data Passed on
2747  * \param sub The stasis subscription for this message callback
2748  * \param topic The topic this message was published for
2749  * \param message The message about who got parked
2750  * */
2752  struct stasis_message *message)
2753 {
2754  struct ast_parked_call_payload *payload = stasis_message_data(message);
2755  struct ast_channel_snapshot *channel = payload->parkee;
2756  struct cdr_object *cdr;
2757  int unhandled = 1;
2758  struct cdr_object *it_cdr;
2759 
2760  /* Anything other than getting parked will be handled by other updates */
2761  if (payload->event_type != PARKED_CALL) {
2762  return;
2763  }
2764 
2765  /* No one got parked? */
2766  if (!channel) {
2767  return;
2768  }
2769 
2770  if (filter_channel_snapshot(channel)) {
2771  return;
2772  }
2773 
2774  CDR_DEBUG("Parked Call message for channel %s: %u.%08u\n",
2775  channel->base->name,
2776  (unsigned int)stasis_message_timestamp(message)->tv_sec,
2777  (unsigned int)stasis_message_timestamp(message)->tv_usec);
2778 
2779  cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);
2780  if (!cdr) {
2781  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2782  ast_assert(0);
2783  return;
2784  }
2785 
2786  ao2_lock(cdr);
2787 
2788  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2789  it_cdr->lastevent = *stasis_message_timestamp(message);
2790  if (it_cdr->fn_table->process_parked_channel) {
2791  unhandled &= it_cdr->fn_table->process_parked_channel(it_cdr, payload);
2792  }
2793  }
2794 
2795  if (unhandled) {
2796  /* Nothing handled the messgae - we need a new one! */
2797  struct cdr_object *new_cdr;
2798 
2799  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
2800  if (new_cdr) {
2801  /* As the new CDR is created in the single state, it is guaranteed
2802  * to have a function for the parked call message and will handle
2803  * the message */
2804  new_cdr->fn_table->process_parked_channel(new_cdr, payload);
2805  }
2806  }
2807 
2808  ao2_unlock(cdr);
2809 
2810  ao2_cleanup(cdr);
2811 }
2812 
2813 /*!
2814  * \brief Handler for a synchronization message
2815  * \param data Passed on
2816  * \param sub The stasis subscription for this message callback
2817  * \param topic The topic this message was published for
2818  * \param message A blank ao2 object
2819  * */
2821  struct stasis_message *message)
2822 {
2823  return;
2824 }
2825 
2827 {
2828  struct ast_cdr_config *general;
2829  struct module_config *mod_cfg;
2830 
2831  mod_cfg = ao2_global_obj_ref(module_configs);
2832  if (!mod_cfg) {
2833  return NULL;
2834  }
2835  general = ao2_bump(mod_cfg->general);
2836  ao2_cleanup(mod_cfg);
2837  return general;
2838 }
2839 
2841 {
2842  struct module_config *mod_cfg;
2843 
2844  if (!config) {
2845  return;
2846  }
2847 
2848  mod_cfg = ao2_global_obj_ref(module_configs);
2849  if (!mod_cfg) {
2850  return;
2851  }
2852 
2853  ao2_replace(mod_cfg->general, config);
2854 
2855  cdr_set_debug_mode(mod_cfg);
2857 
2858  ao2_cleanup(mod_cfg);
2859 }
2860 
2862 {
2863  return is_cdr_flag_set(CDR_ENABLED);
2864 }
2865 
2867 {
2868  int success = -1;
2869  struct cdr_beitem *i = NULL;
2870 
2872  AST_RWLIST_TRAVERSE(&be_list, i, list) {
2873  if (!strcasecmp(name, i->name)) {
2874  ast_debug(3, "Suspending CDR backend %s\n", i->name);
2875  i->suspended = 1;
2876  success = 0;
2877  }
2878  }
2880 
2881  return success;
2882 }
2883 
2885 {
2886  int success = -1;
2887  struct cdr_beitem *i = NULL;
2888 
2890  AST_RWLIST_TRAVERSE(&be_list, i, list) {
2891  if (!strcasecmp(name, i->name)) {
2892  ast_debug(3, "Unsuspending CDR backend %s\n", i->name);
2893  i->suspended = 0;
2894  success = 0;
2895  }
2896  }
2898 
2899  return success;
2900 }
2901 
2902 static int cdr_generic_register(struct be_list *generic_list, const char *name, const char *desc, ast_cdrbe be)
2903 {
2904  struct cdr_beitem *i;
2905  struct cdr_beitem *cur;
2906 
2907  if (!name) {
2908  return -1;
2909  }
2910 
2911  if (!be) {
2912  ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
2913 
2914  return -1;
2915  }
2916 
2917  i = ast_calloc(1, sizeof(*i));
2918  if (!i) {
2919  return -1;
2920  }
2921 
2922  i->be = be;
2923  ast_copy_string(i->name, name, sizeof(i->name));
2924  ast_copy_string(i->desc, desc, sizeof(i->desc));
2925 
2926  AST_RWLIST_WRLOCK(generic_list);
2927  AST_RWLIST_TRAVERSE(generic_list, cur, list) {
2928  if (!strcasecmp(name, cur->name)) {
2929  ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
2930  AST_RWLIST_UNLOCK(generic_list);
2931  ast_free(i);
2932 
2933  return -1;
2934  }
2935  }
2936 
2937  AST_RWLIST_INSERT_HEAD(generic_list, i, list);
2938  AST_RWLIST_UNLOCK(generic_list);
2939 
2940  return 0;
2941 }
2942 
2943 int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
2944 {
2945  return cdr_generic_register(&be_list, name, desc, be);
2946 }
2947 
2948 int ast_cdr_modifier_register(const char *name, const char *desc, ast_cdrbe be)
2949 {
2950  return cdr_generic_register((struct be_list *)&mo_list, name, desc, be);
2951 }
2952 
2953 static int ast_cdr_generic_unregister(struct be_list *generic_list, const char *name)
2954 {
2955  struct cdr_beitem *match = NULL;
2956  int active_count;
2957 
2958  AST_RWLIST_WRLOCK(generic_list);
2959  AST_RWLIST_TRAVERSE(generic_list, match, list) {
2960  if (!strcasecmp(name, match->name)) {
2961  break;
2962  }
2963  }
2964 
2965  if (!match) {
2966  AST_RWLIST_UNLOCK(generic_list);
2967  return 0;
2968  }
2969 
2970  active_count = ao2_container_count(active_cdrs_master);
2971 
2972  if (!match->suspended && active_count != 0) {
2973  AST_RWLIST_UNLOCK(generic_list);
2974  ast_log(AST_LOG_WARNING, "Unable to unregister CDR backend %s; %d CDRs are still active\n",
2975  name, active_count);
2976  return -1;
2977  }
2978 
2979  AST_RWLIST_REMOVE(generic_list, match, list);
2980  AST_RWLIST_UNLOCK(generic_list);
2981 
2982  ast_verb(2, "Unregistered '%s' CDR backend\n", name);
2983  ast_free(match);
2984 
2985  return 0;
2986 }
2987 
2988 int ast_cdr_unregister(const char *name)
2989 {
2990  return ast_cdr_generic_unregister(&be_list, name);
2991 }
2992 
2994 {
2995  return ast_cdr_generic_unregister((struct be_list *)&mo_list, name);
2996 }
2997 
2998 struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
2999 {
3000  struct ast_cdr *newcdr;
3001 
3002  if (!cdr) {
3003  return NULL;
3004  }
3005  newcdr = ast_cdr_alloc();
3006  if (!newcdr) {
3007  return NULL;
3008  }
3009 
3010  *newcdr = *cdr;
3012  copy_variables(&newcdr->varshead, &cdr->varshead);
3013  newcdr->next = NULL;
3014 
3015  return newcdr;
3016 }
3017 
3018 static const char *cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
3019 {
3020  struct ast_var_t *variables;
3021 
3022  if (ast_strlen_zero(name)) {
3023  return NULL;
3024  }
3025 
3026  AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
3027  if (!strcasecmp(name, ast_var_name(variables))) {
3028  return ast_var_value(variables);
3029  }
3030  }
3031 
3032  return NULL;
3033 }
3034 
3035 static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
3036 {
3037  if (fmt == NULL) { /* raw mode */
3038  snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec);
3039  } else {
3040  buf[0] = '\0';/* Ensure the buffer is initialized. */
3041  if (when.tv_sec) {
3042  struct ast_tm tm;
3043 
3044  ast_localtime(&when, &tm, NULL);
3045  ast_strftime(buf, bufsize, fmt, &tm);
3046  }
3047  }
3048 }
3049 
3050 void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
3051 {
3052  const char *fmt = "%Y-%m-%d %T";
3053  const char *varbuf;
3054 
3055  if (!cdr) {
3056  return;
3057  }
3058 
3059  *ret = NULL;
3060 
3061  if (!strcasecmp(name, "clid")) {
3062  ast_copy_string(workspace, cdr->clid, workspacelen);
3063  } else if (!strcasecmp(name, "src")) {
3064  ast_copy_string(workspace, cdr->src, workspacelen);
3065  } else if (!strcasecmp(name, "dst")) {
3066  ast_copy_string(workspace, cdr->dst, workspacelen);
3067  } else if (!strcasecmp(name, "dcontext")) {
3068  ast_copy_string(workspace, cdr->dcontext, workspacelen);
3069  } else if (!strcasecmp(name, "channel")) {
3070  ast_copy_string(workspace, cdr->channel, workspacelen);
3071  } else if (!strcasecmp(name, "dstchannel")) {
3072  ast_copy_string(workspace, cdr->dstchannel, workspacelen);
3073  } else if (!strcasecmp(name, "lastapp")) {
3074  ast_copy_string(workspace, cdr->lastapp, workspacelen);
3075  } else if (!strcasecmp(name, "lastdata")) {
3076  ast_copy_string(workspace, cdr->lastdata, workspacelen);
3077  } else if (!strcasecmp(name, "start")) {
3078  cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
3079  } else if (!strcasecmp(name, "answer")) {
3080  cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
3081  } else if (!strcasecmp(name, "end")) {
3082  cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
3083  } else if (!strcasecmp(name, "duration")) {
3084  snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
3085  } else if (!strcasecmp(name, "billsec")) {
3086  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);
3087  } else if (!strcasecmp(name, "disposition")) {
3088  if (raw) {
3089  snprintf(workspace, workspacelen, "%ld", cdr->disposition);
3090  } else {
3091  ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
3092  }
3093  } else if (!strcasecmp(name, "amaflags")) {
3094  if (raw) {
3095  snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
3096  } else {
3097  ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
3098  }
3099  } else if (!strcasecmp(name, "accountcode")) {
3100  ast_copy_string(workspace, cdr->accountcode, workspacelen);
3101  } else if (!strcasecmp(name, "peeraccount")) {
3102  ast_copy_string(workspace, cdr->peeraccount, workspacelen);
3103  } else if (!strcasecmp(name, "uniqueid")) {
3104  ast_copy_string(workspace, cdr->uniqueid, workspacelen);
3105  } else if (!strcasecmp(name, "linkedid")) {
3106  ast_copy_string(workspace, cdr->linkedid, workspacelen);
3107  } else if (!strcasecmp(name, "userfield")) {
3108  ast_copy_string(workspace, cdr->userfield, workspacelen);
3109  } else if (!strcasecmp(name, "sequence")) {
3110  snprintf(workspace, workspacelen, "%d", cdr->sequence);
3111  } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
3112  ast_copy_string(workspace, varbuf, workspacelen);
3113  } else {
3114  workspace[0] = '\0';
3115  }
3116 
3117  if (!ast_strlen_zero(workspace)) {
3118  *ret = workspace;
3119  }
3120 }
3121 
3122 /*!
3123  * \internal
3124  * \brief Callback that finds all CDRs that reference a particular channel by name
3125  */
3126 static int cdr_object_select_all_by_name_cb(void *obj, void *arg, int flags)
3127 {
3128  struct cdr_object *cdr = obj;
3129  const char *name = arg;
3130 
3131  if (!strcasecmp(cdr->party_a.snapshot->base->name, name) ||
3132  (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->base->name, name))) {
3133  return CMP_MATCH;
3134  }
3135  return 0;
3136 }
3137 
3138 /*!
3139  * \internal
3140  * \brief Callback that finds a CDR by channel name
3141  */
3142 static int cdr_object_get_by_name_cb(void *obj, void *arg, int flags)
3143 {
3144  struct cdr_object *cdr = obj;
3145  const char *name = arg;
3146 
3147  if (!strcasecmp(cdr->party_a.snapshot->base->name, name)) {
3148  return CMP_MATCH;
3149  }
3150  return 0;
3151 }
3152 
3153 /* Read Only CDR variables */
3154 static const char * const cdr_readonly_vars[] = {
3155  "clid",
3156  "src",
3157  "dst",
3158  "dcontext",
3159  "channel",
3160  "dstchannel",
3161  "lastapp",
3162  "lastdata",
3163  "start",
3164  "answer",
3165  "end",
3166  "duration",
3167  "billsec",
3168  "disposition",
3169  "amaflags",
3170  "accountcode",
3171  "uniqueid",
3172  "linkedid",
3173  "userfield",
3174  "sequence",
3175  NULL
3176 };
3177 
3178 int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
3179 {
3180  struct cdr_object *cdr;
3181  struct cdr_object *it_cdr;
3182  struct ao2_iterator *it_cdrs;
3183  char *arg = ast_strdupa(channel_name);
3184  int x;
3185 
3186  for (x = 0; cdr_readonly_vars[x]; x++) {
3187  if (!strcasecmp(name, cdr_readonly_vars[x])) {
3188  ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
3189  return -1;
3190  }
3191  }
3192 
3193  it_cdrs = ao2_callback(active_cdrs_master, OBJ_MULTIPLE, cdr_object_select_all_by_name_cb, arg);
3194  if (!it_cdrs) {
3195  ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3196  return -1;
3197  }
3198 
3199  for (; (cdr = ao2_iterator_next(it_cdrs)); ao2_unlock(cdr), ao2_cleanup(cdr)) {
3200  ao2_lock(cdr);
3201  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3202  struct varshead *headp = NULL;
3203 
3204  if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3205  continue;
3206  }
3207  if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->base->name)) {
3208  headp = &it_cdr->party_a.variables;
3209  } else if (it_cdr->party_b.snapshot
3210  && !strcasecmp(channel_name, it_cdr->party_b.snapshot->base->name)) {
3211  headp = &it_cdr->party_b.variables;
3212  }
3213  if (headp) {
3214  set_variable(headp, name, value);
3215  }
3216  }
3217  }
3218  ao2_iterator_destroy(it_cdrs);
3219 
3220  return 0;
3221 }
3222 
3223 /*!
3224  * \brief Format a variable on a \ref cdr_object
3225  */
3226 static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
3227 {
3228  struct ast_var_t *variable;
3229 
3230  AST_LIST_TRAVERSE(&cdr->party_a.variables, variable, entries) {
3231  if (!strcasecmp(name, ast_var_name(variable))) {
3232  ast_copy_string(value, ast_var_value(variable), length);
3233  return;
3234  }
3235  }
3236 
3237  *value = '\0';
3238 }
3239 
3240 /*!
3241  * \brief Format one of the standard properties on a \ref cdr_object
3242  */
3243 static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
3244 {
3245  struct ast_channel_snapshot *party_a = cdr_obj->party_a.snapshot;
3246  struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;
3247 
3248  if (!strcasecmp(name, "clid")) {
3249  ast_callerid_merge(value, length, party_a->caller->name, party_a->caller->number, "");
3250  } else if (!strcasecmp(name, "src")) {
3251  ast_copy_string(value, party_a->caller->number, length);
3252  } else if (!strcasecmp(name, "dst")) {
3253  ast_copy_string(value, party_a->dialplan->exten, length);
3254  } else if (!strcasecmp(name, "dcontext")) {
3255  ast_copy_string(value, party_a->dialplan->context, length);
3256  } else if (!strcasecmp(name, "channel")) {
3257  ast_copy_string(value, party_a->base->name, length);
3258  } else if (!strcasecmp(name, "dstchannel")) {
3259  if (party_b) {
3260  ast_copy_string(value, party_b->base->name, length);
3261  } else {
3262  ast_copy_string(value, "", length);
3263  }
3264  } else if (!strcasecmp(name, "lastapp")) {
3265  ast_copy_string(value, party_a->dialplan->appl, length);
3266  } else if (!strcasecmp(name, "lastdata")) {
3267  ast_copy_string(value, party_a->dialplan->data, length);
3268  } else if (!strcasecmp(name, "start")) {
3269  cdr_get_tv(cdr_obj->start, NULL, value, length);
3270  } else if (!strcasecmp(name, "answer")) {
3271  cdr_get_tv(cdr_obj->answer, NULL, value, length);
3272  } else if (!strcasecmp(name, "end")) {
3273  cdr_get_tv(cdr_obj->end, NULL, value, length);
3274  } else if (!strcasecmp(name, "duration")) {
3275  snprintf(value, length, "%ld", cdr_object_get_duration(cdr_obj));
3276  } else if (!strcasecmp(name, "billsec")) {
3277  snprintf(value, length, "%ld", cdr_object_get_billsec(cdr_obj));
3278  } else if (!strcasecmp(name, "disposition")) {
3279  snprintf(value, length, "%u", cdr_obj->disposition);
3280  } else if (!strcasecmp(name, "amaflags")) {
3281  snprintf(value, length, "%d", party_a->amaflags);
3282  } else if (!strcasecmp(name, "accountcode")) {
3283  ast_copy_string(value, party_a->base->accountcode, length);
3284  } else if (!strcasecmp(name, "peeraccount")) {
3285  if (party_b) {
3286  ast_copy_string(value, party_b->base->accountcode, length);
3287  } else {
3288  ast_copy_string(value, "", length);
3289  }
3290  } else if (!strcasecmp(name, "uniqueid")) {
3291  ast_copy_string(value, party_a->base->uniqueid, length);
3292  } else if (!strcasecmp(name, "linkedid")) {
3293  ast_copy_string(value, cdr_obj->linkedid, length);
3294  } else if (!strcasecmp(name, "userfield")) {
3295  ast_copy_string(value, cdr_obj->party_a.userfield, length);
3296  } else if (!strcasecmp(name, "sequence")) {
3297  snprintf(value, length, "%u", cdr_obj->sequence);
3298  } else {
3299  return 1;
3300  }
3301 
3302  return 0;
3303 }
3304 
3305 /*! \internal
3306  * \brief Look up and retrieve a CDR object by channel name
3307  * \param name The name of the channel
3308  * \retval NULL on error
3309  * \retval The \ref cdr_object for the channel on success, with the reference
3310  * count bumped by one.
3311  */
3312 static struct cdr_object *cdr_object_get_by_name(const char *name)
3313 {
3314  char *param;
3315 
3316  if (ast_strlen_zero(name)) {
3317  return NULL;
3318  }
3319 
3320  param = ast_strdupa(name);
3321  return ao2_callback(active_cdrs_master, 0, cdr_object_get_by_name_cb, param);
3322 }
3323 
3324 int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
3325 {
3326  struct cdr_object *cdr;
3327  struct cdr_object *cdr_obj;
3328 
3329  if (ast_strlen_zero(name)) {
3330  return 1;
3331  }
3332 
3333  cdr = cdr_object_get_by_name(channel_name);
3334  if (!cdr) {
3335  ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3336  return 1;
3337  }
3338 
3339  ao2_lock(cdr);
3340 
3341  cdr_obj = cdr->last;
3342  if (cdr_object_format_property(cdr_obj, name, value, length)) {
3343  /* Property failed; attempt variable */
3344  cdr_object_format_var_internal(cdr_obj, name, value, length);
3345  }
3346 
3347  ao2_unlock(cdr);
3348 
3349  ao2_cleanup(cdr);
3350  return 0;
3351 }
3352 
3353 int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
3354 {
3355  struct cdr_object *cdr;
3356  struct cdr_object *it_cdr;
3357  struct ast_var_t *variable;
3358  const char *var;
3359  char workspace[256];
3360  int total = 0, x = 0, i;
3361 
3362  cdr = cdr_object_get_by_name(channel_name);
3363  if (!cdr) {
3365  ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3366  }
3367  return 0;
3368  }
3369 
3370  ast_str_reset(*buf);
3371 
3372  ao2_lock(cdr);
3373  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3374  if (++x > 1) {
3375  ast_str_append(buf, 0, "\n");
3376  }
3377 
3378  AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
3379  if (!(var = ast_var_name(variable))) {
3380  continue;
3381  }
3382 
3383  if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
3384  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3385  break;
3386  }
3387 
3388  total++;
3389  }
3390 
3391  for (i = 0; cdr_readonly_vars[i]; i++) {
3392  if (cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace))) {
3393  /* Unhandled read-only CDR variable. */
3394  ast_assert(0);
3395  continue;
3396  }
3397 
3398  if (!ast_strlen_zero(workspace)
3399  && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
3400  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3401  break;
3402  }
3403  total++;
3404  }
3405  }
3406  ao2_unlock(cdr);
3407  ao2_cleanup(cdr);
3408  return total;
3409 }
3410 
3411 void ast_cdr_free(struct ast_cdr *cdr)
3412 {
3413  while (cdr) {
3414  struct ast_cdr *next = cdr->next;
3415 
3416  free_variables(&cdr->varshead);
3417  ast_free(cdr);
3418  cdr = next;
3419  }
3420 }
3421 
3422 struct ast_cdr *ast_cdr_alloc(void)
3423 {
3424  struct ast_cdr *x;
3425 
3426  x = ast_calloc(1, sizeof(*x));
3427  return x;
3428 }
3429 
3430 const char *ast_cdr_disp2str(int disposition)
3431 {
3432  switch (disposition) {
3433  case AST_CDR_NULL:
3434  return "NO ANSWER"; /* by default, for backward compatibility */
3435  case AST_CDR_NOANSWER:
3436  return "NO ANSWER";
3437  case AST_CDR_FAILED:
3438  return "FAILED";
3439  case AST_CDR_BUSY:
3440  return "BUSY";
3441  case AST_CDR_ANSWERED:
3442  return "ANSWERED";
3443  case AST_CDR_CONGESTION:
3444  return "CONGESTION";
3445  }
3446  return "UNKNOWN";
3447 }
3448 
3450  const char *channel_name;
3451  const char *userfield;
3452 };
3453 
3454 /*! \brief Callback used to update the userfield on Party B on all CDRs */
3455 static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, void *data, int flags)
3456 {
3457  struct cdr_object *cdr = obj;
3458 
3459  if ((cdr->fn_table != &finalized_state_fn_table || !cdr->next)
3460  && !strcasecmp(cdr->party_b_name, arg)) {
3461  struct party_b_userfield_update *info = data;
3462 
3463  /*
3464  * For sanity's sake we also assert the party_b snapshot
3465  * is consistent with the key.
3466  */
3468  && !strcasecmp(cdr->party_b.snapshot->base->name, info->channel_name));
3469 
3471  sizeof(cdr->party_b.userfield));
3472  }
3473 
3474  return 0;
3475 }
3476 
3477 void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
3478 {
3479  struct cdr_object *cdr;
3480  struct party_b_userfield_update party_b_info = {
3482  .userfield = userfield,
3483  };
3484  struct cdr_object *it_cdr;
3485 
3486  /* Handle Party A */
3487  cdr = cdr_object_get_by_name(channel_name);
3488  if (cdr) {
3489  ao2_lock(cdr);
3490  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3491  if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3492  continue;
3493  }
3494  ast_copy_string(it_cdr->party_a.userfield, userfield,
3495  sizeof(it_cdr->party_a.userfield));
3496  }
3497  ao2_unlock(cdr);
3498  }
3499 
3500  /* Handle Party B */
3503  &party_b_info);
3504 
3505  ao2_cleanup(cdr);
3506 }
3507 
3508 static void post_cdr(struct ast_cdr *cdr)
3509 {
3510  struct module_config *mod_cfg;
3511  struct cdr_beitem *i;
3512 
3513  mod_cfg = ao2_global_obj_ref(module_configs);
3514  if (!mod_cfg) {
3515  return;
3516  }
3517 
3518  for (; cdr ; cdr = cdr->next) {
3519  /* For people, who don't want to see unanswered single-channel events */
3520  if (!ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) &&
3521  cdr->disposition < AST_CDR_ANSWERED &&
3523  ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel);
3524  continue;
3525  }
3526 
3527  /* Modify CDR's */
3529  AST_RWLIST_TRAVERSE(&mo_list, i, list) {
3530  i->be(cdr);
3531  }
3533 
3534  if (ast_test_flag(cdr, AST_CDR_FLAG_DISABLE)) {
3535  continue;
3536  }
3538  AST_RWLIST_TRAVERSE(&be_list, i, list) {
3539  if (!i->suspended) {
3540  i->be(cdr);
3541  }
3542  }
3544  }
3545  ao2_cleanup(mod_cfg);
3546 }
3547 
3548 int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
3549 {
3550  struct cdr_object *cdr;
3551  struct cdr_object *it_cdr;
3552 
3553  cdr = cdr_object_get_by_name(channel_name);
3554  if (!cdr) {
3555  return -1;
3556  }
3557 
3558  ao2_lock(cdr);
3559  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3560  if (it_cdr->fn_table == &finalized_state_fn_table) {
3561  continue;
3562  }
3563  /* Note: in general, set the flags on both the CDR record as well as the
3564  * Party A. Sometimes all we have is the Party A to look at.
3565  */
3566  ast_set_flag(&it_cdr->flags, option);
3567  ast_set_flag(&it_cdr->party_a, option);
3568  }
3569  ao2_unlock(cdr);
3570 
3571  ao2_cleanup(cdr);
3572  return 0;
3573 }
3574 
3575 int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
3576 {
3577  struct cdr_object *cdr;
3578  struct cdr_object *it_cdr;
3579 
3580  cdr = cdr_object_get_by_name(channel_name);
3581  if (!cdr) {
3582  return -1;
3583  }
3584 
3585  ao2_lock(cdr);
3586  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3587  if (it_cdr->fn_table == &finalized_state_fn_table) {
3588  continue;
3589  }
3590  ast_clear_flag(&it_cdr->flags, option);
3591  }
3592  ao2_unlock(cdr);
3593 
3594  ao2_cleanup(cdr);
3595  return 0;
3596 }
3597 
3598 int ast_cdr_reset(const char *channel_name, int keep_variables)
3599 {
3600  struct cdr_object *cdr;
3601  struct ast_var_t *vardata;
3602  struct cdr_object *it_cdr;
3603 
3604  cdr = cdr_object_get_by_name(channel_name);
3605  if (!cdr) {
3606  return -1;
3607  }
3608 
3609  ao2_lock(cdr);
3610  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3611  /* clear variables */
3612  if (!keep_variables) {
3613  while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
3614  ast_var_delete(vardata);
3615  }
3616  if (cdr->party_b.snapshot) {
3617  while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
3618  ast_var_delete(vardata);
3619  }
3620  }
3621  }
3622 
3623  /* Reset to initial state */
3624  memset(&it_cdr->start, 0, sizeof(it_cdr->start));
3625  memset(&it_cdr->end, 0, sizeof(it_cdr->end));
3626  memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
3627  it_cdr->start = ast_tvnow();
3628  it_cdr->lastevent = it_cdr->start;
3630  }
3631  ao2_unlock(cdr);
3632 
3633  ao2_cleanup(cdr);
3634  return 0;
3635 }
3636 
3637 int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
3638 {
3639  RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3640  struct cdr_object *new_cdr;
3641  struct cdr_object *it_cdr;
3642  struct cdr_object *cdr_obj;
3643 
3644  if (!cdr) {
3645  return -1;
3646  }
3647 
3648  {
3649  SCOPED_AO2LOCK(lock, cdr);
3650  struct timeval now = ast_tvnow();
3651 
3652  cdr_obj = cdr->last;
3653  if (cdr_obj->fn_table == &finalized_state_fn_table) {
3654  /* If the last CDR in the chain is finalized, don't allow a fork -
3655  * things are already dying at this point
3656  */
3657  return -1;
3658  }
3659 
3660  /* Copy over the basic CDR information. The Party A information is
3661  * copied over automatically as part of the append
3662  */
3663  ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->base->name);
3664  new_cdr = cdr_object_create_and_append(cdr, &now);
3665  if (!new_cdr) {
3666  return -1;
3667  }
3668  new_cdr->fn_table = cdr_obj->fn_table;
3669  ast_string_field_set(new_cdr, bridge, cdr->bridge);
3670  ast_string_field_set(new_cdr, appl, cdr->appl);
3671  ast_string_field_set(new_cdr, data, cdr->data);
3672  ast_string_field_set(new_cdr, context, cdr->context);
3673  ast_string_field_set(new_cdr, exten, cdr->exten);
3674  new_cdr->flags = cdr->flags;
3675  /* Explicitly clear the AST_CDR_LOCK_APP flag - we want
3676  * the application to be changed on the new CDR if the
3677  * dialplan demands it
3678  */
3680 
3681  /* If there's a Party B, copy it over as well */
3682  if (cdr_obj->party_b.snapshot) {
3683  new_cdr->party_b.snapshot = cdr_obj->party_b.snapshot;
3684  ao2_ref(new_cdr->party_b.snapshot, +1);
3685  cdr_all_relink(new_cdr);
3686  strcpy(new_cdr->party_b.userfield, cdr_obj->party_b.userfield);
3687  new_cdr->party_b.flags = cdr_obj->party_b.flags;
3688  if (ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3689  copy_variables(&new_cdr->party_b.variables, &cdr_obj->party_b.variables);
3690  }
3691  }
3692  new_cdr->start = cdr_obj->start;
3693  new_cdr->answer = cdr_obj->answer;
3694  new_cdr->lastevent = ast_tvnow();
3695 
3696  /* Modify the times based on the flags passed in */
3698  && new_cdr->party_a.snapshot->state == AST_STATE_UP) {
3699  new_cdr->answer = ast_tvnow();
3700  }
3701  if (ast_test_flag(options, AST_CDR_FLAG_RESET)) {
3702  new_cdr->answer = ast_tvnow();
3703  new_cdr->start = ast_tvnow();
3704  }
3705 
3706  /* Create and append, by default, copies over the variables */
3707  if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3708  free_variables(&new_cdr->party_a.variables);
3709  }
3710 
3711  /* Finalize any current CDRs */
3712  if (ast_test_flag(options, AST_CDR_FLAG_FINALIZE)) {
3713  for (it_cdr = cdr; it_cdr != new_cdr; it_cdr = it_cdr->next) {
3714  if (it_cdr->fn_table == &finalized_state_fn_table) {
3715  continue;
3716  }
3717  /* Force finalization on the CDR. This will bypass any checks for
3718  * end before 'h' extension.
3719  */
3720  cdr_object_finalize(it_cdr);
3721  cdr_object_transition_state(it_cdr, &finalized_state_fn_table);
3722  }
3723  }
3724  }
3725 
3726  return 0;
3727 }
3728 
3729 /*! \note Don't call without cdr_batch_lock */
3730 static void reset_batch(void)
3731 {
3732  batch->size = 0;
3733  batch->head = NULL;
3734  batch->tail = NULL;
3735 }
3736 
3737 /*! \note Don't call without cdr_batch_lock */
3738 static int init_batch(void)
3739 {
3740  /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
3741  if (!(batch = ast_malloc(sizeof(*batch))))
3742  return -1;
3743 
3744  reset_batch();
3745 
3746  return 0;
3747 }
3748 
3749 static void *do_batch_backend_process(void *data)
3750 {
3751  struct cdr_batch_item *processeditem;
3752  struct cdr_batch_item *batchitem = data;
3753 
3754  /* Push each CDR into storage mechanism(s) and free all the memory */
3755  while (batchitem) {
3756  post_cdr(batchitem->cdr);
3757  ast_cdr_free(batchitem->cdr);
3758  processeditem = batchitem;
3759  batchitem = batchitem->next;
3760  ast_free(processeditem);
3761  }
3762 
3763  return NULL;
3764 }
3765 
3766 static void cdr_submit_batch(int do_shutdown)
3767 {
3768  struct module_config *mod_cfg;
3769  struct cdr_batch_item *oldbatchitems = NULL;
3770  pthread_t batch_post_thread = AST_PTHREADT_NULL;
3771 
3772  /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
3773  if (!batch || !batch->head) {
3774  return;
3775  }
3776 
3777  /* move the old CDRs aside, and prepare a new CDR batch */
3779  oldbatchitems = batch->head;
3780  reset_batch();
3782 
3783  mod_cfg = ao2_global_obj_ref(module_configs);
3784 
3785  /* if configured, spawn a new thread to post these CDRs,
3786  also try to save as much as possible if we are shutting down safely */
3787  if (!mod_cfg
3789  || do_shutdown) {
3790  ast_debug(1, "CDR single-threaded batch processing begins now\n");
3791  do_batch_backend_process(oldbatchitems);
3792  } else {
3793  if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
3794  ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
3795  do_batch_backend_process(oldbatchitems);
3796  } else {
3797  ast_debug(1, "CDR multi-threaded batch processing begins now\n");
3798  }
3799  }
3800 
3801  ao2_cleanup(mod_cfg);
3802 }
3803 
3804 static int submit_scheduled_batch(const void *data)
3805 {
3806  struct module_config *mod_cfg;
3807  int nextms;
3808 
3809  cdr_submit_batch(0);
3810 
3811  mod_cfg = ao2_global_obj_ref(module_configs);
3812  if (!mod_cfg) {
3813  return 0;
3814  }
3815 
3816  /* Calculate the next scheduled interval */
3817  nextms = mod_cfg->general->batch_settings.time * 1000;
3818 
3819  ao2_cleanup(mod_cfg);
3820 
3821  return nextms;
3822 }
3823 
3824 /*! Do not hold the batch lock while calling this function */
3825 static void start_batch_mode(void)
3826 {
3827  /* Prevent two deletes from happening at the same time */
3829  /* this is okay since we are not being called from within the scheduler */
3830  AST_SCHED_DEL(sched, cdr_sched);
3831  /* schedule the submission to occur ASAP (1 ms) */
3834 
3835  /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
3839 }
3840 
3841 static void cdr_detach(struct ast_cdr *cdr)
3842 {
3843  struct cdr_batch_item *newtail;
3844  int curr;
3845  RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3846  int submit_batch = 0;
3847 
3848  if (!cdr) {
3849  return;
3850  }
3851 
3852  /* maybe they disabled CDR stuff completely, so just drop it */
3853  if (!mod_cfg || !ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
3854  ast_debug(1, "Dropping CDR !\n");
3855  ast_cdr_free(cdr);
3856  return;
3857  }
3858 
3859  /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
3860  if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
3861  post_cdr(cdr);
3862  ast_cdr_free(cdr);
3863  return;
3864  }
3865 
3866  /* otherwise, each CDR gets put into a batch list (at the end) */
3867  ast_debug(1, "CDR detaching from this thread\n");
3868 
3869  /* we'll need a new tail for every CDR */
3870  if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
3871  post_cdr(cdr);
3872  ast_cdr_free(cdr);
3873  return;
3874  }
3875 
3876  /* don't traverse a whole list (just keep track of the tail) */
3878  if (!batch)
3879  init_batch();
3880  if (!batch->head) {
3881  /* new batch is empty, so point the head at the new tail */
3882  batch->head = newtail;
3883  } else {
3884  /* already got a batch with something in it, so just append a new tail */
3885  batch->tail->next = newtail;
3886  }
3887  newtail->cdr = cdr;
3888  batch->tail = newtail;
3889  curr = batch->size++;
3890 
3891  /* if we have enough stuff to post, then do it */
3892  if (curr >= (mod_cfg->general->batch_settings.size - 1)) {
3893  submit_batch = 1;
3894  }
3896 
3897  /* Don't submit a batch with cdr_batch_lock held */
3898  if (submit_batch) {
3899  start_batch_mode();
3900  }
3901 }
3902 
3903 static void *do_cdr(void *data)
3904 {
3905  struct timespec timeout;
3906  int schedms;
3907  int numevents = 0;
3908 
3909  for (;;) {
3910  struct timeval now;
3911  schedms = ast_sched_wait(sched);
3912  /* this shouldn't happen, but provide a 1 second default just in case */
3913  if (schedms < 0)
3914  schedms = 1000;
3915  now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
3916  timeout.tv_sec = now.tv_sec;
3917  timeout.tv_nsec = now.tv_usec * 1000;
3918  /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
3921  numevents = ast_sched_runq(sched);
3923  ast_debug(2, "Processed %d CDR batches from the run queue\n", numevents);
3924  }
3925 
3926  return NULL;
3927 }
3928 
3929 static char *handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3930 {
3931  struct module_config *mod_cfg;
3932 
3933  switch (cmd) {
3934  case CLI_INIT:
3935  e->command = "cdr set debug [on|off]";
3936  e->usage = "Enable or disable extra debugging in the CDR Engine. Note\n"
3937  "that this will dump debug information to the VERBOSE setting\n"
3938  "and should only be used when debugging information from the\n"
3939  "CDR engine is needed.\n";
3940  return NULL;
3941  case CLI_GENERATE:
3942  return NULL;
3943  }
3944 
3945  if (a->argc != 4) {
3946  return CLI_SHOWUSAGE;
3947  }
3948 
3949  mod_cfg = ao2_global_obj_ref(module_configs);
3950  if (!mod_cfg) {
3951  ast_cli(a->fd, "Could not set CDR debugging mode\n");
3952  return CLI_SUCCESS;
3953  }
3954  if (!strcasecmp(a->argv[3], "on")
3955  && !ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3956  ast_set_flag(&mod_cfg->general->settings, CDR_DEBUG);
3957  ast_cli(a->fd, "CDR debugging enabled\n");
3958  } else if (!strcasecmp(a->argv[3], "off")
3959  && ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3961  ast_cli(a->fd, "CDR debugging disabled\n");
3962  }
3963  cdr_set_debug_mode(mod_cfg);
3964  ao2_cleanup(mod_cfg);
3965 
3966  return CLI_SUCCESS;
3967 }
3968 
3969 /*! \brief Complete user input for 'cdr show' */
3970 static char *cli_complete_show(struct ast_cli_args *a)
3971 {
3972  int wordlen = strlen(a->word);
3973  struct ao2_iterator it_cdrs;
3974  struct cdr_object *cdr;
3975 
3976  it_cdrs = ao2_iterator_init(active_cdrs_master, 0);
3977  while ((cdr = ao2_iterator_next(&it_cdrs))) {
3978  if (!strncasecmp(a->word, cdr->party_a.snapshot->base->name, wordlen)) {
3980  ao2_ref(cdr, -1);
3981  break;
3982  }
3983  }
3984  ao2_ref(cdr, -1);
3985  }
3986  ao2_iterator_destroy(&it_cdrs);
3987 
3988  return NULL;
3989 }
3990 
3991 static void cli_show_channels(struct ast_cli_args *a)
3992 {
3993  struct ao2_iterator it_cdrs;
3994  struct cdr_object *cdr;
3995  char start_time_buffer[64];
3996  char answer_time_buffer[64];
3997  char end_time_buffer[64];
3998 
3999 #define TITLE_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
4000 #define FORMAT_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
4001 
4002  ast_cli(a->fd, "\n");
4003  ast_cli(a->fd, "Channels with Call Detail Record (CDR) Information\n");
4004  ast_cli(a->fd, "--------------------------------------------------\n");
4005  ast_cli(a->fd, TITLE_STRING, "Channel", "Dst. Channel", "LastApp", "Start", "Answer", "End", "Billsec", "Duration");
4006 
4007  it_cdrs = ao2_iterator_init(active_cdrs_master, 0);
4008  for (; (cdr = ao2_iterator_next(&it_cdrs)); ao2_cleanup(cdr)) {
4009  struct cdr_object *it_cdr;
4010  struct timeval start_time = { 0, };
4011  struct timeval answer_time = { 0, };
4012  struct timeval end_time = { 0, };
4013 
4014  SCOPED_AO2LOCK(lock, cdr);
4015 
4016  /* Calculate the start, end, answer, billsec, and duration over the
4017  * life of all of the CDR entries
4018  */
4019  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4020  if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
4021  continue;
4022  }
4023  if (ast_tvzero(start_time)) {
4024  start_time = it_cdr->start;
4025  }
4026  if (!ast_tvzero(it_cdr->answer) && ast_tvzero(answer_time)) {
4027  answer_time = it_cdr->answer;
4028  }
4029  }
4030 
4031  /* If there was no start time, then all CDRs were for a dialed channel; skip */
4032  if (ast_tvzero(start_time)) {
4033  continue;
4034  }
4035  it_cdr = cdr->last;
4036 
4037  end_time = ast_tvzero(it_cdr->end) ? ast_tvnow() : it_cdr->end;
4038  cdr_get_tv(start_time, "%T", start_time_buffer, sizeof(start_time_buffer));
4039  cdr_get_tv(answer_time, "%T", answer_time_buffer, sizeof(answer_time_buffer));
4040  cdr_get_tv(end_time, "%T", end_time_buffer, sizeof(end_time_buffer));
4041  ast_cli(a->fd, FORMAT_STRING, it_cdr->party_a.snapshot->base->name,
4042  it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
4043  it_cdr->appl,
4044  start_time_buffer,
4045  answer_time_buffer,
4046  end_time_buffer,
4047  ast_tvzero(answer_time) ? 0 : (long)ast_tvdiff_ms(end_time, answer_time) / 1000,
4048  (long)ast_tvdiff_ms(end_time, start_time) / 1000);
4049  }
4050  ao2_iterator_destroy(&it_cdrs);
4051 #undef FORMAT_STRING
4052 #undef TITLE_STRING
4053 }
4054 
4055 static void cli_show_channel(struct ast_cli_args *a)
4056 {
4057  struct cdr_object *it_cdr;
4058  char clid[64];
4059  char start_time_buffer[64];
4060  char answer_time_buffer[64];
4061  char end_time_buffer[64];
4062  const char *channel_name = a->argv[3];
4063  struct cdr_object *cdr;
4064 
4065 #define TITLE_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
4066 #define FORMAT_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
4067 
4068  cdr = cdr_object_get_by_name(channel_name);
4069  if (!cdr) {
4070  ast_cli(a->fd, "Unknown channel: %s\n", channel_name);
4071  return;
4072  }
4073 
4074  ast_cli(a->fd, "\n");
4075  ast_cli(a->fd, "Call Detail Record (CDR) Information for %s\n", channel_name);
4076  ast_cli(a->fd, "--------------------------------------------------\n");
4077  ast_cli(a->fd, TITLE_STRING, "AccountCode", "CallerID", "Dst. Channel", "LastApp", "Data", "Start", "Answer", "End", "Billsec", "Duration");
4078 
4079  ao2_lock(cdr);
4080  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4081  struct timeval end;
4082 
4083  if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
4084  continue;
4085  }
4086  ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller->name, it_cdr->party_a.snapshot->caller->number, "");
4087  if (ast_tvzero(it_cdr->end)) {
4088  end = ast_tvnow();
4089  } else {
4090  end = it_cdr->end;
4091  }
4092  cdr_get_tv(it_cdr->start, "%T", start_time_buffer, sizeof(start_time_buffer));
4093  cdr_get_tv(it_cdr->answer, "%T", answer_time_buffer, sizeof(answer_time_buffer));
4094  cdr_get_tv(end, "%T", end_time_buffer, sizeof(end_time_buffer));
4095  ast_cli(a->fd, FORMAT_STRING,
4096  it_cdr->party_a.snapshot->base->accountcode,
4097  clid,
4098  it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
4099  it_cdr->appl,
4100  it_cdr->data,
4101  start_time_buffer,
4102  answer_time_buffer,
4103  end_time_buffer,
4104  (long)ast_tvdiff_ms(end, it_cdr->answer) / 1000,
4105  (long)ast_tvdiff_ms(end, it_cdr->start) / 1000);
4106  }
4107  ao2_unlock(cdr);
4108 
4109  ao2_cleanup(cdr);
4110 
4111 #undef FORMAT_STRING
4112 #undef TITLE_STRING
4113 }
4114 
4115 static char *handle_cli_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4116 {
4117  switch (cmd) {
4118  case CLI_INIT:
4119  e->command = "cdr show active";
4120  e->usage =
4121  "Usage: cdr show active [channel]\n"
4122  " Displays a summary of all Call Detail Records when [channel]\n"
4123  " is omitted; displays all of the Call Detail Records\n"
4124  " currently in flight for a given [channel] when [channel] is\n"
4125  " specified.\n\n"
4126  " Note that this will not display Call Detail Records that\n"
4127  " have already been dispatched to a backend storage, nor for\n"
4128  " channels that are no longer active.\n";
4129  return NULL;
4130  case CLI_GENERATE:
4131  return cli_complete_show(a);
4132  }
4133 
4134  if (a->argc > 4) {
4135  return CLI_SHOWUSAGE;
4136  } else if (a->argc < 4) {
4137  cli_show_channels(a);
4138  } else {
4139  cli_show_channel(a);
4140  }
4141 
4142  return CLI_SUCCESS;
4143 }
4144 
4145 static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4146 {
4147  struct cdr_beitem *beitem = NULL;
4148  struct module_config *mod_cfg;
4149  int cnt = 0;
4150  long nextbatchtime = 0;
4151 
4152  switch (cmd) {
4153  case CLI_INIT:
4154  e->command = "cdr show status";
4155  e->usage =
4156  "Usage: cdr show status\n"
4157  " Displays the Call Detail Record engine system status.\n";
4158  return NULL;
4159  case CLI_GENERATE:
4160  return NULL;
4161  }
4162 
4163  if (a->argc > 3) {
4164  return CLI_SHOWUSAGE;
4165  }
4166 
4167  mod_cfg = ao2_global_obj_ref(module_configs);
4168  if (!mod_cfg) {
4169  return CLI_FAILURE;
4170  }
4171 
4172  ast_cli(a->fd, "\n");
4173  ast_cli(a->fd, "Call Detail Record (CDR) settings\n");
4174  ast_cli(a->fd, "----------------------------------\n");
4175  ast_cli(a->fd, " Logging: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED) ? "Enabled" : "Disabled");
4176  ast_cli(a->fd, " Mode: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE) ? "Batch" : "Simple");
4177  if (ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4178  ast_cli(a->fd, " Log unanswered calls: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) ? "Yes" : "No");
4179  ast_cli(a->fd, " Log congestion: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION) ? "Yes" : "No");
4180  if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4181  ast_cli(a->fd, "* Batch Mode Settings\n");
4182  ast_cli(a->fd, " -------------------\n");
4183  if (batch)
4184  cnt = batch->size;
4185  if (cdr_sched > -1)
4186  nextbatchtime = ast_sched_when(sched, cdr_sched);
4187  ast_cli(a->fd, " Safe shutdown: %s\n", ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SAFE_SHUTDOWN) ? "Enabled" : "Disabled");
4188  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");
4189  ast_cli(a->fd, " Current batch size: %d record%s\n", cnt, ESS(cnt));
4190  ast_cli(a->fd, " Maximum batch size: %u record%s\n", mod_cfg->general->batch_settings.size, ESS(mod_cfg->general->batch_settings.size));
4191  ast_cli(a->fd, " Maximum batch time: %u second%s\n", mod_cfg->general->batch_settings.time, ESS(mod_cfg->general->batch_settings.time));
4192  ast_cli(a->fd, " Next batch processing time: %ld second%s\n\n", nextbatchtime, ESS(nextbatchtime));
4193  }
4194  ast_cli(a->fd, "* Registered Backends\n");
4195  ast_cli(a->fd, " -------------------\n");
4197  if (AST_RWLIST_EMPTY(&be_list)) {
4198  ast_cli(a->fd, " (none)\n");
4199  } else {
4200  AST_RWLIST_TRAVERSE(&be_list, beitem, list) {
4201  ast_cli(a->fd, " %s%s\n", beitem->name, beitem->suspended ? " (suspended) " : "");
4202  }
4203  }
4205  ast_cli(a->fd, "\n");
4206  }
4207 
4208  ao2_cleanup(mod_cfg);
4209  return CLI_SUCCESS;
4210 }
4211 
4212 static char *handle_cli_submit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4213 {
4214  struct module_config *mod_cfg;
4215 
4216  switch (cmd) {
4217  case CLI_INIT:
4218  e->command = "cdr submit";
4219  e->usage =
4220  "Usage: cdr submit\n"
4221  "Posts all pending batched CDR data to the configured CDR\n"
4222  "backend engine modules.\n";
4223  return NULL;
4224  case CLI_GENERATE:
4225  return NULL;
4226  }
4227  if (a->argc > 2) {
4228  return CLI_SHOWUSAGE;
4229  }
4230 
4231  mod_cfg = ao2_global_obj_ref(module_configs);
4232  if (!mod_cfg) {
4233  return CLI_FAILURE;
4234  }
4235 
4236  if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4237  ast_cli(a->fd, "Cannot submit CDR batch: CDR engine disabled.\n");
4238  } else if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4239  ast_cli(a->fd, "Cannot submit CDR batch: batch mode not enabled.\n");
4240  } else {
4241  start_batch_mode();
4242  ast_cli(a->fd, "Submitted CDRs to backend engines for processing. This may take a while.\n");
4243  }
4244  ao2_cleanup(mod_cfg);
4245 
4246  return CLI_SUCCESS;
4247 }
4248 
4249 static struct ast_cli_entry cli_commands[] = {
4250  AST_CLI_DEFINE(handle_cli_submit, "Posts all pending batched CDR data"),
4251  AST_CLI_DEFINE(handle_cli_status, "Display the CDR status"),
4252  AST_CLI_DEFINE(handle_cli_show, "Display active CDRs for channels"),
4253  AST_CLI_DEFINE(handle_cli_debug, "Enable debugging in the CDR engine"),
4254 };
4255 
4256 /*!
4257  * \brief This dispatches *all* \ref cdr_objects. It should only be used during
4258  * shutdown, so that we get billing records for everything that we can.
4259  */
4260 static int cdr_object_dispatch_all_cb(void *obj, void *arg, int flags)
4261 {
4262  struct cdr_object *cdr = obj;
4263  struct cdr_object *it_cdr;
4264 
4265  ao2_lock(cdr);
4266  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4267  cdr_object_transition_state(it_cdr, &finalized_state_fn_table);
4268  }
4269  cdr_object_dispatch(cdr);
4270  ao2_unlock(cdr);
4271 
4272  cdr_all_unlink(cdr);
4273 
4274  return CMP_MATCH;
4275 }
4276 
4277 static void finalize_batch_mode(void)
4278 {
4279  if (cdr_thread == AST_PTHREADT_NULL) {
4280  return;
4281  }
4282  /* wake up the thread so it will exit */
4283  pthread_cancel(cdr_thread);
4284  pthread_kill(cdr_thread, SIGURG);
4285  pthread_join(cdr_thread, NULL);
4289 }
4290 
4292 {
4293  if (!stasis_router) {
4294  return NULL;
4295  }
4296 
4297  ao2_bump(stasis_router);
4298  return stasis_router;
4299 }
4300 
4301 /*!
4302  * \brief Destroy the active Stasis subscriptions
4303  */
4304 static void destroy_subscriptions(void)
4305 {
4306  channel_subscription = stasis_forward_cancel(channel_subscription);
4307  bridge_subscription = stasis_forward_cancel(bridge_subscription);
4308  parking_subscription = stasis_forward_cancel(parking_subscription);
4309 }
4310 
4311 /*!
4312  * \brief Create the Stasis subcriptions for CDRs
4313  */
4314 static int create_subscriptions(void)
4315 {
4316  if (!cdr_topic) {
4317  return -1;
4318  }
4319 
4320  if (channel_subscription || bridge_subscription || parking_subscription) {
4321  return 0;
4322  }
4323 
4324  channel_subscription = stasis_forward_all(ast_channel_topic_all(), cdr_topic);
4325  if (!channel_subscription) {
4326  return -1;
4327  }
4328  bridge_subscription = stasis_forward_all(ast_bridge_topic_all(), cdr_topic);
4329  if (!bridge_subscription) {
4330  return -1;
4331  }
4332  parking_subscription = stasis_forward_all(ast_parking_topic(), cdr_topic);
4333  if (!parking_subscription) {
4334  return -1;
4335  }
4336 
4337  return 0;
4338 }
4339 
4340 static int process_config(int reload)
4341 {
4342  if (!reload) {
4343  if (aco_info_init(&cfg_info)) {
4344  return 1;
4345  }
4346 
4347  aco_option_register(&cfg_info, "enable", ACO_EXACT, general_options, DEFAULT_ENABLED, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_ENABLED);
4348  aco_option_register(&cfg_info, "debug", ACO_EXACT, general_options, 0, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_DEBUG);
4349  aco_option_register(&cfg_info, "unanswered", ACO_EXACT, general_options, DEFAULT_UNANSWERED, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_UNANSWERED);
4350  aco_option_register(&cfg_info, "congestion", ACO_EXACT, general_options, 0, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_CONGESTION);
4351  aco_option_register(&cfg_info, "batch", ACO_EXACT, general_options, DEFAULT_BATCHMODE, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_BATCHMODE);
4352  aco_option_register(&cfg_info, "endbeforehexten", ACO_EXACT, general_options, DEFAULT_END_BEFORE_H_EXTEN, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_END_BEFORE_H_EXTEN);
4353  aco_option_register(&cfg_info, "initiatedseconds", ACO_EXACT, general_options, DEFAULT_INITIATED_SECONDS, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_INITIATED_SECONDS);
4354  aco_option_register(&cfg_info, "scheduleronly", ACO_EXACT, general_options, DEFAULT_BATCH_SCHEDULER_ONLY, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, batch_settings.settings), BATCH_MODE_SCHEDULER_ONLY);
4355  aco_option_register(&cfg_info, "safeshutdown", ACO_EXACT, general_options, DEFAULT_BATCH_SAFE_SHUTDOWN, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, batch_settings.settings), BATCH_MODE_SAFE_SHUTDOWN);
4356  aco_option_register(&cfg_info, "size", ACO_EXACT, general_options, DEFAULT_BATCH_SIZE, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_cdr_config, batch_settings.size), 0, MAX_BATCH_SIZE);
4357  aco_option_register(&cfg_info, "time", ACO_EXACT, general_options, DEFAULT_BATCH_TIME, OPT_UINT_T, PARSE_IN_RANGE, FLDSET(struct ast_cdr_config, batch_settings.time), 1, MAX_BATCH_TIME);
4358  }
4359 
4360  if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) {
4361  struct module_config *mod_cfg;
4362 
4363  if (reload) {
4364  return 1;
4365  }
4366 
4367  /* If we couldn't process the configuration and this wasn't a reload,
4368  * create a default config
4369  */
4370  mod_cfg = module_config_alloc();
4371  if (!mod_cfg
4372  || aco_set_defaults(&general_option, "general", mod_cfg->general)) {
4373  ao2_cleanup(mod_cfg);
4374  return 1;
4375  }
4376  ast_log(LOG_NOTICE, "Failed to process CDR configuration; using defaults\n");
4377  ao2_global_obj_replace_unref(module_configs, mod_cfg);
4378  cdr_set_debug_mode(mod_cfg);
4379  ao2_cleanup(mod_cfg);
4380  }
4381 
4382  return 0;
4383 }
4384 
4385 static void cdr_engine_shutdown(void)
4386 {
4388  stasis_router = NULL;
4389 
4390  ao2_cleanup(cdr_topic);
4391  cdr_topic = NULL;
4392 
4393  STASIS_MESSAGE_TYPE_CLEANUP(cdr_sync_message_type);
4394 
4395  ao2_callback(active_cdrs_master, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
4398  ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
4400  sched = NULL;
4401  ast_free(batch);
4402  batch = NULL;
4403 
4404  aco_info_destroy(&cfg_info);
4405  ao2_global_obj_release(module_configs);
4406 
4407  ao2_container_unregister("cdrs_master");
4408  ao2_cleanup(active_cdrs_master);
4409  active_cdrs_master = NULL;
4410 
4411  ao2_container_unregister("cdrs_all");
4412  ao2_cleanup(active_cdrs_all);
4413  active_cdrs_all = NULL;
4414 }
4415 
4417 {
4418  /* Only create the thread level portions once */
4419  if (cdr_thread == AST_PTHREADT_NULL) {
4422  ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
4423  return;
4424  }
4425  }
4426 
4427  /* Start the batching process */
4428  start_batch_mode();
4429 
4430  ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %u or time %u seconds.\n",
4431  config->batch_settings.size, config->batch_settings.time);
4432 }
4433 
4434 /*!
4435  * \internal
4436  * \brief Print master CDR container object.
4437  * \since 12.0.0
4438  *
4439  * \param v_obj A pointer to the object we want printed.
4440  * \param where User data needed by prnt to determine where to put output.
4441  * \param prnt Print output callback function to use.
4442  *
4443  * \return Nothing
4444  */
4445 static void cdr_master_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
4446 {
4447  struct cdr_object *cdr = v_obj;
4448  struct cdr_object *it_cdr;
4449 
4450  if (!cdr) {
4451  return;
4452  }
4453  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4454  prnt(where, "Party A: %s; Party B: %s; Bridge %s\n",
4455  it_cdr->party_a.snapshot->base->name,
4456  it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<unknown>",
4457  it_cdr->bridge);
4458  }
4459 }
4460 
4461 /*!
4462  * \internal
4463  * \brief Print all CDR container object.
4464  * \since 13.19.0
4465  *
4466  * \param v_obj A pointer to the object we want printed.
4467  * \param where User data needed by prnt to determine where to put output.
4468  * \param prnt Print output callback function to use.
4469  *
4470  * \return Nothing
4471  */
4472 static void cdr_all_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
4473 {
4474  struct cdr_object *cdr = v_obj;
4475 
4476  if (!cdr) {
4477  return;
4478  }
4479  prnt(where, "Party A: %s; Party B: %s; Bridge %s",
4480  cdr->party_a.snapshot->base->name,
4481  cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<unknown>",
4482  cdr->bridge);
4483 }
4484 
4485 /*!
4486  * \brief Checks if CDRs are enabled and enables/disables the necessary options
4487  */
4489 {
4490  struct module_config *mod_cfg;
4491 
4492  mod_cfg = ao2_global_obj_ref(module_configs);
4493  if (mod_cfg
4494  && ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4495  if (create_subscriptions()) {
4497  ast_log(AST_LOG_ERROR, "Failed to create Stasis subscriptions\n");
4498  ao2_cleanup(mod_cfg);
4499  return -1;
4500  }
4501  if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4502  cdr_enable_batch_mode(mod_cfg->general);
4503  } else {
4504  ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
4505  }
4506  } else {
4508  ast_log(LOG_NOTICE, "CDR logging disabled.\n");
4509  }
4510  ao2_cleanup(mod_cfg);
4511 
4512  return mod_cfg ? 0 : -1;
4513 }
4514 
4515 static int unload_module(void)
4516 {
4518 
4519  return 0;
4520 }
4521 
4522 static int load_module(void)
4523 {
4524  if (process_config(0)) {
4525  return AST_MODULE_LOAD_FAILURE;
4526  }
4527 
4528  cdr_topic = stasis_topic_create("cdr:aggregator");
4529  if (!cdr_topic) {
4530  return AST_MODULE_LOAD_FAILURE;
4531  }
4532 
4533  stasis_router = stasis_message_router_create(cdr_topic);
4534  if (!stasis_router) {
4535  return AST_MODULE_LOAD_FAILURE;
4536  }
4539 
4540  if (STASIS_MESSAGE_TYPE_INIT(cdr_sync_message_type)) {
4541  return AST_MODULE_LOAD_FAILURE;
4542  }
4543 
4549  stasis_message_router_add(stasis_router, cdr_sync_message_type(), handle_cdr_sync_message, NULL);
4550 
4551  active_cdrs_master = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
4553  if (!active_cdrs_master) {
4554  return AST_MODULE_LOAD_FAILURE;
4555  }
4556  ao2_container_register("cdrs_master", active_cdrs_master, cdr_master_print_fn);
4557 
4560  if (!active_cdrs_all) {
4561  return AST_MODULE_LOAD_FAILURE;
4562  }
4563  ao2_container_register("cdrs_all", active_cdrs_all, cdr_all_print_fn);
4564 
4565  sched = ast_sched_context_create();
4566  if (!sched) {
4567  ast_log(LOG_ERROR, "Unable to create schedule context.\n");
4568  return AST_MODULE_LOAD_FAILURE;
4569  }
4570 
4571  ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
4573 
4575 }
4576 
4578 {
4579  RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
4580 
4581  /* Since this is called explicitly during process shutdown, we might not have ever
4582  * been initialized. If so, the config object will be NULL.
4583  */
4584  if (!mod_cfg) {
4585  return;
4586  }
4587 
4588  if (cdr_sync_message_type()) {
4589  void *payload;
4590  struct stasis_message *message;
4591 
4592  if (!stasis_router) {
4593  return;
4594  }
4595 
4596  /* Make sure we have the needed items */
4597  payload = ao2_alloc(sizeof(*payload), NULL);
4598  if (!payload) {
4599  return;
4600  }
4601 
4602  ast_debug(1, "CDR Engine termination request received; waiting on messages...\n");
4603 
4604  message = stasis_message_create(cdr_sync_message_type(), payload);
4605  if (message) {
4606  stasis_message_router_publish_sync(stasis_router, message);
4607  }
4608  ao2_cleanup(message);
4609  ao2_cleanup(payload);
4610  }
4611 
4612  if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4613  cdr_submit_batch(ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SAFE_SHUTDOWN));
4614  }
4615 }
4616 
4617 static int reload_module(void)
4618 {
4619  struct module_config *old_mod_cfg;
4620  struct module_config *mod_cfg;
4621 
4622  old_mod_cfg = ao2_global_obj_ref(module_configs);
4623 
4624  if (!old_mod_cfg || process_config(1)) {
4625  ao2_cleanup(old_mod_cfg);
4626  return -1;
4627  }
4628 
4629  mod_cfg = ao2_global_obj_ref(module_configs);
4630  if (!mod_cfg
4631  || !ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)
4632  || !ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4633  /* If batch mode used to be enabled, finalize the batch */
4634  if (ast_test_flag(&old_mod_cfg->general->settings, CDR_BATCHMODE)) {
4636  }
4637  }
4638  ao2_cleanup(mod_cfg);
4639 
4640  ao2_cleanup(old_mod_cfg);
4641  return cdr_toggle_runtime_options();
4642 }
4643 
4645  .support_level = AST_MODULE_SUPPORT_CORE,
4646  .load = load_module,
4647  .unload = unload_module,
4648  .reload = reload_module,
4649  .load_pri = AST_MODPRI_CORE,
4650  .requires = "extconfig",
4651 );
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
#define MAX_BATCH_SIZE
Definition: cdr.c:197
static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:1540
static enum process_bridge_enter_results dialed_pending_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1976
static struct stasis_message_router * stasis_router
Message router for stasis messages regarding channel state.
Definition: cdr.c:371
const ast_string_field data
static int cdr_object_get_by_name_cb(void *obj, void *arg, int flags)
Definition: cdr.c:3142
static long cdr_object_get_billsec(struct cdr_object *cdr)
Compute the billsec for a cdr_object.
Definition: cdr.c:1235
struct ao2_container * channels
Definition: bridge.h:339
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:308
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
struct ast_bridge_snapshot * bridge
Definition: cdr.c:2355
static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, void *data, int flags)
Callback used to update the userfield on Party B on all CDRs.
Definition: cdr.c:3455
struct ast_channel_snapshot_base * base
Asterisk locking-related definitions:
static void * module_config_alloc(void)
Create a new module config object.
Definition: cdr.c:300
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct cdr_batch_item * tail
Definition: cdr.c:345
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
struct varshead variables
Definition: cdr.c:708
int ast_cdr_reset(const char *channel_name, int keep_variables)
Reset the detail record.
Definition: cdr.c:3598
static int cdr_master_cmp_fn(void *obj, void *arg, int flags)
Definition: cdr.c:854
static void reset_batch(void)
Definition: cdr.c:3730
static void * do_batch_backend_process(void *data)
Definition: cdr.c:3749
static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:2015
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
struct ast_cdr_config * ast_cdr_get_config(void)
Obtain the current CDR configuration.
Definition: cdr.c:2826
struct stasis_message_type * ast_channel_entered_bridge_type(void)
Message type for channel enter bridge blob messages.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
Definition: ast_expr2.c:325
struct ast_channel_snapshot * channel
char * config
Definition: conf2ael.c:66
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:288
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
int(*const process_parked_channel)(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
Process an update informing us that the channel got itself parked.
Definition: cdr.c:546
Call Parking API.
static void cdr_all_unlink(struct cdr_object *cdr)
Definition: cdr.c:972
#define cdr_set_debug_mode(mod_cfg)
Definition: cdr.c:203
const ast_string_field name
static void * do_cdr(void *data)
Definition: cdr.c:3903
static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
Process a single bridge_candidate.
Definition: cdr.c:2503
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ast_flags settings
Definition: cdr.h:265
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
Format a variable on a cdr_object.
Definition: cdr.c:3226
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition: codec_g726.c:367
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
char desc[80]
Definition: cdr.c:323
static const char * ignore_categories[]
Definition: cdr.c:239
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static void handle_bridge_leave_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for when a channel leaves a bridge.
Definition: cdr.c:2404
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127
int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
Set a property on a CDR for a channel.
Definition: cdr.c:3548
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
struct stasis_message_type * ast_channel_left_bridge_type(void)
Message type for channel leave bridge blob messages.
long int billsec
Definition: cdr.h:302
#define ast_set_flag(p, flag)
Definition: utils.h:70
static void handle_parking_bridge_enter_message(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel, const struct timeval *event_time)
Handle entering into a parking bridge.
Definition: cdr.c:2586
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
static void post_cdr(struct ast_cdr *cdr)
Definition: cdr.c:3508
#define LOG_WARNING
Definition: logger.h:274
struct ast_cdr * next
Definition: cdr.h:325
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:63
static void cdr_object_dtor(void *obj)
cdr_object Destructor
Definition: cdr.c:999
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
Definition: cdr.c:1653
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:3422
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:322
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
static int cdr_master_hash_fn(const void *obj, const int flags)
Definition: cdr.c:830
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:284
#define FORMAT_STRING
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:2943
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
unsigned int flags
Definition: utils.h:200
static void destroy_subscriptions(void)
Destroy the active Stasis subscriptions.
Definition: cdr.c:4304
void stasis_message_router_unsubscribe_and_join(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic, blocking until the final message has been processed...
void stasis_message_router_publish_sync(struct stasis_message_router *router, struct stasis_message *message)
Publish a message to a message router&#39;s subscription synchronously.
#define AST_LOG_WARNING
Definition: logger.h:279
struct cdr_object * next
Definition: cdr.c:735
#define DEFAULT_BATCH_SIZE
Definition: cdr.c:196
#define var
Definition: ast_expr2f.c:614
struct cdr_object_snapshot party_b
Definition: cdr.c:714
Structure representing a snapshot of channel state.
static char * handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cdr.c:4145
int(*const process_party_a)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party A update for the cdr_object.
Definition: cdr.c:437
static void module_config_post_apply(void)
Definition: cdr.c:276
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
#define DEFAULT_BATCH_TIME
Definition: cdr.c:198
A wrapper object around a snapshot. Fields that are mutable by the CDR engine are replicated here...
Definition: cdr.c:704
static ast_mutex_t cdr_sched_lock
Definition: cdr.c:354
static void cdr_engine_shutdown(void)
Definition: cdr.c:4385
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
Definition: cli.h:152
static const char desc[]
Definition: cdr_mysql.c:73
#define ao2_t_replace(dst, src, tag)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:503
static int cdr_debug_enabled
Definition: cdr.c:208
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Adds a scheduled event with rescheduling support.
Definition: sched.c:524
static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
Definition: cdr.c:1617
static struct stasis_topic * cdr_topic
The parent topic for all topics we want to aggregate for CDRs.
Definition: cdr.c:383
static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
Definition: cdr.c:1848
int sequence
Definition: cdr.h:320
const ast_string_field accountcode
const ast_string_field exten
Definition: cdr.c:734
static struct cdr_object * cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
cdr_object constructor
Definition: cdr.c:1039
#define AST_NUM_CHANNEL_BUCKETS
Definition: channel.h:156
char * be
Definition: eagi_proxy.c:73
int(* ast_cdrbe)(struct ast_cdr *cdr)
CDR backend callback.
Definition: cdr.h:458
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
Definition: channel.c:4418
struct timeval answer
Definition: cdr.c:719
const ast_string_field uniqueid
static void set_variable(struct varshead *headp, const char *name, const char *value)
Definition: cdr.c:1262
static void handle_bridge_enter_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: cdr.c:2708
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
static void handle_dial_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for Stasis-Core dial messages.
Definition: cdr.c:2105
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
static int submit_scheduled_batch(const void *data)
Definition: cdr.c:3804
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:337
unsigned int sequence
Definition: cdr.c:722
static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2002
static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
Set the disposition on a cdr_object based on a hangupcause code.
Definition: cdr.c:1402
static void cdr_submit_batch(int shutdown)
Definition: cdr.c:3766
#define ast_assert(a)
Definition: utils.h:695
#define DEFAULT_ENABLED
Definition: cdr.c:189
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ao2_unlock(a)
Definition: astobj2.h:730
Definition: muted.c:95
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
A parked call message payload.
Definition: parking.h:59
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2064
static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1601
struct timeval start
Definition: cdr.c:718
unsigned int flags
Definition: cdr.c:707
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:746
#define NULL
Definition: resample.c:96
static int cdr_object_select_all_by_name_cb(void *obj, void *arg, int flags)
Definition: cdr.c:3126
char * end
Definition: eagi_proxy.c:73
static long cdr_object_get_duration(struct cdr_object *cdr)
Definition: cdr.c:1227
The representation of a single configuration file to be processed.
int value
Definition: syslog.c:37
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
ast_cdr_options
CDR manipulation options. Certain function calls will manipulate the state of a CDR object based on t...
Definition: cdr.h:239
Structure representing a change of snapshot of channel state.
static const char cdr_config[]
Definition: cdr_radius.c:86
struct ast_channel_snapshot * channel
Definition: cdr.c:2356
enum aco_type_t type
enum ast_parked_call_event_type event_type
Definition: parking.h:62
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
static int ast_cdr_generic_unregister(struct be_list *generic_list, const char *name)
Definition: cdr.c:2953
#define ast_cond_signal(cond)
Definition: lock.h:201
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
static void handle_channel_snapshot_update_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for channel snapshot update messages.
Definition: cdr.c:2278
struct ast_channel_snapshot_dialplan * dialplan
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:572
#define ast_verb(level,...)
Definition: logger.h:463
Registration object for CDR backends.
Definition: cdr.c:321
struct cdr_object_snapshot party_a
Definition: cdr.c:713
void(*const init_function)(struct cdr_object *cdr)
An initialization function. This will be called automatically when a cdr_object is switched to this t...
Definition: cdr.c:427
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
void ast_cdr_engine_term(void)
Definition: cdr.c:4577
struct ast_json * ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
Retrieve the JSON blob from a ast_multi_channel_blob. Returned ast_json is still owned by obj...
enum process_bridge_enter_results(*const process_bridge_enter)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process the entering of a bridge by this CDR. The purpose of this callback is to have the CDR prepare...
Definition: cdr.c:503
Utility functions.
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
Definition: astobj2.h:1442
pthread_cond_t ast_cond_t
Definition: lock.h:176
A virtual table used for cdr_object.
Definition: cdr.c:416
static struct stasis_forward * bridge_subscription
Our subscription for bridges.
Definition: cdr.c:374
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define DEFAULT_BATCH_SAFE_SHUTDOWN
Definition: cdr.c:201
const ast_string_field appl
Definition: cdr.c:734
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
struct varshead varshead
Definition: cdr.h:323
#define ao2_bump(obj)
Definition: astobj2.h:491
const ast_string_field context
Definition: cdr.c:734
static int cdr_object_dispatch_all_cb(void *obj, void *arg, int flags)
This dispatches all cdr_objects. It should only be used during shutdown, so that we get billing recor...
Definition: cdr.c:4260
Call Detail Record API.
const ast_string_field dialed_subaddr
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:292
const ast_string_field context
Configuration File Parser.
long int amaflags
Definition: cdr.h:306
int is_root
Definition: cdr.c:737
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
const char * userfield
Definition: cdr.c:3451
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:717
struct ast_bridge_snapshot * bridge
static int global_cdr_sequence
The global sequence counter used for CDRs.
Definition: cdr.c:349
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:706
#define AST_LOG_ERROR
Definition: logger.h:290
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
const ast_string_field technology
Definition: bridge.h:336
struct ast_flags flags
Definition: cdr.c:723
struct ast_cdr * cdr
Definition: cdr.c:337
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
void ast_cdr_free(struct ast_cdr *cdr)
Free a CDR record.
Definition: cdr.c:3411
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1073
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
static char * handle_cli_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cdr.c:4115
static int cdr_all_hash_fn(const void *obj, const int flags)
Definition: cdr.c:888
struct ast_channel_snapshot * parkee
Definition: parking.h:60
General Asterisk PBX channel definitions.
Asterisk JSON abstraction layer.
static void bridge_candidate_add_to_cdr(struct cdr_object *cdr, struct cdr_object_snapshot *party_b)
Definition: cdr.c:2472
static int create_subscriptions(void)
Create the Stasis subcriptions for CDRs.
Definition: cdr.c:4314
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
int(*const process_dial_begin)(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
Process the beginning of a dial. A dial message implies one of two things: The cdr_object&#39;s Party A h...
Definition: cdr.c:462
#define DEFAULT_UNANSWERED
Definition: cdr.c:191
static int load_module(void)
Definition: cdr.c:4522
const ast_string_field appl
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
Type for default option handler for unsigned integers.
static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
Format one of the standard properties on a cdr_object.
Definition: cdr.c:3243
static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1982
static void single_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:1645
const int fd
Definition: cli.h:159
static int process_config(int reload)
Definition: cdr.c:4340
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
static void single_state_init_function(struct cdr_object *cdr)
Definition: cdr.c:1639
#define AST_PTHREADT_NULL
Definition: lock.h:66
struct cdr_batch_item * next
Definition: cdr.c:338
struct ast_cdr_config::batch_settings batch_settings
static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:2032
ast_mutex_t lock
Definition: app_meetme.c:1091
static void cdr_object_dispatch(struct cdr_object *cdr)
Dispatch a CDR.
Definition: cdr.c:1386
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
#define DEFAULT_END_BEFORE_H_EXTEN
Definition: cdr.c:193
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
process_bridge_enter_results
Return types for process_bridge_enter functions.
Definition: cdr.c:391
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
Scheduler Routines (derived from cheops)
char linkedid[AST_MAX_UNIQUEID]
Definition: cdr.h:316
static struct ast_cli_entry cli_commands[]
Definition: cdr.c:4249
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:299
const ast_string_field linkedid
Definition: cdr.c:734
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:2988
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
static ast_mutex_t cdr_pending_lock
These are used to wake up the CDR thread when there&#39;s work to do.
Definition: cdr.c:361
static void module_config_destructor(void *obj)
Dispose of a module config object.
Definition: cdr.c:289
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct aco_file module_file_conf
The file definition.
Definition: cdr.c:264
const ast_string_field subaddr
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13
#define ao2_lock(a)
Definition: astobj2.h:718
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
Definition: cdr.c:1606
struct cdr_object_fn_table parked_state_fn_table
The virtual table for the Parked state.
Definition: cdr.c:678
const ast_string_field exten
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int filter_bridge_messages(struct ast_bridge_snapshot *bridge)
Filter bridge messages based on bridge technology.
Definition: cdr.c:2386
static const char *const cdr_readonly_vars[]
Definition: cdr.c:3154
static void handle_bridge_pairings(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge)
Handle creating bridge pairings for the cdr_object that just entered a bridge.
Definition: cdr.c:2561
static enum process_bridge_enter_results dial_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1880
char uniqueid[AST_MAX_UNIQUEID]
Definition: cdr.h:314
struct ast_channel_snapshot_hangup * hangup
static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
Definition: cdr.c:3035
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:282
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
static int init_batch(void)
Definition: cdr.c:3738
struct cdr_object_fn_table dialed_pending_state_fn_table
The virtual table for the Dialed Pending state.
Definition: cdr.c:637
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
The configuration settings for this module.
Definition: cdr.c:222
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3312
static void cdr_detach(struct ast_cdr *cdr)
Definition: cdr.c:3841
void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:3477
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:286
static int cdr_generic_register(struct be_list *generic_list, const char *name, const char *desc, ast_cdrbe be)
Definition: cdr.c:2902
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition: stasis.c:618
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:108
static char * handle_cli_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cdr.c:3929
Blob of data associated with a bridge.
static int answer(void *data)
Definition: chan_pjsip.c:682
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:972
enum aco_category_op category_match
static AO2_GLOBAL_OBJ_STATIC(module_configs)
The container for the module configuration.
static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:1802
static const char * cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
Definition: cdr.c:3018
#define stasis_message_router_create(topic)
static struct cdr_batch * batch
static void free_variables(struct varshead *headp)
Delete all variables from a variable list.
Definition: cdr.c:777
static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Return whether or not a channel has changed its state in the dialplan, subject to endbeforehexten log...
Definition: cdr.c:1148
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
Their was an error and no changes were applied.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236
enum ast_cdr_disposition disposition
Definition: cdr.c:717
const char * channel_name
Definition: cdr.c:3450
int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
Retrieve a CDR variable from a channel&#39;s current CDR.
Definition: cdr.c:3324
struct ast_channel_snapshot_caller * caller
const char *const * argv
Definition: cli.h:161
List of registered modifiers.
Definition: cdr.c:333
static struct cdr_object_snapshot * cdr_object_pick_party_a(struct cdr_object_snapshot *left, struct cdr_object_snapshot *right)
Given two CDR snapshots, figure out who should be Party A for the resulting CDR.
Definition: cdr.c:1192
An in-memory representation of an active CDR.
Definition: cdr.c:712
The actual batch queue.
Definition: cdr.c:342
struct cdr_object * last
Definition: cdr.c:736
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static void cdr_object_transition_state_init(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table, int do_init)
Transition a cdr_object to a new state with initiation flag.
Definition: cdr.c:804
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
struct timeval answer
Definition: cdr.h:296
Queued CDR waiting to be batched.
Definition: cdr.c:336
struct ast_flags softhangup_flags
Responsible for call detail data.
Definition: cdr.h:276
Configuration option-handling.
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:290
const ast_string_field data
Definition: cdr.c:734
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
int ast_cdr_backend_unsuspend(const char *name)
Unsuspend a CDR backend.
Definition: cdr.c:2884
struct cdr_object_fn_table single_state_fn_table
The virtual table for the Single state.
Definition: cdr.c:573
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
const ast_string_field dnid
static enum process_bridge_enter_results single_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1736
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
static struct ast_cdr * cdr_object_create_public_records(struct cdr_object *cdr)
Create a chain of ast_cdr objects from a chain of cdr_object suitable for consumption by the register...
Definition: cdr.c:1287
#define CLI_SHOWUSAGE
Definition: cli.h:45
static ast_cond_t cdr_pending_cond
Definition: cdr.c:362
static ast_mutex_t cdr_batch_lock
Lock protecting modifications to the batch queue.
Definition: cdr.c:358
char name[20]
Definition: cdr.c:322
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
Fork a CDR.
Definition: cdr.c:3637
int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
Serializes all the data and variables for a current CDR record.
Definition: cdr.c:3353
unsigned int parkingspace
Definition: parking.h:65
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865
static void cdr_object_check_party_a_hangup(struct cdr_object *cdr)
Check to see if a CDR needs to move to the finalized state because its Party A hungup.
Definition: cdr.c:1477
int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
Clear a property on a CDR for a channel.
Definition: cdr.c:3575
CONFIG_INFO_CORE("cdr", cfg_info, module_configs, module_config_alloc,.files=ACO_FILES(&module_file_conf),.post_apply_config=module_config_post_apply,)
static int cdr_sched
Definition: cdr.c:353
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
def info(msg)
const char * name
Name of the subclass.
Definition: cdr.c:418
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
void(*const process_party_b)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party B update for the cdr_object.
Definition: cdr.c:446
static int single_state_bridge_enter_comparison(struct cdr_object *cdr, struct cdr_object *cand_cdr)
Handle a comparison between our cdr_object and a cdr_object already in the bridge while in the Single...
Definition: cdr.c:1692
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct stasis_message_router * ast_cdr_message_router(void)
Return the message router for the CDR engine.
Definition: cdr.c:4291
static struct aco_type * general_options[]
Definition: cdr.c:274
#define LOG_NOTICE
Definition: logger.h:263
const ast_string_field party_b_name
Definition: cdr.c:734
long ast_sched_when(struct ast_sched_context *con, int id)
Returns the number of seconds before an event takes place.
Definition: sched.c:814
struct timeval lastevent
Definition: cdr.c:721
static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
Return whether or not a ast_channel_snapshot is for a channel that was created as the result of a dia...
Definition: cdr.c:1179
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
struct timeval end
Definition: cdr.c:720
struct timeval start
Definition: cdr.h:294
#define CLI_FAILURE
Definition: cli.h:46
#define ESS(x)
Definition: cli.h:59
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define AST_CAUSE_UNREGISTERED
Definition: causes.h:153
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2049
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static int cdr_object_update_party_b(void *obj, void *arg, void *data, int flags)
Definition: cdr.c:2220
struct ast_var_t::@249 entries
static int reload(void)
Definition: cdr_mysql.c:741
static void start_batch_mode(void)
Definition: cdr.c:3825
#define AST_FLAGS_ALL
Definition: utils.h:196
#define ast_var_assign(name, value)
Definition: chanvars.h:40
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
Module could not be loaded properly.
Definition: module.h:102
static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
Definition: cdr.c:1992
static int unload_module(void)
Definition: cdr.c:4515
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition: stasis.c:1548
const char * word
Definition: cli.h:163
struct ast_channel_snapshot * new_snapshot
long int duration
Definition: cdr.h:300
static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
Copy a snapshot and its details.
Definition: cdr.c:791
enum ast_channel_state state
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
static int cdr_all_cmp_fn(void *obj, void *arg, int flags)
Definition: cdr.c:912
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const ast_string_field uniqueid
Definition: bridge.h:336
An API for managing task processing threads that can be shared across modules.
const ast_string_field parkinglot
Definition: parking.h:69
static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
Definition: cdr.c:1828
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
int(*const process_parking_bridge_enter)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process entering into a parking bridge.
Definition: cdr.c:519
int ast_cdr_modifier_unregister(const char *name)
Unregister a CDR modifier.
Definition: cdr.c:2993
struct ast_channel_snapshot * old_snapshot
Structure used to handle boolean flags.
Definition: utils.h:199
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:414
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
const char * usage
Definition: cli.h:177
char src[AST_MAX_EXTENSION]
Definition: cdr.h:280
char peeraccount[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:310
void ast_cdr_set_config(struct ast_cdr_config *config)
Set the current CDR configuration.
Definition: cdr.c:2840
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
#define CLI_SUCCESS
Definition: cli.h:44
static int dial_status_end(const char *dialstatus)
Definition: cdr.c:2089
#define ao2_global_obj_replace_unref(holder, obj)
Definition: astobj2.h:908
#define ACO_FILES(...)
STASIS_MESSAGE_TYPE_DEFN_LOCAL(cdr_sync_message_type)
A message type used to synchronize with the CDR topic.
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
struct stasis_topic * ast_parking_topic(void)
accessor for the parking stasis topic
Definition: parking.c:67
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
struct timeval end
Definition: cdr.h:298
static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, void *data, int flags)
Callback used to notify CDRs of a Party B leaving the bridge.
Definition: cdr.c:2361
const struct timeval * lastevent
Definition: cdr.c:2357
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition: causes.h:99
struct ast_flags settings
Definition: cdr.h:269
#define ao2_replace(dst, src)
Definition: astobj2.h:517
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_cdr_is_enabled(void)
Return TRUE if CDR subsystem is enabled.
Definition: cdr.c:2861
Standard Command Line Interface.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
ast_cdr_disposition
CDR Flags - Disposition.
Definition: cdr.h:253
Type information about a category-level configurable object.
const ast_string_field number
int ast_cdr_modifier_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR modifier.
Definition: cdr.c:2948
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
int ast_cdr_backend_suspend(const char *name)
Suspend a CDR backend temporarily.
Definition: cdr.c:2866
static void cdr_enable_batch_mode(struct ast_cdr_config *config)
Definition: cdr.c:4416
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static void handle_parked_call_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for when a channel is parked.
Definition: cdr.c:2751
struct ast_flags flags
static void cli_show_channel(struct ast_cli_args *a)
Definition: cdr.c:4055
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
const char * filename
static struct aco_type general_option
The type definition for general options.
Definition: cdr.c:230
A multi channel blob data structure for multi_channel_blob stasis messages.
int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
Set a variable on a CDR.
Definition: cdr.c:3178
#define DEFAULT_BATCHMODE
Definition: cdr.c:190
static int single_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1793
static void handle_standard_bridge_enter_message(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel, const struct timeval *event_time)
Handle a bridge enter message for a &#39;normal&#39; bridge.
Definition: cdr.c:2627
static PGresult * result
Definition: cel_pgsql.c:88
#define AST_CAUSE_BUSY
Definition: causes.h:148
static char * cli_complete_show(struct ast_cli_args *a)
Complete user input for &#39;cdr show&#39;.
Definition: cdr.c:3970
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:431
static void cdr_all_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: cdr.c:4472
static struct ao2_container * active_cdrs_all
A container of all active CDRs with a Party B indexed by Party B channel name.
Definition: cdr.c:368
struct stasis_forward * sub
Definition: res_corosync.c:240
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622
static void cdr_object_check_party_a_answer(struct cdr_object *cdr)
Check to see if a CDR needs to be answered based on its Party A. Note that this is safe to call as mu...
Definition: cdr.c:1494
Internal Asterisk hangup causes.
static int total
Definition: res_adsi.c:968
Abstract JSON element (object, array, string, int, ...).
ast_cdrbe be
Definition: cdr.c:324
struct cdr_batch_item * head
Definition: cdr.c:344
int(*const process_bridge_leave)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process the leaving of a bridge by this CDR.
Definition: cdr.c:533
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:884
static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Swap an old cdr_object_snapshot&#39;s ast_channel_snapshot for a new ast_channel_snapshot.
Definition: cdr.c:1531
Forwarding information.
Definition: stasis.c:1531
The global options available for CDRs.
Definition: cdr.h:264
struct stasis_message_type * ast_channel_dial_type(void)
Message type for when a channel dials another channel.
static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Definition: cdr.c:1506
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static struct stasis_forward * channel_subscription
Our subscription for channels.
Definition: cdr.c:377
struct cdr_object_fn_table bridge_state_fn_table
The virtual table for the Bridged state.
Definition: cdr.c:659
static void finalized_state_init_function(struct cdr_object *cdr)
Definition: cdr.c:2044
Generic container type.
long int disposition
Definition: cdr.h:304
static struct test_options options
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:278
Search option field mask.
Definition: astobj2.h:1076
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
Definition: stasis.c:1578
const ast_string_field uniqueid
Definition: cdr.c:734
struct cdr_object_fn_table dial_state_fn_table
The virtual table for the Dial state.
Definition: cdr.c:604
static struct aco_type ignore_option
Definition: cdr.c:252
int stasis_message_router_set_congestion_limits(struct stasis_message_router *router, long low_water, long high_water)
Set the high and low alert water marks of the stasis message router.
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2726
struct ast_channel_snapshot_peer * peer
static struct cdr_object * cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
Create a new cdr_object and append it to an existing chain.
Definition: cdr.c:1075
static int dialed_pending_state_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:1951
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
struct ast_cdr_config * general
Definition: cdr.c:223
int(*const process_dial_end)(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
Process the end of a dial. At the end of a dial, a CDR can be transitioned into one of two states - D...
Definition: cdr.c:480
static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Determine if we need to add a new CDR based on snapshots.
Definition: cdr.c:2249
Asterisk module definitions.
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
static void cdr_master_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: cdr.c:4445
const ast_string_field subclass
Definition: bridge.h:336
int size
Definition: cdr.c:343
static int cdr_object_finalize_party_b(void *obj, void *arg, void *data, int flags)
Definition: cdr.c:2196
static struct stasis_forward * parking_subscription
Our subscription for parking.
Definition: cdr.c:380
static void handle_cdr_sync_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for a synchronization message.
Definition: cdr.c:2820
#define TITLE_STRING
static struct cdr_tds_config * settings
Definition: cdr_tds.c:98
static char * handle_cli_submit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cdr.c:4212
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
#define DEFAULT_BATCH_SCHEDULER_ONLY
Definition: cdr.c:200
static enum process_bridge_enter_results base_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Definition: cdr.c:1611
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
static int cdr_toggle_runtime_options(void)
Checks if CDRs are enabled and enables/disables the necessary options.
Definition: cdr.c:4488
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
#define AST_CAUSE_CONGESTION
Definition: causes.h:152
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
static pthread_t cdr_thread
Definition: cdr.c:355
List of registered backends.
Definition: cdr.c:330
#define DEFAULT_INITIATED_SECONDS
Definition: cdr.c:194
static void finalize_batch_mode(void)
Definition: cdr.c:4277
static int dial_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
Definition: cdr.c:1816
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1250
const ast_string_field bridge
Definition: cdr.c:734
static int reload_module(void)
Definition: cdr.c:4617
const ast_string_field name
void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
Format a CDR variable from an already posted CDR.
Definition: cdr.c:3050
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:318
#define ast_mutex_unlock(a)
Definition: lock.h:188
static void cdr_all_relink(struct cdr_object *cdr)
Definition: cdr.c:949
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3430
static int filter_channel_snapshot_message(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Definition: cdr.c:2073
static struct ast_sched_context * sched
Scheduler items.
Definition: cdr.c:352
struct ast_cdr * ast_cdr_dup(struct ast_cdr *cdr)
Duplicate a public CDR.
Definition: cdr.c:2998
#define MAX_BATCH_TIME
Definition: cdr.c:199
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
static struct test_val a
#define AST_MAX_USER_FIELD
Definition: channel.h:175
#define ao2_link(container, obj)
Definition: astobj2.h:1549
static void cli_show_channels(struct ast_cli_args *a)
Definition: cdr.c:3991