Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Enumerations | Functions | Variables
cdr.c File Reference

Call Detail Record API. More...

#include "asterisk.h"
#include <signal.h>
#include <inttypes.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/callerid.h"
#include "asterisk/manager.h"
#include "asterisk/module.h"
#include "asterisk/causes.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/stringfields.h"
#include "asterisk/config_options.h"
#include "asterisk/json.h"
#include "asterisk/parking.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/astobj2.h"
#include "asterisk/taskprocessor.h"

Go to the source code of this file.

Data Structures

struct  be_list
 List of registered backends. More...
 
struct  bridge_leave_data
 
struct  cdr_batch
 The actual batch queue. More...
 
struct  cdr_batch_item
 Queued CDR waiting to be batched. More...
 
struct  cdr_beitem
 Registration object for CDR backends. More...
 
struct  cdr_object
 An in-memory representation of an active CDR. More...
 
struct  cdr_object_fn_table
 A virtual table used for cdr_object. More...
 
struct  cdr_object_snapshot
 A wrapper object around a snapshot. Fields that are mutable by the CDR engine are replicated here. More...
 
struct  mo_list
 List of registered modifiers. More...
 
struct  module_config
 The configuration settings for this module. More...
 
struct  party_b_userfield_update
 

Macros

#define CDR_DEBUG(fmt, ...)
 
#define cdr_set_debug_mode(mod_cfg)
 
#define DEFAULT_BATCH_SAFE_SHUTDOWN   "1"
 
#define DEFAULT_BATCH_SCHEDULER_ONLY   "0"
 
#define DEFAULT_BATCH_SIZE   "100"
 
#define DEFAULT_BATCH_TIME   "300"
 
#define DEFAULT_BATCHMODE   "0"
 
#define DEFAULT_CHANNEL_ENABLED   "1"
 
#define DEFAULT_CONGESTION   "0"
 
#define DEFAULT_ENABLED   "1"
 
#define DEFAULT_END_BEFORE_H_EXTEN   "1"
 
#define DEFAULT_IGNORE_DIAL_CHANGES   "0"
 
#define DEFAULT_IGNORE_STATE_CHANGES   "0"
 
#define DEFAULT_INITIATED_SECONDS   "0"
 
#define DEFAULT_UNANSWERED   "0"
 
#define FORMAT_STRING   "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
 
#define FORMAT_STRING   "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
 
#define MAX_BATCH_SIZE   1000
 
#define MAX_BATCH_TIME   86400
 
#define TITLE_STRING   "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
 
#define TITLE_STRING   "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
 

Enumerations

enum  process_bridge_enter_results { BRIDGE_ENTER_ONLY_PARTY, BRIDGE_ENTER_OBTAINED_PARTY_B, BRIDGE_ENTER_NO_PARTY_B, BRIDGE_ENTER_NEED_CDR }
 Return types for process_bridge_enter functions. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static AO2_GLOBAL_OBJ_STATIC (module_configs)
 The container for the module configuration.
 
struct ast_cdrast_cdr_alloc (void)
 Allocate a CDR record. More...
 
int ast_cdr_backend_suspend (const char *name)
 Suspend a CDR backend temporarily. More...
 
int ast_cdr_backend_unsuspend (const char *name)
 Unsuspend a CDR backend. More...
 
int ast_cdr_clear_property (const char *channel_name, enum ast_cdr_options option)
 Clear a property on a CDR for a channel. More...
 
const char * ast_cdr_disp2str (int disposition)
 Disposition to a string. More...
 
struct ast_cdrast_cdr_dup (struct ast_cdr *cdr)
 Duplicate a public CDR. More...
 
void ast_cdr_engine_term (void)
 
int ast_cdr_fork (const char *channel_name, struct ast_flags *options)
 Fork a CDR. More...
 
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. More...
 
void ast_cdr_free (struct ast_cdr *cdr)
 Free a CDR record. More...
 
static int ast_cdr_generic_unregister (struct be_list *generic_list, const char *name)
 
struct ast_cdr_configast_cdr_get_config (void)
 Obtain the current CDR configuration. More...
 
int ast_cdr_getvar (const char *channel_name, const char *name, char *value, size_t length)
 Retrieve a CDR variable from a channel's current CDR. More...
 
int ast_cdr_is_enabled (void)
 Return TRUE if CDR subsystem is enabled.
 
struct stasis_message_routerast_cdr_message_router (void)
 Return the message router for the CDR engine. More...
 
int ast_cdr_modifier_register (const char *name, const char *desc, ast_cdrbe be)
 Register a CDR modifier. More...
 
int ast_cdr_modifier_unregister (const char *name)
 Unregister a CDR modifier. More...
 
int ast_cdr_register (const char *name, const char *desc, ast_cdrbe be)
 Register a CDR handling engine. More...
 
int ast_cdr_reset (const char *channel_name, int keep_variables)
 Reset the detail record. More...
 
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. More...
 
void ast_cdr_set_config (struct ast_cdr_config *config)
 Set the current CDR configuration. More...
 
int ast_cdr_set_property (const char *channel_name, enum ast_cdr_options option)
 Set a property on a CDR for a channel. More...
 
void ast_cdr_setuserfield (const char *channel_name, const char *userfield)
 Set CDR user field for channel (stored in CDR) More...
 
int ast_cdr_setvar (const char *channel_name, const char *name, const char *value)
 Set a variable on a CDR. More...
 
int ast_cdr_unregister (const char *name)
 Unregister a CDR handling engine. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static enum process_bridge_enter_results base_process_bridge_enter (struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
 
static int base_process_bridge_leave (struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
 
static int base_process_dial_end (struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
 
static int base_process_parked_channel (struct cdr_object *cdr, struct ast_parked_call_payload *parking_info)
 
static int base_process_party_a (struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
 
static void bridge_candidate_add_to_cdr (struct cdr_object *cdr, struct cdr_object_snapshot *party_b)
 
static void bridge_candidate_process (struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
 Process a single bridge_candidate. More...
 
static int bridge_state_process_bridge_leave (struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
 
static void bridge_state_process_party_b (struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
 
static int cdr_all_cmp_fn (void *obj, void *arg, int flags)
 
static int cdr_all_hash_fn (const void *obj, const int flags)
 
static void cdr_all_print_fn (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static void cdr_all_relink (struct cdr_object *cdr)
 
static void cdr_all_unlink (struct cdr_object *cdr)
 
static void cdr_detach (struct ast_cdr *cdr)
 
static void cdr_enable_batch_mode (struct ast_cdr_config *config)
 
static void cdr_engine_shutdown (void)
 
static const char * cdr_format_var_internal (struct ast_cdr *cdr, const char *name)
 
static int cdr_generic_register (struct be_list *generic_list, const char *name, const char *desc, ast_cdrbe be)
 
static void cdr_get_tv (struct timeval when, const char *fmt, char *buf, int bufsize)
 
static int cdr_master_cmp_fn (void *obj, void *arg, int flags)
 
static int cdr_master_hash_fn (const void *obj, const int flags)
 
static void cdr_master_print_fn (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static struct cdr_objectcdr_object_alloc (struct ast_channel_snapshot *chan, const struct timeval *event_time)
 cdr_object constructor More...
 
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 much as you want - we won't answer twice.
 
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.
 
static struct cdr_objectcdr_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. More...
 
static struct ast_cdrcdr_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 registered CDR backends. More...
 
static void cdr_object_dispatch (struct cdr_object *cdr)
 Dispatch a CDR. More...
 
static int cdr_object_dispatch_all_cb (void *obj, void *arg, int flags)
 This dispatches all cdr_object. It should only be used during shutdown, so that we get billing records for everything that we can.
 
static void cdr_object_dtor (void *obj)
 cdr_object Destructor
 
static void cdr_object_finalize (struct cdr_object *cdr)
 Finalize a CDR. More...
 
static int cdr_object_finalize_party_b (void *obj, void *arg, void *data, int flags)
 
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.
 
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.
 
static long cdr_object_get_billsec (struct cdr_object *cdr)
 Compute the billsec for a cdr_object.
 
static struct cdr_objectcdr_object_get_by_name (const char *name)
 
static int cdr_object_get_by_name_cb (void *obj, void *arg, int flags)
 
static long cdr_object_get_duration (struct cdr_object *cdr)
 
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.
 
static struct cdr_object_snapshotcdr_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. More...
 
static int cdr_object_select_all_by_name_cb (void *obj, void *arg, int flags)
 
static void cdr_object_set_disposition (struct cdr_object *cdr, int hangupcause)
 Set the disposition on a cdr_object based on a hangupcause code. More...
 
static void cdr_object_snapshot_copy (struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
 Copy a snapshot and its details. More...
 
static void cdr_object_swap_snapshot (struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
 Swap an old cdr_object_snapshot's ast_channel_snapshot for a new ast_channel_snapshot. More...
 
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. More...
 
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. More...
 
static void cdr_object_update_cid (struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
 Set Caller ID information on a CDR.
 
static int cdr_object_update_party_b (void *obj, void *arg, void *data, int flags)
 
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.
 
static void cdr_submit_batch (int shutdown)
 
static int cdr_toggle_runtime_options (void)
 Checks if CDRs are enabled and enables/disables the necessary options.
 
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.
 
static char * cli_complete_show (struct ast_cli_args *a)
 Complete user input for 'cdr show'.
 
static void cli_show_channel (struct ast_cli_args *a)
 
static void cli_show_channels (struct ast_cli_args *a)
 
 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 copy_variables (struct varshead *to_list, struct varshead *from_list)
 Copy variables from one list to another. More...
 
static int create_subscriptions (void)
 Create the Stasis subcriptions for CDRs.
 
static void destroy_subscriptions (void)
 Destroy the active Stasis subscriptions.
 
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)
 
static int dial_state_process_dial_begin (struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
 
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)
 
static void dial_state_process_party_b (struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
 
static int dial_status_end (const char *dialstatus)
 
static enum ast_cdr_disposition dial_status_to_disposition (const char *dial_status)
 
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)
 
static int dialed_pending_state_process_dial_begin (struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
 
static int dialed_pending_state_process_parking_bridge_enter (struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
 
static int dialed_pending_state_process_party_a (struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
 
static void * do_batch_backend_process (void *data)
 
static void * do_cdr (void *data)
 
static int filter_bridge_messages (struct ast_bridge_snapshot *bridge)
 Filter bridge messages based on bridge technology.
 
static int filter_channel_snapshot (struct ast_channel_snapshot *snapshot)
 
static int filter_channel_snapshot_message (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
 
static void finalize_batch_mode (void)
 
static void finalized_state_init_function (struct cdr_object *cdr)
 
static int finalized_state_process_party_a (struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
 
static void free_variables (struct varshead *headp)
 Delete all variables from a variable list. More...
 
static void handle_bridge_enter_message (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void handle_bridge_leave_message (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 Handler for when a channel leaves a bridge. More...
 
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. More...
 
static void handle_cdr_sync_message (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 Handler for a synchronization message. More...
 
static void handle_channel_snapshot_update_message (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 Handler for channel snapshot update messages. More...
 
static char * handle_cli_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_submit (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void handle_dial_message (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 Handler for Stasis-Core dial messages. More...
 
static void handle_parked_call_message (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 Handler for when a channel is parked. More...
 
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. More...
 
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 'normal' bridge. More...
 
static int init_batch (void)
 
static int is_cdr_flag_set (unsigned int cdr_flag)
 
static int load_module (void)
 
static void * module_config_alloc (void)
 Create a new module config object.
 
static void module_config_destructor (void *obj)
 Dispose of a module config object.
 
static void module_config_post_apply (void)
 
static int parked_state_process_bridge_leave (struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
 
static void post_cdr (struct ast_cdr *cdr)
 
static int process_config (int reload)
 
static int reload_module (void)
 
static void reset_batch (void)
 
static void set_variable (struct varshead *headp, const char *name, const char *value)
 
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 state. The goal of this is to find a Party B for our CDR. More...
 
static void single_state_init_function (struct cdr_object *cdr)
 
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)
 
static int single_state_process_dial_begin (struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
 
static int single_state_process_parking_bridge_enter (struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
 
static void single_state_process_party_b (struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
 
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 logic. More...
 
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 dial operation. More...
 
static void start_batch_mode (void)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (cdr_sync_message_type)
 A message type used to synchronize with the CDR topic.
 
static int submit_scheduled_batch (const void *data)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "CDR Engine" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "da6642af068ee5e6490c5b1d2cc1d238" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
 
static struct ao2_containeractive_cdrs_all
 A container of all active CDRs with a Party B indexed by Party B channel name.
 
static struct ao2_containeractive_cdrs_master
 A container of the active master CDRs indexed by Party A channel uniqueid.
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct cdr_batchbatch = NULL
 
static struct be_list be_list = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
struct cdr_object_fn_table bridge_state_fn_table
 The virtual table for the Bridged state. More...
 
static struct stasis_forwardbridge_subscription
 Our subscription for bridges.
 
static ast_mutex_t cdr_batch_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Lock protecting modifications to the batch queue.
 
static int cdr_debug_enabled
 
static ast_cond_t cdr_pending_cond
 
static ast_mutex_t cdr_pending_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 These are used to wake up the CDR thread when there's work to do.
 
static const char *const cdr_readonly_vars []
 
static int cdr_sched = -1
 
static ast_mutex_t cdr_sched_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static pthread_t cdr_thread = AST_PTHREADT_NULL
 
static struct stasis_topiccdr_topic
 The parent topic for all topics we want to aggregate for CDRs.
 
static struct stasis_forwardchannel_subscription
 Our subscription for channels.
 
static struct ast_cli_entry cli_commands []
 
static int dial_changes_ignored
 
struct cdr_object_fn_table dial_state_fn_table
 The virtual table for the Dial state. More...
 
struct cdr_object_fn_table dialed_pending_state_fn_table
 The virtual table for the Dialed Pending state. More...
 
struct cdr_object_fn_table finalized_state_fn_table
 The virtual table for the finalized state. More...
 
static struct aco_type general_option
 The type definition for general options.
 
static struct aco_typegeneral_options [] = ACO_TYPES(&general_option)
 
static int global_cdr_sequence = 0
 The global sequence counter used for CDRs.
 
static const char * ignore_categories []
 
static struct aco_type ignore_option
 
static struct mo_list mo_list = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct aco_file module_file_conf
 The file definition. More...
 
struct cdr_object_fn_table parked_state_fn_table
 The virtual table for the Parked state. More...
 
static struct stasis_forwardparking_subscription
 Our subscription for parking.
 
static struct ast_sched_contextsched
 Scheduler items.
 
struct cdr_object_fn_table single_state_fn_table
 The virtual table for the Single state. More...
 
static struct stasis_message_routerstasis_router
 Message router for stasis messages regarding channel state.
 

Detailed Description

Call Detail Record API.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Note
Includes code and algorithms from the Zapata library.
We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip through our fingers somehow. If someone allocates a CDR, it must be completely handled normally or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR isn't properly generated and posted.

Definition in file cdr.c.

Macro Definition Documentation

#define CDR_DEBUG (   fmt,
  ... 
)
Value:
do { \
if (cdr_debug_enabled) { \
ast_verbose((fmt), ##__VA_ARGS__); \
} \
} while (0)

Definition at line 252 of file cdr.c.

#define cdr_set_debug_mode (   mod_cfg)
Value:
do { \
cdr_debug_enabled = ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG); \
} while (0)
Definition: cdr.h:226

Definition at line 244 of file cdr.c.

Enumeration Type Documentation

Return types for process_bridge_enter functions.

Enumerator
BRIDGE_ENTER_ONLY_PARTY 

The CDR was the only party in the bridge.

BRIDGE_ENTER_OBTAINED_PARTY_B 

The CDR was able to obtain a Party B from some other party already in the bridge

BRIDGE_ENTER_NO_PARTY_B 

The CDR was not able to obtain a Party B

BRIDGE_ENTER_NEED_CDR 

This CDR can't handle a bridge enter message and a new CDR needs to be created

Definition at line 433 of file cdr.c.

433  {
434  /*!
435  * The CDR was the only party in the bridge.
436  */
438  /*!
439  * The CDR was able to obtain a Party B from some other party already in the bridge
440  */
442  /*!
443  * The CDR was not able to obtain a Party B
444  */
446  /*!
447  * This CDR can't handle a bridge enter message and a new CDR needs to be created
448  */
450 };

Function Documentation

struct ast_cdr* ast_cdr_alloc ( void  )

Allocate a CDR record.

Returns
a malloc'd ast_cdr structure
Return values
NULLon error (malloc failure)

Definition at line 3484 of file cdr.c.

References ast_calloc.

Referenced by ast_cdr_dup().

3485 {
3486  struct ast_cdr *x;
3487 
3488  x = ast_calloc(1, sizeof(*x));
3489  return x;
3490 }
Responsible for call detail data.
Definition: cdr.h:279
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int ast_cdr_backend_suspend ( const char *  name)

Suspend a CDR backend temporarily.

Return values
0The backend is suspended
-1The backend could not be suspended

Definition at line 2928 of file cdr.c.

References ast_debug, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

2929 {
2930  int success = -1;
2931  struct cdr_beitem *i = NULL;
2932 
2934  AST_RWLIST_TRAVERSE(&be_list, i, list) {
2935  if (!strcasecmp(name, i->name)) {
2936  ast_debug(3, "Suspending CDR backend %s\n", i->name);
2937  i->suspended = 1;
2938  success = 0;
2939  }
2940  }
2942 
2943  return success;
2944 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
Registration object for CDR backends.
Definition: cdr.c:363
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
List of registered backends.
Definition: cdr.c:372
int ast_cdr_backend_unsuspend ( const char *  name)

Unsuspend a CDR backend.

Return values
0The backend was unsuspended
-1The back could not be unsuspended

Definition at line 2946 of file cdr.c.

References ast_debug, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

2947 {
2948  int success = -1;
2949  struct cdr_beitem *i = NULL;
2950 
2952  AST_RWLIST_TRAVERSE(&be_list, i, list) {
2953  if (!strcasecmp(name, i->name)) {
2954  ast_debug(3, "Unsuspending CDR backend %s\n", i->name);
2955  i->suspended = 0;
2956  success = 0;
2957  }
2958  }
2960 
2961  return success;
2962 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
Registration object for CDR backends.
Definition: cdr.c:363
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
List of registered backends.
Definition: cdr.c:372
int ast_cdr_clear_property ( const char *  channel_name,
enum ast_cdr_options  option 
)

Clear a property on a CDR for a channel.

Since
12 Clears a flag previously set by ast_cdr_set_property
Parameters
channel_nameThe CDR's channel
optionOption to clear from the CDR
Return values
0on success
1on error

Definition at line 3637 of file cdr.c.

References cdr_object::flags, cdr_object::fn_table, and cdr_object::next.

3638 {
3639  struct cdr_object *cdr;
3640  struct cdr_object *it_cdr;
3641 
3642  cdr = cdr_object_get_by_name(channel_name);
3643  if (!cdr) {
3644  return -1;
3645  }
3646 
3647  ao2_lock(cdr);
3648  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3649  if (it_cdr->fn_table == &finalized_state_fn_table) {
3650  continue;
3651  }
3652  ast_clear_flag(&it_cdr->flags, option);
3653  }
3654  ao2_unlock(cdr);
3655 
3656  ao2_cleanup(cdr);
3657  return 0;
3658 }
struct cdr_object * next
Definition: cdr.c:777
struct ast_flags flags
Definition: cdr.c:765
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:736
const char* ast_cdr_disp2str ( int  disposition)

Disposition to a string.

Parameters
dispositioninput binary form Converts the binary form of a disposition to string form.
Returns
a pointer to the string form

Definition at line 3492 of file cdr.c.

Referenced by ast_cdr_format_var(), and cdr_object_finalize().

3493 {
3494  switch (disposition) {
3495  case AST_CDR_NULL:
3496  return "NO ANSWER"; /* by default, for backward compatibility */
3497  case AST_CDR_NOANSWER:
3498  return "NO ANSWER";
3499  case AST_CDR_FAILED:
3500  return "FAILED";
3501  case AST_CDR_BUSY:
3502  return "BUSY";
3503  case AST_CDR_ANSWERED:
3504  return "ANSWERED";
3505  case AST_CDR_CONGESTION:
3506  return "CONGESTION";
3507  }
3508  return "UNKNOWN";
3509 }
enum ast_cdr_disposition disposition
Definition: cdr.c:759
struct ast_cdr* ast_cdr_dup ( struct ast_cdr cdr)

Duplicate a public CDR.

Parameters
cdrthe record to duplicate
Returns
a malloc'd ast_cdr structure,
Return values
NULLon error (malloc failure)

Definition at line 3060 of file cdr.c.

References ast_cdr_alloc(), AST_LIST_HEAD_INIT_NOLOCK, copy_variables(), and ast_cdr::varshead.

3061 {
3062  struct ast_cdr *newcdr;
3063 
3064  if (!cdr) {
3065  return NULL;
3066  }
3067  newcdr = ast_cdr_alloc();
3068  if (!newcdr) {
3069  return NULL;
3070  }
3071 
3072  *newcdr = *cdr;
3074  copy_variables(&newcdr->varshead, &cdr->varshead);
3075  newcdr->next = NULL;
3076 
3077  return newcdr;
3078 }
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:3484
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:788
struct varshead varshead
Definition: cdr.h:326
Responsible for call detail data.
Definition: cdr.h:279
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
void ast_cdr_engine_term ( void  )

Submit any remaining CDRs and prepare for shutdown

Definition at line 4665 of file cdr.c.

References ao2_global_obj_ref, ast_debug, BATCH_MODE_SAFE_SHUTDOWN, CDR_BATCHMODE, module_config::general, RAII_VAR, ast_cdr_config::batch_settings::settings, ast_cdr_config::settings, stasis_message_create(), and stasis_message_router_publish_sync().

4666 {
4667  RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
4668 
4669  /* Since this is called explicitly during process shutdown, we might not have ever
4670  * been initialized. If so, the config object will be NULL.
4671  */
4672  if (!mod_cfg) {
4673  return;
4674  }
4675 
4676  if (cdr_sync_message_type()) {
4677  void *payload;
4678  struct stasis_message *message;
4679 
4680  if (!stasis_router) {
4681  return;
4682  }
4683 
4684  /* Make sure we have the needed items */
4685  payload = ao2_alloc(sizeof(*payload), NULL);
4686  if (!payload) {
4687  return;
4688  }
4689 
4690  ast_debug(1, "CDR Engine termination request received; waiting on messages...\n");
4691 
4692  message = stasis_message_create(cdr_sync_message_type(), payload);
4693  if (message) {
4695  }
4696  ao2_cleanup(message);
4697  ao2_cleanup(payload);
4698  }
4699 
4700  if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4701  cdr_submit_batch(ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SAFE_SHUTDOWN));
4702  }
4703 }
static struct stasis_message_router * stasis_router
Message router for stasis messages regarding channel state.
Definition: cdr.c:413
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
The configuration settings for this module.
Definition: cdr.c:264
#define ast_debug(level,...)
Log a DEBUG message.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_message_router_publish_sync(struct stasis_message_router *router, struct stasis_message *message)
Publish a message to a message router's subscription synchronously.
#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:941
int ast_cdr_fork ( const char *  channel_name,
struct ast_flags options 
)

Fork a CDR.

Since
12
Parameters
channel_nameThe name of the channel whose CDR should be forked
optionsOptions to control how the fork occurs.
Return values
0on success
-1on failure

Definition at line 3699 of file cdr.c.

References cdr_object::answer, ao2_ref, AST_CDR_FLAG_FINALIZE, AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_RESET, AST_CDR_FLAG_SET_ANSWER, AST_CDR_LOCK_APP, ast_debug, AST_STATE_UP, ast_string_field_set, ast_tvnow(), cdr_object_create_and_append(), cdr_object_finalize(), cdr_object_transition_state(), copy_variables(), ast_cdr::flags, cdr_object_snapshot::flags, cdr_object::flags, cdr_object::fn_table, free_variables(), cdr_object::lastevent, lock, cdr_object::next, cdr_object::party_a, cdr_object::party_b, RAII_VAR, SCOPED_AO2LOCK, cdr_object_snapshot::snapshot, cdr_object::start, ast_channel_snapshot::state, cdr_object_snapshot::userfield, and cdr_object_snapshot::variables.

3700 {
3701  RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3702  struct cdr_object *new_cdr;
3703  struct cdr_object *it_cdr;
3704  struct cdr_object *cdr_obj;
3705 
3706  if (!cdr) {
3707  return -1;
3708  }
3709 
3710  {
3711  SCOPED_AO2LOCK(lock, cdr);
3712  struct timeval now = ast_tvnow();
3713 
3714  cdr_obj = cdr->last;
3715  if (cdr_obj->fn_table == &finalized_state_fn_table) {
3716  /* If the last CDR in the chain is finalized, don't allow a fork -
3717  * things are already dying at this point
3718  */
3719  return -1;
3720  }
3721 
3722  /* Copy over the basic CDR information. The Party A information is
3723  * copied over automatically as part of the append
3724  */
3725  ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->base->name);
3726  new_cdr = cdr_object_create_and_append(cdr, &now);
3727  if (!new_cdr) {
3728  return -1;
3729  }
3730  new_cdr->fn_table = cdr_obj->fn_table;
3731  ast_string_field_set(new_cdr, bridge, cdr->bridge);
3732  ast_string_field_set(new_cdr, appl, cdr->appl);
3733  ast_string_field_set(new_cdr, data, cdr->data);
3734  ast_string_field_set(new_cdr, context, cdr->context);
3735  ast_string_field_set(new_cdr, exten, cdr->exten);
3736  new_cdr->flags = cdr->flags;
3737  /* Explicitly clear the AST_CDR_LOCK_APP flag - we want
3738  * the application to be changed on the new CDR if the
3739  * dialplan demands it
3740  */
3741  ast_clear_flag(&new_cdr->flags, AST_CDR_LOCK_APP);
3742 
3743  /* If there's a Party B, copy it over as well */
3744  if (cdr_obj->party_b.snapshot) {
3745  new_cdr->party_b.snapshot = cdr_obj->party_b.snapshot;
3746  ao2_ref(new_cdr->party_b.snapshot, +1);
3747  cdr_all_relink(new_cdr);
3748  strcpy(new_cdr->party_b.userfield, cdr_obj->party_b.userfield);
3749  new_cdr->party_b.flags = cdr_obj->party_b.flags;
3750  if (ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3751  copy_variables(&new_cdr->party_b.variables, &cdr_obj->party_b.variables);
3752  }
3753  }
3754  new_cdr->start = cdr_obj->start;
3755  new_cdr->answer = cdr_obj->answer;
3756  new_cdr->lastevent = ast_tvnow();
3757 
3758  /* Modify the times based on the flags passed in */
3759  if (ast_test_flag(options, AST_CDR_FLAG_SET_ANSWER)
3760  && new_cdr->party_a.snapshot->state == AST_STATE_UP) {
3761  new_cdr->answer = ast_tvnow();
3762  }
3763  if (ast_test_flag(options, AST_CDR_FLAG_RESET)) {
3764  new_cdr->answer = ast_tvnow();
3765  new_cdr->start = ast_tvnow();
3766  }
3767 
3768  /* Create and append, by default, copies over the variables */
3769  if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3770  free_variables(&new_cdr->party_a.variables);
3771  }
3772 
3773  /* Finalize any current CDRs */
3774  if (ast_test_flag(options, AST_CDR_FLAG_FINALIZE)) {
3775  for (it_cdr = cdr; it_cdr != new_cdr; it_cdr = it_cdr->next) {
3776  if (it_cdr->fn_table == &finalized_state_fn_table) {
3777  continue;
3778  }
3779  /* Force finalization on the CDR. This will bypass any checks for
3780  * end before 'h' extension.
3781  */
3782  cdr_object_finalize(it_cdr);
3784  }
3785  }
3786  }
3787 
3788  return 0;
3789 }
struct varshead variables
Definition: cdr.c:750
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
struct cdr_object * next
Definition: cdr.c:777
struct cdr_object_snapshot party_b
Definition: cdr.c:756
const ast_string_field exten
Definition: cdr.c:776
struct timeval answer
Definition: cdr.c:761
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval start
Definition: cdr.c:760
unsigned int flags
Definition: cdr.c:749
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:788
struct cdr_object_snapshot party_a
Definition: cdr.c:755
const ast_string_field appl
Definition: cdr.c:776
const ast_string_field context
Definition: cdr.c:776
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:748
struct ast_flags flags
Definition: cdr.c:765
ast_mutex_t lock
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ast_debug(level,...)
Log a DEBUG message.
static void free_variables(struct varshead *headp)
Delete all variables from a variable list.
Definition: cdr.c:819
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct cdr_object * last
Definition: cdr.c:778
const ast_string_field data
Definition: cdr.c:776
struct timeval lastevent
Definition: cdr.c:763
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
enum ast_channel_state state
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:736
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:1116
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1479
#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:941
const ast_string_field bridge
Definition: cdr.c:776
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:864
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
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.

Since
12
Parameters
cdrThe dispatched CDR to process
nameThe name of the variable
retPointer to the formatted buffer
workspaceA pointer to the buffer to use to format the variable
workspacelenThe size of workspace
rawIf non-zero and a date/time is extracted, provide epoch seconds. Otherwise format as a date/time stamp

Definition at line 3112 of file cdr.c.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr_disp2str(), ast_channel_amaflags2string(), ast_copy_string(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_cdr::billsec, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::linkedid, ast_cdr::peeraccount, ast_cdr::sequence, ast_cdr::src, ast_cdr::uniqueid, and ast_cdr::userfield.

3113 {
3114  const char *fmt = "%Y-%m-%d %T";
3115  const char *varbuf;
3116 
3117  if (!cdr) {
3118  return;
3119  }
3120 
3121  *ret = NULL;
3122 
3123  if (!strcasecmp(name, "clid")) {
3124  ast_copy_string(workspace, cdr->clid, workspacelen);
3125  } else if (!strcasecmp(name, "src")) {
3126  ast_copy_string(workspace, cdr->src, workspacelen);
3127  } else if (!strcasecmp(name, "dst")) {
3128  ast_copy_string(workspace, cdr->dst, workspacelen);
3129  } else if (!strcasecmp(name, "dcontext")) {
3130  ast_copy_string(workspace, cdr->dcontext, workspacelen);
3131  } else if (!strcasecmp(name, "channel")) {
3132  ast_copy_string(workspace, cdr->channel, workspacelen);
3133  } else if (!strcasecmp(name, "dstchannel")) {
3134  ast_copy_string(workspace, cdr->dstchannel, workspacelen);
3135  } else if (!strcasecmp(name, "lastapp")) {
3136  ast_copy_string(workspace, cdr->lastapp, workspacelen);
3137  } else if (!strcasecmp(name, "lastdata")) {
3138  ast_copy_string(workspace, cdr->lastdata, workspacelen);
3139  } else if (!strcasecmp(name, "start")) {
3140  cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
3141  } else if (!strcasecmp(name, "answer")) {
3142  cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
3143  } else if (!strcasecmp(name, "end")) {
3144  cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
3145  } else if (!strcasecmp(name, "duration")) {
3146  snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
3147  } else if (!strcasecmp(name, "billsec")) {
3148  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);
3149  } else if (!strcasecmp(name, "disposition")) {
3150  if (raw) {
3151  snprintf(workspace, workspacelen, "%ld", cdr->disposition);
3152  } else {
3153  ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
3154  }
3155  } else if (!strcasecmp(name, "amaflags")) {
3156  if (raw) {
3157  snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
3158  } else {
3159  ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
3160  }
3161  } else if (!strcasecmp(name, "accountcode")) {
3162  ast_copy_string(workspace, cdr->accountcode, workspacelen);
3163  } else if (!strcasecmp(name, "peeraccount")) {
3164  ast_copy_string(workspace, cdr->peeraccount, workspacelen);
3165  } else if (!strcasecmp(name, "uniqueid")) {
3166  ast_copy_string(workspace, cdr->uniqueid, workspacelen);
3167  } else if (!strcasecmp(name, "linkedid")) {
3168  ast_copy_string(workspace, cdr->linkedid, workspacelen);
3169  } else if (!strcasecmp(name, "userfield")) {
3170  ast_copy_string(workspace, cdr->userfield, workspacelen);
3171  } else if (!strcasecmp(name, "sequence")) {
3172  snprintf(workspace, workspacelen, "%d", cdr->sequence);
3173  } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
3174  ast_copy_string(workspace, varbuf, workspacelen);
3175  } else {
3176  workspace[0] = '\0';
3177  }
3178 
3179  if (!ast_strlen_zero(workspace)) {
3180  *ret = workspace;
3181  }
3182 }
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:311
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:291
long int billsec
Definition: cdr.h:305
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:287
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
int sequence
Definition: cdr.h:323
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
Definition: channel.c:4373
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:295
long int amaflags
Definition: cdr.h:309
char linkedid[AST_MAX_UNIQUEID]
Definition: cdr.h:319
char uniqueid[AST_MAX_UNIQUEID]
Definition: cdr.h:317
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:285
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:293
long int duration
Definition: cdr.h:303
char src[AST_MAX_EXTENSION]
Definition: cdr.h:283
char peeraccount[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:313
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
long int disposition
Definition: cdr.h:307
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:281
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:321
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3492
void ast_cdr_free ( struct ast_cdr cdr)

Free a CDR record.

Parameters
cdrast_cdr structure to free

Definition at line 3473 of file cdr.c.

References free_variables(), and ast_cdr::varshead.

Referenced by ast_channel_destructor(), and ast_dummy_channel_destructor().

3474 {
3475  while (cdr) {
3476  struct ast_cdr *next = cdr->next;
3477 
3478  free_variables(&cdr->varshead);
3479  ast_free(cdr);
3480  cdr = next;
3481  }
3482 }
struct varshead varshead
Definition: cdr.h:326
static void free_variables(struct varshead *headp)
Delete all variables from a variable list.
Definition: cdr.c:819
Responsible for call detail data.
Definition: cdr.h:279
struct ast_cdr_config* ast_cdr_get_config ( void  )

Obtain the current CDR configuration.

Since
12 The configuration is a ref counted object. The caller of this function must decrement the ref count when finished with the configuration.
Return values
NULLon error
Returns
The current CDR configuration

Definition at line 2888 of file cdr.c.

References ao2_bump, ao2_global_obj_ref, and module_config::general.

2889 {
2890  struct ast_cdr_config *general;
2891  struct module_config *mod_cfg;
2892 
2893  mod_cfg = ao2_global_obj_ref(module_configs);
2894  if (!mod_cfg) {
2895  return NULL;
2896  }
2897  general = ao2_bump(mod_cfg->general);
2898  ao2_cleanup(mod_cfg);
2899  return general;
2900 }
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
The configuration settings for this module.
Definition: cdr.c:264
The global options available for CDRs.
Definition: cdr.h:267
struct ast_cdr_config * general
Definition: cdr.c:265
int ast_cdr_getvar ( const char *  channel_name,
const char *  name,
char *  value,
size_t  length 
)

Retrieve a CDR variable from a channel's current CDR.

Since
12
Parameters
channel_nameThe name of the party A channel that the CDR is associated with
nameThe name of the variable to retrieve
valueBuffer to hold the value
lengthThe size of the buffer
Return values
0on success
non-zeroon failure

Definition at line 3386 of file cdr.c.

References cdr_object_format_property(), cdr_object_format_var_internal(), and cdr_object::last.

3387 {
3388  struct cdr_object *cdr;
3389  struct cdr_object *cdr_obj;
3390 
3391  if (ast_strlen_zero(name)) {
3392  return 1;
3393  }
3394 
3395  cdr = cdr_object_get_by_name(channel_name);
3396  if (!cdr) {
3397  ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3398  return 1;
3399  }
3400 
3401  ao2_lock(cdr);
3402 
3403  cdr_obj = cdr->last;
3404  if (cdr_object_format_property(cdr_obj, name, value, length)) {
3405  /* Property failed; attempt variable */
3406  cdr_object_format_var_internal(cdr_obj, name, value, length);
3407  }
3408 
3409  ao2_unlock(cdr);
3410 
3411  ao2_cleanup(cdr);
3412  return 0;
3413 }
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:3288
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:3305
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct cdr_object * last
Definition: cdr.c:778
const ast_string_field name
Definition: cdr.c:776
struct stasis_message_router* ast_cdr_message_router ( void  )

Return the message router for the CDR engine.

This returns the stasis_message_router that the CDR engine uses for dispatching Stasis Message Bus API messages. The reference on the message router is bumped and must be released by the caller of this function.

Return values
NULLif the CDR engine is disabled or unavailable
Returns
the stasis_message_router otherwise

Definition at line 4356 of file cdr.c.

References ao2_bump, and stasis_router.

4357 {
4358  if (!stasis_router) {
4359  return NULL;
4360  }
4361 
4363  return stasis_router;
4364 }
static struct stasis_message_router * stasis_router
Message router for stasis messages regarding channel state.
Definition: cdr.c:413
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
int ast_cdr_modifier_register ( const char *  name,
const char *  desc,
ast_cdrbe  be 
)

Register a CDR modifier.

Parameters
namename associated with the particular CDR modifier
descdescription of the CDR modifier
befunction pointer to a CDR modifier

Used to register a Call Detail Record modifier.

This gives modules a chance to modify CDR fields before they are dispatched to registered backends (odbc, syslog, etc).

Note
The modified CDR will be passed to all registered backends for logging. For instance, if cdr_manager changes the CDR data, cdr_adaptive_odbc will also get the modified CDR.
Return values
0on success.
-1on error

Definition at line 3010 of file cdr.c.

3011 {
3012  return cdr_generic_register((struct be_list *)&mo_list, name, desc, be);
3013 }
List of registered modifiers.
Definition: cdr.c:375
const ast_string_field name
Definition: cdr.c:776
List of registered backends.
Definition: cdr.c:372
int ast_cdr_modifier_unregister ( const char *  name)

Unregister a CDR modifier.

Parameters
namename of CDR modifier to unregister Unregisters a CDR modifier by its name
Return values
0The modifier unregistered successfully
-1The modifier could not be unregistered at this time

Definition at line 3055 of file cdr.c.

3056 {
3057  return ast_cdr_generic_unregister((struct be_list *)&mo_list, name);
3058 }
List of registered modifiers.
Definition: cdr.c:375
const ast_string_field name
Definition: cdr.c:776
List of registered backends.
Definition: cdr.c:372
int ast_cdr_register ( const char *  name,
const char *  desc,
ast_cdrbe  be 
)

Register a CDR handling engine.

Parameters
namename associated with the particular CDR handler
descdescription of the CDR handler
befunction pointer to a CDR handler Used to register a Call Detail Record handler.
Return values
0on success.
-1on error

Definition at line 3005 of file cdr.c.

3006 {
3007  return cdr_generic_register(&be_list, name, desc, be);
3008 }
const ast_string_field name
Definition: cdr.c:776
List of registered backends.
Definition: cdr.c:372
int ast_cdr_reset ( const char *  channel_name,
int  keep_variables 
)

Reset the detail record.

Parameters
channel_nameThe channel that the CDR is associated with
keep_variablesKeep the variables during the reset. If zero, variables are discarded during the reset.
Return values
0on success
-1on failure

Definition at line 3660 of file cdr.c.

References cdr_object::answer, AST_LIST_REMOVE_HEAD, ast_tvnow(), cdr_object_check_party_a_answer(), cdr_object::end, cdr_object::lastevent, cdr_object::next, cdr_object::party_a, cdr_object::party_b, cdr_object_snapshot::snapshot, cdr_object::start, and cdr_object_snapshot::variables.

Referenced by dial_exec_full().

3661 {
3662  struct cdr_object *cdr;
3663  struct ast_var_t *vardata;
3664  struct cdr_object *it_cdr;
3665 
3666  cdr = cdr_object_get_by_name(channel_name);
3667  if (!cdr) {
3668  return -1;
3669  }
3670 
3671  ao2_lock(cdr);
3672  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3673  /* clear variables */
3674  if (!keep_variables) {
3675  while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
3676  ast_var_delete(vardata);
3677  }
3678  if (cdr->party_b.snapshot) {
3679  while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
3680  ast_var_delete(vardata);
3681  }
3682  }
3683  }
3684 
3685  /* Reset to initial state */
3686  memset(&it_cdr->start, 0, sizeof(it_cdr->start));
3687  memset(&it_cdr->end, 0, sizeof(it_cdr->end));
3688  memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
3689  it_cdr->start = ast_tvnow();
3690  it_cdr->lastevent = it_cdr->start;
3692  }
3693  ao2_unlock(cdr);
3694 
3695  ao2_cleanup(cdr);
3696  return 0;
3697 }
struct varshead variables
Definition: cdr.c:750
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
struct cdr_object * next
Definition: cdr.c:777
struct cdr_object_snapshot party_b
Definition: cdr.c:756
struct timeval answer
Definition: cdr.c:761
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval start
Definition: cdr.c:760
struct cdr_object_snapshot party_a
Definition: cdr.c:755
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct timeval lastevent
Definition: cdr.c:763
struct timeval end
Definition: cdr.c:762
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:1533
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.

Parameters
channel_nameThe channel to get the CDR for
bufA buffer to use for formatting the data
delimA delimeter to use to separate variable keys/values
sepA separator to use between nestings
Returns
the total number of serialized variables

Definition at line 3415 of file cdr.c.

References AST_LIST_TRAVERSE, ast_str_append(), ast_str_reset(), CDR_ENABLED, cdr_object_format_property(), cdr_object::next, cdr_object::party_a, S_OR, and cdr_object_snapshot::variables.

Referenced by handle_showchan().

3416 {
3417  struct cdr_object *cdr;
3418  struct cdr_object *it_cdr;
3419  struct ast_var_t *variable;
3420  const char *var;
3421  char workspace[256];
3422  int total = 0, x = 0, i;
3423 
3424  cdr = cdr_object_get_by_name(channel_name);
3425  if (!cdr) {
3426  if (is_cdr_flag_set(CDR_ENABLED)) {
3427  ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3428  }
3429  return 0;
3430  }
3431 
3432  ast_str_reset(*buf);
3433 
3434  ao2_lock(cdr);
3435  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3436  if (++x > 1) {
3437  ast_str_append(buf, 0, "\n");
3438  }
3439 
3440  AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
3441  if (!(var = ast_var_name(variable))) {
3442  continue;
3443  }
3444 
3445  if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
3446  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3447  break;
3448  }
3449 
3450  total++;
3451  }
3452 
3453  for (i = 0; cdr_readonly_vars[i]; i++) {
3454  if (cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace))) {
3455  /* Unhandled read-only CDR variable. */
3456  ast_assert(0);
3457  continue;
3458  }
3459 
3460  if (!ast_strlen_zero(workspace)
3461  && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
3462  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3463  break;
3464  }
3465  total++;
3466  }
3467  }
3468  ao2_unlock(cdr);
3469  ao2_cleanup(cdr);
3470  return total;
3471 }
struct varshead variables
Definition: cdr.c:750
struct cdr_object * next
Definition: cdr.c:777
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:1139
struct cdr_object_snapshot party_a
Definition: cdr.c:755
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:3305
An in-memory representation of an active CDR.
Definition: cdr.c:754
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
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:693
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
void ast_cdr_set_config ( struct ast_cdr_config config)

Set the current CDR configuration.

Since
12
Parameters
configThe new CDR configuration

Definition at line 2902 of file cdr.c.

References ao2_global_obj_ref, ao2_replace, cdr_toggle_runtime_options(), and module_config::general.

2903 {
2904  struct module_config *mod_cfg;
2905 
2906  if (!config) {
2907  return;
2908  }
2909 
2910  mod_cfg = ao2_global_obj_ref(module_configs);
2911  if (!mod_cfg) {
2912  return;
2913  }
2914 
2915  ao2_replace(mod_cfg->general, config);
2916 
2917  cdr_set_debug_mode(mod_cfg);
2919 
2920  ao2_cleanup(mod_cfg);
2921 }
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
The configuration settings for this module.
Definition: cdr.c:264
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
struct ast_cdr_config * general
Definition: cdr.c:265
static int cdr_toggle_runtime_options(void)
Checks if CDRs are enabled and enables/disables the necessary options.
Definition: cdr.c:4552
int ast_cdr_set_property ( const char *  channel_name,
enum ast_cdr_options  option 
)

Set a property on a CDR for a channel.

Since
12 This function sets specific administrative properties on a CDR for a channel. This includes properties like preventing a CDR from being dispatched, to setting the channel as the preferred Party A in future CDRs. See ast_cdr_options for more information.
Parameters
channel_nameThe CDR's channel
optionOption to apply to the CDR
Return values
0on success
1on error

Definition at line 3610 of file cdr.c.

References cdr_object::flags, cdr_object::fn_table, cdr_object::next, and cdr_object::party_a.

3611 {
3612  struct cdr_object *cdr;
3613  struct cdr_object *it_cdr;
3614 
3615  cdr = cdr_object_get_by_name(channel_name);
3616  if (!cdr) {
3617  return -1;
3618  }
3619 
3620  ao2_lock(cdr);
3621  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3622  if (it_cdr->fn_table == &finalized_state_fn_table) {
3623  continue;
3624  }
3625  /* Note: in general, set the flags on both the CDR record as well as the
3626  * Party A. Sometimes all we have is the Party A to look at.
3627  */
3628  ast_set_flag(&it_cdr->flags, option);
3629  ast_set_flag(&it_cdr->party_a, option);
3630  }
3631  ao2_unlock(cdr);
3632 
3633  ao2_cleanup(cdr);
3634  return 0;
3635 }
struct cdr_object * next
Definition: cdr.c:777
struct cdr_object_snapshot party_a
Definition: cdr.c:755
struct ast_flags flags
Definition: cdr.c:765
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:736
void ast_cdr_setuserfield ( const char *  channel_name,
const char *  userfield 
)

Set CDR user field for channel (stored in CDR)

Parameters
channel_nameThe name of the channel that owns the CDR
userfieldThe user field to set

Definition at line 3539 of file cdr.c.

References ast_copy_string(), cdr_object_update_party_b_userfield_cb(), cdr_object::fn_table, cdr_object::next, OBJ_MULTIPLE, OBJ_NODATA, OBJ_SEARCH_KEY, cdr_object::party_a, and cdr_object_snapshot::userfield.

3540 {
3541  struct cdr_object *cdr;
3542  struct party_b_userfield_update party_b_info = {
3543  .channel_name = channel_name,
3544  .userfield = userfield,
3545  };
3546  struct cdr_object *it_cdr;
3547 
3548  /* Handle Party A */
3549  cdr = cdr_object_get_by_name(channel_name);
3550  if (cdr) {
3551  ao2_lock(cdr);
3552  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3553  if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3554  continue;
3555  }
3556  ast_copy_string(it_cdr->party_a.userfield, userfield,
3557  sizeof(it_cdr->party_a.userfield));
3558  }
3559  ao2_unlock(cdr);
3560  }
3561 
3562  /* Handle Party B */
3563  ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,
3564  cdr_object_update_party_b_userfield_cb, (char *) party_b_info.channel_name,
3565  &party_b_info);
3566 
3567  ao2_cleanup(cdr);
3568 }
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:3517
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
struct cdr_object * next
Definition: cdr.c:777
struct cdr_object_snapshot party_a
Definition: cdr.c:755
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:748
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:736
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
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:410
int ast_cdr_setvar ( const char *  channel_name,
const char *  name,
const char *  value 
)

Set a variable on a CDR.

Since
12
Parameters
channel_nameThe channel to set the variable on
nameThe name of the variable to set
valueThe value of the variable to set
Return values
0on success
non-zeroon failure

Definition at line 3240 of file cdr.c.

References ao2_callback, ao2_iterator_destroy(), ast_strdupa, ast_channel_snapshot::base, cdr_object::fn_table, ast_channel_snapshot_base::name, cdr_object::next, OBJ_MULTIPLE, cdr_object::party_a, cdr_object::party_b, cdr_object_snapshot::snapshot, and cdr_object_snapshot::variables.

3241 {
3242  struct cdr_object *cdr;
3243  struct cdr_object *it_cdr;
3244  struct ao2_iterator *it_cdrs;
3245  char *arg = ast_strdupa(channel_name);
3246  int x;
3247 
3248  for (x = 0; cdr_readonly_vars[x]; x++) {
3249  if (!strcasecmp(name, cdr_readonly_vars[x])) {
3250  ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
3251  return -1;
3252  }
3253  }
3254 
3255  it_cdrs = ao2_callback(active_cdrs_master, OBJ_MULTIPLE, cdr_object_select_all_by_name_cb, arg);
3256  if (!it_cdrs) {
3257  ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3258  return -1;
3259  }
3260 
3261  for (; (cdr = ao2_iterator_next(it_cdrs)); ao2_unlock(cdr), ao2_cleanup(cdr)) {
3262  ao2_lock(cdr);
3263  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3264  struct varshead *headp = NULL;
3265 
3266  if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3267  continue;
3268  }
3269  if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->base->name)) {
3270  headp = &it_cdr->party_a.variables;
3271  } else if (it_cdr->party_b.snapshot
3272  && !strcasecmp(channel_name, it_cdr->party_b.snapshot->base->name)) {
3273  headp = &it_cdr->party_b.variables;
3274  }
3275  if (headp) {
3276  set_variable(headp, name, value);
3277  }
3278  }
3279  }
3280  ao2_iterator_destroy(it_cdrs);
3281 
3282  return 0;
3283 }
struct ast_channel_snapshot_base * base
struct varshead variables
Definition: cdr.c:750
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1693
struct cdr_object * next
Definition: cdr.c:777
struct cdr_object_snapshot party_b
Definition: cdr.c:756
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct cdr_object_snapshot party_a
Definition: cdr.c:755
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:407
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:736
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
const ast_string_field name
int ast_cdr_unregister ( const char *  name)

Unregister a CDR handling engine.

Parameters
namename of CDR handler to unregister Unregisters a CDR by it's name
Return values
0The backend unregistered successfully
-1The backend could not be unregistered at this time

Definition at line 3050 of file cdr.c.

3051 {
3052  return ast_cdr_generic_unregister(&be_list, name);
3053 }
List of registered backends.
Definition: cdr.c:372
static void bridge_candidate_process ( struct cdr_object cdr,
struct cdr_object base_cand_cdr 
)
static

Process a single bridge_candidate.

When a CDR enters a bridge, it needs to make pairings with everyone else that it is not currently paired with. This function determines, for the CDR for the channel that entered the bridge and the CDR for every other channel currently in the bridge, who is Party A and makes new CDRs.

Parameters
cdrThe cdr_object being processed
base_cand_cdrThe cdr_object that is a candidate

Definition at line 2566 of file cdr.c.

References ast_channel_snapshot::base, cdr_object::bridge, CDR_DEBUG, cdr_object_pick_party_a(), cdr_object_snapshot_copy(), cdr_object::end, ast_channel_snapshot_base::name, cdr_object::next, cdr_object::party_a, cdr_object::party_b, and cdr_object_snapshot::snapshot.

Referenced by handle_bridge_pairings().

2567 {
2568  struct cdr_object_snapshot *party_a;
2569  struct cdr_object *cand_cdr;
2570 
2571  ao2_lock(base_cand_cdr);
2572 
2573  for (cand_cdr = base_cand_cdr; cand_cdr; cand_cdr = cand_cdr->next) {
2574  /* Skip any records that are not in this bridge */
2575  if (strcmp(cand_cdr->bridge, cdr->bridge)) {
2576  continue;
2577  }
2578 
2579  /* If the candidate is us or someone we've taken on, pass on by */
2580  if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)
2581  || (cdr->party_b.snapshot
2582  && !strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name))) {
2583  break;
2584  }
2585 
2586  party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
2587  /* We're party A - make a new CDR, append it to us, and set the candidate as
2588  * Party B */
2589  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2590  bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);
2591  break;
2592  }
2593 
2594  /* We're Party B. Check if we can add ourselves immediately or if we need
2595  * a new CDR for them (they already have a Party B) */
2596  if (cand_cdr->party_b.snapshot
2597  && strcasecmp(cand_cdr->party_b.snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2598  bridge_candidate_add_to_cdr(cand_cdr, &cdr->party_a);
2599  } else {
2600  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
2601  cand_cdr, cand_cdr->party_a.snapshot->base->name,
2602  cdr->party_a.snapshot->base->name);
2603  cdr_object_snapshot_copy(&cand_cdr->party_b, &cdr->party_a);
2604  cdr_all_relink(cand_cdr);
2605  /* It's possible that this joined at one point and was never chosen
2606  * as party A. Clear their end time, as it would be set in such a
2607  * case.
2608  */
2609  memset(&cand_cdr->end, 0, sizeof(cand_cdr->end));
2610  }
2611 
2612  break;
2613  }
2614 
2615  ao2_unlock(base_cand_cdr);
2616 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
struct cdr_object * next
Definition: cdr.c:777
struct cdr_object_snapshot party_b
Definition: cdr.c:756
A wrapper object around a snapshot. Fields that are mutable by the CDR engine are replicated here...
Definition: cdr.c:746
struct cdr_object_snapshot party_a
Definition: cdr.c:755
Definition: cdr.h:226
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:1231
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct timeval end
Definition: cdr.c:762
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:833
const ast_string_field bridge
Definition: cdr.c:776
const ast_string_field name
static struct cdr_object* cdr_object_alloc ( struct ast_channel_snapshot chan,
const struct timeval *  event_time 
)
static

cdr_object constructor

Parameters
chanThe ast_channel_snapshot that is the CDR's Party A
event_timeThis implicitly sets the state of the newly created CDR to the Single state (single_state_fn_table)

Definition at line 1079 of file cdr.c.

References ast_atomic_fetchadd_int(), ast_string_field_init, ast_string_field_set, ast_channel_snapshot::base, CDR_DEBUG, cdr_object_dtor(), cdr_object_transition_state(), cdr_object::disposition, cdr_object::last, cdr_object::lastevent, ast_channel_snapshot_peer::linkedid, cdr_object::linkedid, ast_channel_snapshot_base::name, cdr_object::name, cdr_object::party_a, ast_channel_snapshot::peer, cdr_object::sequence, cdr_object_snapshot::snapshot, ast_channel_snapshot_base::uniqueid, and cdr_object::uniqueid.

Referenced by cdr_object_create_and_append(), and handle_channel_snapshot_update_message().

1080 {
1081  struct cdr_object *cdr;
1082 
1083  ast_assert(chan != NULL);
1084 
1085  cdr = ao2_alloc(sizeof(*cdr), cdr_object_dtor);
1086  if (!cdr) {
1087  return NULL;
1088  }
1089  cdr->last = cdr;
1090  if (ast_string_field_init(cdr, 64)) {
1091  ao2_cleanup(cdr);
1092  return NULL;
1093  }
1095  ast_string_field_set(cdr, name, chan->base->name);
1097  cdr->disposition = AST_CDR_NULL;
1099  cdr->lastevent = *event_time;
1100 
1101  cdr->party_a.snapshot = chan;
1102  ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
1103 
1104  CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->base->name);
1105 
1107 
1108  return cdr;
1109 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
static void cdr_object_dtor(void *obj)
cdr_object Destructor
Definition: cdr.c:1038
const ast_string_field uniqueid
unsigned int sequence
Definition: cdr.c:764
struct cdr_object_snapshot party_a
Definition: cdr.c:755
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:757
static int global_cdr_sequence
The global sequence counter used for CDRs.
Definition: cdr.c:391
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
const ast_string_field linkedid
Definition: cdr.c:776
Definition: cdr.h:226
enum ast_cdr_disposition disposition
Definition: cdr.c:759
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct cdr_object * last
Definition: cdr.c:778
struct cdr_object_fn_table single_state_fn_table
The virtual table for the Single state.
Definition: cdr.c:615
struct timeval lastevent
Definition: cdr.c:763
const ast_string_field name
Definition: cdr.c:776
const ast_string_field uniqueid
Definition: cdr.c:776
struct ast_channel_snapshot_peer * peer
const ast_string_field name
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:864
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
static struct cdr_object* cdr_object_create_and_append ( struct cdr_object cdr,
const struct timeval *  event_time 
)
static

Create a new cdr_object and append it to an existing chain.

Parameters
cdrThe cdr_object to append to
event_time

Definition at line 1116 of file cdr.c.

References cdr_object::appl, AST_CDR_FLAG_DISABLE_ALL, ast_string_field_set, cdr_object_alloc(), cdr_object_snapshot_copy(), cdr_object::context, cdr_object::data, cdr_object::disposition, cdr_object::exten, cdr_object::flags, cdr_object::last, cdr_object::linkedid, cdr_object::next, cdr_object::party_a, and cdr_object_snapshot::snapshot.

Referenced by ast_cdr_fork(), handle_channel_snapshot_update_message(), handle_dial_message(), handle_parked_call_message(), handle_parking_bridge_enter_message(), and handle_standard_bridge_enter_message().

1117 {
1118  struct cdr_object *new_cdr;
1119  struct cdr_object *it_cdr;
1120  struct cdr_object *cdr_last;
1121 
1122  cdr_last = cdr->last;
1123  new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot, event_time);
1124  if (!new_cdr) {
1125  return NULL;
1126  }
1127  new_cdr->disposition = AST_CDR_NULL;
1128 
1129  /* Copy over the linkedid, as it may have changed */
1130  ast_string_field_set(new_cdr, linkedid, cdr_last->linkedid);
1131  ast_string_field_set(new_cdr, appl, cdr_last->appl);
1132  ast_string_field_set(new_cdr, data, cdr_last->data);
1133  ast_string_field_set(new_cdr, context, cdr_last->context);
1134  ast_string_field_set(new_cdr, exten, cdr_last->exten);
1135 
1136  /*
1137  * If the current CDR says to disable all future ones,
1138  * keep the disable chain going
1139  */
1140  if (ast_test_flag(&cdr_last->flags, AST_CDR_FLAG_DISABLE_ALL)) {
1141  ast_set_flag(&new_cdr->flags, AST_CDR_FLAG_DISABLE_ALL);
1142  }
1143 
1144  /* Copy over other Party A information */
1145  cdr_object_snapshot_copy(&new_cdr->party_a, &cdr_last->party_a);
1146 
1147  /* Append the CDR to the end of the list */
1148  for (it_cdr = cdr; it_cdr->next; it_cdr = it_cdr->next) {
1149  it_cdr->last = new_cdr;
1150  }
1151  it_cdr->last = new_cdr;
1152  it_cdr->next = new_cdr;
1153 
1154  return new_cdr;
1155 }
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
struct cdr_object * next
Definition: cdr.c:777
const ast_string_field exten
Definition: cdr.c:776
static struct cdr_object * cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
cdr_object constructor
Definition: cdr.c:1079
struct cdr_object_snapshot party_a
Definition: cdr.c:755
const ast_string_field appl
Definition: cdr.c:776
const ast_string_field context
Definition: cdr.c:776
struct ast_flags flags
Definition: cdr.c:765
const ast_string_field linkedid
Definition: cdr.c:776
enum ast_cdr_disposition disposition
Definition: cdr.c:759
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct cdr_object * last
Definition: cdr.c:778
const ast_string_field data
Definition: cdr.c:776
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:833
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
static struct ast_cdr* cdr_object_create_public_records ( struct cdr_object cdr)
static

Create a chain of ast_cdr objects from a chain of cdr_object suitable for consumption by the registered CDR backends.

Parameters
cdrThe cdr_object to convert to a public record
Returns
A chain of ast_cdr objects on success
Return values
NULLon failure

Definition at line 1326 of file cdr.c.

References ast_channel_snapshot_base::accountcode, ast_cdr::accountcode, ast_channel_snapshot::amaflags, ast_cdr::amaflags, cdr_object::answer, cdr_object::appl, ast_calloc, ast_copy_string(), ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_channel_snapshot::base, ast_cdr::billsec, ast_channel_snapshot::caller, cdr_object_get_billsec(), cdr_object_get_duration(), ast_cdr::clid, cdr_object::context, copy_variables(), cdr_object::data, ast_cdr::dcontext, ast_cdr::disposition, cdr_object::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, cdr_object::end, cdr_object::exten, cdr_object::flags, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::linkedid, cdr_object::linkedid, ast_channel_snapshot_caller::name, ast_channel_snapshot_base::name, cdr_object::next, ast_channel_snapshot_caller::number, cdr_object::party_a, cdr_object::party_b, ast_cdr::peeraccount, ast_cdr::sequence, cdr_object::sequence, cdr_object_snapshot::snapshot, snapshot_is_dialed(), ast_cdr::src, cdr_object::start, ast_channel_snapshot_base::uniqueid, ast_cdr::uniqueid, ast_cdr::userfield, cdr_object_snapshot::userfield, cdr_object_snapshot::variables, and ast_cdr::varshead.

Referenced by cdr_object_dispatch().

1327 {
1328  struct ast_cdr *pub_cdr = NULL, *cdr_prev = NULL;
1329  struct cdr_object *it_cdr;
1330  struct ast_var_t *it_var, *it_copy_var;
1331  struct ast_channel_snapshot *party_a;
1332  struct ast_channel_snapshot *party_b;
1333 
1334  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1335  struct ast_cdr *cdr_copy;
1336 
1337  /* Don't create records for CDRs where the party A was a dialed channel */
1338  if (snapshot_is_dialed(it_cdr->party_a.snapshot) && !it_cdr->party_b.snapshot) {
1339  ast_debug(1, "CDR for %s is dialed and has no Party B; discarding\n",
1340  it_cdr->party_a.snapshot->base->name);
1341  continue;
1342  }
1343 
1344  cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
1345  if (!cdr_copy) {
1346  ast_free(pub_cdr);
1347  return NULL;
1348  }
1349 
1350  party_a = it_cdr->party_a.snapshot;
1351  party_b = it_cdr->party_b.snapshot;
1352 
1353  /* Party A */
1354  ast_assert(party_a != NULL);
1355  ast_copy_string(cdr_copy->accountcode, party_a->base->accountcode, sizeof(cdr_copy->accountcode));
1356  cdr_copy->amaflags = party_a->amaflags;
1357  ast_copy_string(cdr_copy->channel, party_a->base->name, sizeof(cdr_copy->channel));
1358  ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller->name, party_a->caller->number, "");
1359  ast_copy_string(cdr_copy->src, party_a->caller->number, sizeof(cdr_copy->src));
1360  ast_copy_string(cdr_copy->uniqueid, party_a->base->uniqueid, sizeof(cdr_copy->uniqueid));
1361  ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
1362  ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
1363  ast_copy_string(cdr_copy->dst, it_cdr->exten, sizeof(cdr_copy->dst));
1364  ast_copy_string(cdr_copy->dcontext, it_cdr->context, sizeof(cdr_copy->dcontext));
1365 
1366  /* Party B */
1367  if (party_b) {
1368  ast_copy_string(cdr_copy->dstchannel, party_b->base->name, sizeof(cdr_copy->dstchannel));
1369  ast_copy_string(cdr_copy->peeraccount, party_b->base->accountcode, sizeof(cdr_copy->peeraccount));
1370  if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
1371  snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
1372  }
1373  }
1374  if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) {
1375  ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield));
1376  }
1377 
1378  /* Timestamps/durations */
1379  cdr_copy->start = it_cdr->start;
1380  cdr_copy->answer = it_cdr->answer;
1381  cdr_copy->end = it_cdr->end;
1382  cdr_copy->billsec = cdr_object_get_billsec(it_cdr);
1383  cdr_copy->duration = cdr_object_get_duration(it_cdr);
1384 
1385  /* Flags and IDs */
1386  ast_copy_flags(cdr_copy, &it_cdr->flags, AST_FLAGS_ALL);
1387  ast_copy_string(cdr_copy->linkedid, it_cdr->linkedid, sizeof(cdr_copy->linkedid));
1388  cdr_copy->disposition = it_cdr->disposition;
1389  cdr_copy->sequence = it_cdr->sequence;
1390 
1391  /* Variables */
1392  copy_variables(&cdr_copy->varshead, &it_cdr->party_a.variables);
1393  AST_LIST_TRAVERSE(&it_cdr->party_b.variables, it_var, entries) {
1394  int found = 0;
1395  struct ast_var_t *newvariable;
1396  AST_LIST_TRAVERSE(&cdr_copy->varshead, it_copy_var, entries) {
1397  if (!strcasecmp(ast_var_name(it_var), ast_var_name(it_copy_var))) {
1398  found = 1;
1399  break;
1400  }
1401  }
1402  if (!found && (newvariable = ast_var_assign(ast_var_name(it_var), ast_var_value(it_var)))) {
1403  AST_LIST_INSERT_TAIL(&cdr_copy->varshead, newvariable, entries);
1404  }
1405  }
1406 
1407  if (!pub_cdr) {
1408  pub_cdr = cdr_copy;
1409  cdr_prev = pub_cdr;
1410  } else {
1411  cdr_prev->next = cdr_copy;
1412  cdr_prev = cdr_copy;
1413  }
1414  }
1415 
1416  return pub_cdr;
1417 }
static long cdr_object_get_billsec(struct cdr_object *cdr)
Compute the billsec for a cdr_object.
Definition: cdr.c:1274
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:311
struct ast_channel_snapshot_base * base
struct varshead variables
Definition: cdr.c:750
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:291
const ast_string_field name
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
long int billsec
Definition: cdr.h:305
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:287
struct cdr_object * next
Definition: cdr.c:777
struct cdr_object_snapshot party_b
Definition: cdr.c:756
Structure representing a snapshot of channel state.
int sequence
Definition: cdr.h:323
const ast_string_field accountcode
const ast_string_field exten
Definition: cdr.c:776
struct timeval answer
Definition: cdr.c:761
const ast_string_field uniqueid
unsigned int sequence
Definition: cdr.c:764
struct timeval start
Definition: cdr.c:760
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:788
static long cdr_object_get_duration(struct cdr_object *cdr)
Definition: cdr.c:1266
struct cdr_object_snapshot party_a
Definition: cdr.c:755
const ast_string_field appl
Definition: cdr.c:776
struct varshead varshead
Definition: cdr.h:326
const ast_string_field context
Definition: cdr.c:776
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:295
long int amaflags
Definition: cdr.h:309
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:748
struct ast_flags flags
Definition: cdr.c:765
char linkedid[AST_MAX_UNIQUEID]
Definition: cdr.h:319
const ast_string_field linkedid
Definition: cdr.c:776
char uniqueid[AST_MAX_UNIQUEID]
Definition: cdr.h:317
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:285
#define ast_debug(level,...)
Log a DEBUG message.
enum ast_cdr_disposition disposition
Definition: cdr.c:759
struct ast_channel_snapshot_caller * caller
An in-memory representation of an active CDR.
Definition: cdr.c:754
Responsible for call detail data.
Definition: cdr.h:279
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:293
const ast_string_field data
Definition: cdr.c:776
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
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:1218
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
struct timeval end
Definition: cdr.c:762
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
long int duration
Definition: cdr.h:303
char src[AST_MAX_EXTENSION]
Definition: cdr.h:283
char peeraccount[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:313
const ast_string_field number
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
long int disposition
Definition: cdr.h:307
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:281
const ast_string_field name
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:321
static void cdr_object_dispatch ( struct cdr_object cdr)
static

Dispatch a CDR.

Parameters
cdrThe cdr_object to dispatch

This will create a ast_cdr object and publish it to the various backends

Definition at line 1425 of file cdr.c.

References ast_channel_snapshot::base, CDR_DEBUG, cdr_object_create_public_records(), ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, and cdr_object_snapshot::snapshot.

Referenced by cdr_object_dispatch_all_cb(), and handle_channel_snapshot_update_message().

1426 {
1427  struct ast_cdr *pub_cdr;
1428 
1429  CDR_DEBUG("%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
1430  cdr->party_a.snapshot->base->name,
1431  cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<none>");
1432  pub_cdr = cdr_object_create_public_records(cdr);
1433  cdr_detach(pub_cdr);
1434 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
struct cdr_object_snapshot party_b
Definition: cdr.c:756
struct cdr_object_snapshot party_a
Definition: cdr.c:755
Definition: cdr.h:226
Responsible for call detail data.
Definition: cdr.h:279
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:1326
const ast_string_field name
static void cdr_object_finalize ( struct cdr_object cdr)
static

Finalize a CDR.

This function is safe to call multiple times. Note that you can call this explicitly before going to the finalized state if there's a chance the CDR will be re-activated, in which case the cdr's end time should be cleared. This function is implicitly called when a CDR transitions to the finalized state and right before it is dispatched

Parameters
cdrThe CDR to finalize

Definition at line 1479 of file cdr.c.

References cdr_object::answer, ast_cdr_disp2str(), ast_debug, ast_tvdiff_ms(), ast_tvzero(), ast_channel_snapshot::base, ast_channel_snapshot_hangup::cause, cdr_object_set_disposition(), cdr_object::disposition, cdr_object::end, ast_channel_snapshot::hangup, cdr_object::lastevent, ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, cdr_object_snapshot::snapshot, and cdr_object::start.

Referenced by ast_cdr_fork(), cdr_object_check_party_a_hangup(), cdr_object_party_b_left_bridge_cb(), handle_channel_snapshot_update_message(), handle_standard_bridge_enter_message(), and single_state_bridge_enter_comparison().

1480 {
1481  if (!ast_tvzero(cdr->end)) {
1482  return;
1483  }
1484  cdr->end = cdr->lastevent;
1485 
1486  if (cdr->disposition == AST_CDR_NULL) {
1487  if (!ast_tvzero(cdr->answer)) {
1488  cdr->disposition = AST_CDR_ANSWERED;
1489  } else if (cdr->party_a.snapshot->hangup->cause) {
1491  } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangup->cause) {
1493  } else {
1494  cdr->disposition = AST_CDR_FAILED;
1495  }
1496  }
1497 
1498  /* tv_usec is suseconds_t, which could be int or long */
1499  ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dur %.3f bill %.3f dispo %s\n",
1500  cdr->party_a.snapshot->base->name,
1501  (long)cdr->start.tv_sec,
1502  (long)cdr->start.tv_usec,
1503  (long)cdr->answer.tv_sec,
1504  (long)cdr->answer.tv_usec,
1505  (long)cdr->end.tv_sec,
1506  (long)cdr->end.tv_usec,
1507  (double)ast_tvdiff_ms(cdr->end, cdr->start) / 1000.0,
1508  (double)ast_tvdiff_ms(cdr->end, cdr->answer) / 1000.0,
1510 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
struct cdr_object_snapshot party_b
Definition: cdr.c:756
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
struct timeval answer
Definition: cdr.c:761
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:1441
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval start
Definition: cdr.c:760
struct cdr_object_snapshot party_a
Definition: cdr.c:755
struct ast_channel_snapshot_hangup * hangup
#define ast_debug(level,...)
Log a DEBUG message.
enum ast_cdr_disposition disposition
Definition: cdr.c:759
struct timeval lastevent
Definition: cdr.c:763
struct timeval end
Definition: cdr.c:762
const ast_string_field name
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3492
static long cdr_object_get_duration ( struct cdr_object cdr)
static

Compute the duration for a cdr_object

Definition at line 1266 of file cdr.c.

References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), cdr_object::end, and cdr_object::start.

Referenced by cdr_object_create_public_records(), and cdr_object_format_property().

1267 {
1268  return (long)(ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->start) / 1000);
1269 }
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval start
Definition: cdr.c:760
struct timeval end
Definition: cdr.c:762
static struct cdr_object_snapshot* cdr_object_pick_party_a ( struct cdr_object_snapshot left,
struct cdr_object_snapshot right 
)
static

Given two CDR snapshots, figure out who should be Party A for the resulting CDR.

Parameters
leftOne of the snapshots
rightThe other snapshot
Returns
The snapshot that won

Definition at line 1231 of file cdr.c.

References AST_CDR_FLAG_PARTY_A, ast_channel_snapshot::base, ast_channel_snapshot_base::creationtime, cdr_object_snapshot::snapshot, and snapshot_is_dialed().

Referenced by bridge_candidate_process(), and single_state_bridge_enter_comparison().

1232 {
1233  /* Check whether or not the party is dialed. A dialed party is never the
1234  * Party A with a party that was not dialed.
1235  */
1236  if (!snapshot_is_dialed(left->snapshot) && snapshot_is_dialed(right->snapshot)) {
1237  return left;
1238  } else if (snapshot_is_dialed(left->snapshot) && !snapshot_is_dialed(right->snapshot)) {
1239  return right;
1240  }
1241 
1242  /* Try the Party A flag */
1243  if (ast_test_flag(left, AST_CDR_FLAG_PARTY_A) && !ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
1244  return left;
1245  } else if (!ast_test_flag(left, AST_CDR_FLAG_PARTY_A) && ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
1246  return right;
1247  }
1248 
1249  /* Neither party is dialed and neither has the Party A flag - defer to
1250  * creation time */
1251  if (left->snapshot->base->creationtime.tv_sec < right->snapshot->base->creationtime.tv_sec) {
1252  return left;
1253  } else if (left->snapshot->base->creationtime.tv_sec > right->snapshot->base->creationtime.tv_sec) {
1254  return right;
1255  } else if (left->snapshot->base->creationtime.tv_usec > right->snapshot->base->creationtime.tv_usec) {
1256  return right;
1257  } else {
1258  /* Okay, fine, take the left one */
1259  return left;
1260  }
1261 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
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:1218
static void cdr_object_set_disposition ( struct cdr_object cdr,
int  hangupcause 
)
static

Set the disposition on a cdr_object based on a hangupcause code.

Parameters
cdrThe cdr_object
hangupcauseThe Asterisk hangup cause code

Definition at line 1441 of file cdr.c.

References CDR_CONGESTION, and cdr_object::disposition.

Referenced by cdr_object_finalize().

1442 {
1443  /* Change the disposition based on the hang up cause */
1444  switch (hangupcause) {
1445  case AST_CAUSE_BUSY:
1446  cdr->disposition = AST_CDR_BUSY;
1447  break;
1448  case AST_CAUSE_CONGESTION:
1449  if (!is_cdr_flag_set(CDR_CONGESTION)) {
1450  cdr->disposition = AST_CDR_FAILED;
1451  } else {
1452  cdr->disposition = AST_CDR_CONGESTION;
1453  }
1454  break;
1455  case AST_CAUSE_NO_ROUTE_DESTINATION:
1456  case AST_CAUSE_UNREGISTERED:
1457  cdr->disposition = AST_CDR_FAILED;
1458  break;
1459  case AST_CAUSE_NORMAL_CLEARING:
1460  case AST_CAUSE_NO_ANSWER:
1461  cdr->disposition = AST_CDR_NOANSWER;
1462  break;
1463  default:
1464  break;
1465  }
1466 }
enum ast_cdr_disposition disposition
Definition: cdr.c:759
static void cdr_object_snapshot_copy ( struct cdr_object_snapshot dst,
struct cdr_object_snapshot src 
)
static

Copy a snapshot and its details.

Parameters
dstThe destination
srcThe source

Definition at line 833 of file cdr.c.

References copy_variables(), cdr_object_snapshot::flags, cdr_object_snapshot::snapshot, cdr_object_snapshot::userfield, and cdr_object_snapshot::variables.

Referenced by bridge_candidate_process(), cdr_object_create_and_append(), and single_state_bridge_enter_comparison().

834 {
835  ao2_t_replace(dst->snapshot, src->snapshot, "CDR snapshot copy");
836  strcpy(dst->userfield, src->userfield);
837  dst->flags = src->flags;
838  copy_variables(&dst->variables, &src->variables);
839 }
struct varshead variables
Definition: cdr.c:750
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
unsigned int flags
Definition: cdr.c:749
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:788
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:748
static void cdr_object_swap_snapshot ( struct cdr_object_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot 
)
static

Swap an old cdr_object_snapshot's ast_channel_snapshot for a new ast_channel_snapshot.

Parameters
old_snapshotThe old cdr_object_snapshot
new_snapshotThe new ast_channel_snapshot for old_snapshot

Definition at line 1570 of file cdr.c.

References cdr_object_update_cid(), and cdr_object_snapshot::snapshot.

1572 {
1573  cdr_object_update_cid(old_snapshot, new_snapshot);
1574  ao2_t_replace(old_snapshot->snapshot, new_snapshot, "Swap CDR shapshot");
1575 }
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Set Caller ID information on a CDR.
Definition: cdr.c:1545
static void cdr_object_transition_state ( struct cdr_object cdr,
struct cdr_object_fn_table fn_table 
)
static

Transition a cdr_object to a new state.

Parameters
cdrThe cdr_object to transition
fn_tableThe cdr_object_fn_table state to go to

Definition at line 864 of file cdr.c.

References cdr_object_transition_state_init().

Referenced by ast_cdr_fork(), cdr_object_alloc(), cdr_object_check_party_a_hangup(), cdr_object_dispatch_all_cb(), and handle_parking_bridge_enter_message().

865 {
866  cdr_object_transition_state_init(cdr, fn_table, 1);
867 }
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:847
static void cdr_object_transition_state_init ( struct cdr_object cdr,
struct cdr_object_fn_table fn_table,
int  do_init 
)
static

Transition a cdr_object to a new state with initiation flag.

Parameters
cdrThe cdr_object to transition
fn_tableThe cdr_object_fn_table state to go to
do_init

Definition at line 847 of file cdr.c.

References ast_channel_snapshot::base, CDR_DEBUG, cdr_object::fn_table, cdr_object_fn_table::init_function, ast_channel_snapshot_base::name, cdr_object_fn_table::name, cdr_object::party_a, and cdr_object_snapshot::snapshot.

Referenced by cdr_object_transition_state().

848 {
849  CDR_DEBUG("%p - Transitioning CDR for %s from state %s to %s\n",
850  cdr, cdr->party_a.snapshot->base->name,
851  cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
852  cdr->fn_table = fn_table;
853 
854  if (cdr->fn_table->init_function && do_init) {
855  cdr->fn_table->init_function(cdr);
856  }
857 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
struct cdr_object_snapshot party_a
Definition: cdr.c:755
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:469
Definition: cdr.h:226
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
const char * name
Name of the subclass.
Definition: cdr.c:460
const ast_string_field name
static int copy_variables ( struct varshead to_list,
struct varshead from_list 
)
static

Copy variables from one list to another.

Parameters
to_listdestination
from_listsource
Returns
The number of copied variables

Definition at line 788 of file cdr.c.

References AST_LIST_INSERT_HEAD, and AST_LIST_TRAVERSE.

Referenced by ast_cdr_dup(), ast_cdr_fork(), cdr_object_create_public_records(), and cdr_object_snapshot_copy().

789 {
790  struct ast_var_t *variables;
791  struct ast_var_t *newvariable;
792  const char *var;
793  const char *val;
794  int x = 0;
795 
796  AST_LIST_TRAVERSE(from_list, variables, entries) {
797  var = ast_var_name(variables);
798  if (ast_strlen_zero(var)) {
799  continue;
800  }
801  val = ast_var_value(variables);
802  if (ast_strlen_zero(val)) {
803  continue;
804  }
805  newvariable = ast_var_assign(var, val);
806  if (newvariable) {
807  AST_LIST_INSERT_HEAD(to_list, newvariable, entries);
808  ++x;
809  }
810  }
811 
812  return x;
813 }
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
static void free_variables ( struct varshead headp)
static

Delete all variables from a variable list.

Parameters
headpThe head pointer to the variable list to delete

Definition at line 819 of file cdr.c.

References AST_LIST_REMOVE_HEAD.

Referenced by ast_cdr_fork(), and ast_cdr_free().

820 {
821  struct ast_var_t *vardata;
822 
823  while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
824  ast_var_delete(vardata);
825  }
826 }
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
static void handle_bridge_leave_message ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Handler for when a channel leaves a bridge.

Parameters
dataPassed on
subThe stasis subscription for this message callback
messageThe message - hopefully a bridge one!

Definition at line 2467 of file cdr.c.

References ast_string_field_set, ast_channel_snapshot::base, ast_bridge_blob::bridge, CDR_DEBUG, cdr_object_party_b_left_bridge_cb(), ast_bridge_blob::channel, filter_bridge_messages(), cdr_object::fn_table, cdr_object::lastevent, ast_channel_snapshot_base::name, cdr_object::next, OBJ_MULTIPLE, OBJ_NODATA, OBJ_SEARCH_KEY, cdr_object_fn_table::process_bridge_leave, stasis_message_data(), stasis_message_timestamp(), ast_bridge_snapshot::subclass, and ast_channel_snapshot_base::uniqueid.

2469 {
2470  struct ast_bridge_blob *update = stasis_message_data(message);
2471  struct ast_bridge_snapshot *bridge = update->bridge;
2472  struct ast_channel_snapshot *channel = update->channel;
2473  struct cdr_object *cdr;
2474  struct cdr_object *it_cdr;
2475  struct bridge_leave_data leave_data = {
2476  .bridge = bridge,
2477  .channel = channel,
2478  .lastevent = stasis_message_timestamp(message)
2479  };
2480  int left_bridge = 0;
2481 
2482  if (filter_bridge_messages(bridge)) {
2483  return;
2484  }
2485 
2486  if (filter_channel_snapshot(channel)) {
2487  return;
2488  }
2489 
2490  CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n",
2491  channel->base->name,
2492  (unsigned int)leave_data.lastevent->tv_sec,
2493  (unsigned int)leave_data.lastevent->tv_usec);
2494 
2495  cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);
2496  if (!cdr) {
2497  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2498  ast_assert(0);
2499  return;
2500  }
2501 
2502  /* Party A */
2503  ao2_lock(cdr);
2504  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2505  it_cdr->lastevent = *leave_data.lastevent;
2506  if (!it_cdr->fn_table->process_bridge_leave) {
2507  continue;
2508  }
2509  CDR_DEBUG("%p - Processing Bridge Leave for %s\n",
2510  it_cdr, channel->base->name);
2511  if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
2512  ast_string_field_set(it_cdr, bridge, "");
2513  left_bridge = 1;
2514  }
2515  }
2516  ao2_unlock(cdr);
2517 
2518  /* Party B */
2519  if (left_bridge
2520  && strcmp(bridge->subclass, "parking")) {
2521  ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,
2522  cdr_object_party_b_left_bridge_cb, (char *) leave_data.channel->base->name,
2523  &leave_data);
2524  }
2525 
2526  ao2_cleanup(cdr);
2527 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * channel
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:314
struct cdr_object * next
Definition: cdr.c:777
Structure representing a snapshot of channel state.
const ast_string_field uniqueid
struct ast_bridge_snapshot * bridge
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
static int filter_bridge_messages(struct ast_bridge_snapshot *bridge)
Filter bridge messages based on bridge technology.
Definition: cdr.c:2450
Definition: cdr.h:226
Blob of data associated with a bridge.
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:407
struct timeval lastevent
Definition: cdr.c:763
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:2425
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:410
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:575
const ast_string_field subclass
Definition: bridge.h:328
const ast_string_field name
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
static void handle_bridge_pairings ( struct cdr_object cdr,
struct ast_bridge_snapshot bridge 
)
static

Handle creating bridge pairings for the cdr_object that just entered a bridge.

Parameters
cdrThe cdr_object that just entered the bridge
bridgeThe ast_bridge_snapshot representing the bridge it just entered

Definition at line 2624 of file cdr.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_ref, bridge_candidate_process(), ast_bridge_snapshot::channels, and OBJ_SEARCH_KEY.

Referenced by handle_standard_bridge_enter_message().

2625 {
2626  struct ao2_iterator it_channels;
2627  char *channel_id;
2628 
2629  it_channels = ao2_iterator_init(bridge->channels, 0);
2630  while ((channel_id = ao2_iterator_next(&it_channels))) {
2631  struct cdr_object *cand_cdr;
2632 
2633  cand_cdr = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
2634  if (cand_cdr) {
2635  bridge_candidate_process(cdr, cand_cdr);
2636  ao2_ref(cand_cdr, -1);
2637  }
2638 
2639  ao2_ref(channel_id, -1);
2640  }
2641  ao2_iterator_destroy(&it_channels);
2642 }
struct ao2_container * channels
Definition: bridge.h:331
static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
Process a single bridge_candidate.
Definition: cdr.c:2566
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
An in-memory representation of an active CDR.
Definition: cdr.c:754
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:407
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static void handle_cdr_sync_message ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Handler for a synchronization message.

Parameters
dataPassed on
subThe stasis subscription for this message callback
messageA blank ao2 object

Definition at line 2882 of file cdr.c.

2884 {
2885  return;
2886 }
static void handle_channel_snapshot_update_message ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Handler for channel snapshot update messages.

Parameters
dataPassed on
subThe stasis subscription for this message callback
messageThe message

Definition at line 2329 of file cdr.c.

References ao2_global_obj_ref, ao2_link, ao2_unlink, AST_CDR_FLAG_DISABLE_ALL, ast_debug, AST_FLAG_DEAD, ast_channel_snapshot::base, CDR_CHANNEL_DEFAULT_ENABLED, CDR_DEBUG, cdr_object_alloc(), cdr_object_create_and_append(), cdr_object_dispatch(), cdr_object_finalize(), check_new_cdr_needed(), ast_channel_snapshot::flags, cdr_object::flags, cdr_object::fn_table, module_config::general, cdr_object::is_root, cdr_object::lastevent, ast_channel_snapshot_base::name, ast_channel_snapshot_update::new_snapshot, cdr_object::next, OBJ_MULTIPLE, OBJ_NODATA, OBJ_SEARCH_KEY, ast_channel_snapshot_update::old_snapshot, cdr_object_fn_table::process_party_a, ast_cdr_config::settings, stasis_message_data(), stasis_message_timestamp(), and ast_channel_snapshot_base::uniqueid.

2330 {
2331  struct cdr_object *cdr;
2332  struct ast_channel_snapshot_update *update = stasis_message_data(message);
2333  struct cdr_object *it_cdr;
2334 
2335  if (filter_channel_snapshot_message(update->old_snapshot, update->new_snapshot)) {
2336  return;
2337  }
2338 
2339  if (update->new_snapshot && !update->old_snapshot) {
2340  struct module_config *mod_cfg = NULL;
2341 
2342  cdr = cdr_object_alloc(update->new_snapshot, stasis_message_timestamp(message));
2343  if (!cdr) {
2344  return;
2345  }
2346  mod_cfg = ao2_global_obj_ref(module_configs);
2347  cdr->is_root = 1;
2349 
2350  /* If CDR should be disabled unless enabled on a per-channel basis, then disable
2351  CDR, right from the get go */
2352  if (mod_cfg) {
2353  if (!ast_test_flag(&mod_cfg->general->settings, CDR_CHANNEL_DEFAULT_ENABLED)) {
2354  ast_debug(3, "Disable CDR by default\n");
2355  ast_set_flag(&cdr->flags, AST_CDR_FLAG_DISABLE_ALL);
2356  }
2357  ao2_cleanup(mod_cfg);
2358  }
2359  } else {
2360  cdr = ao2_find(active_cdrs_master, update->new_snapshot->base->uniqueid, OBJ_SEARCH_KEY);
2361  }
2362 
2363  /* Handle Party A */
2364  if (!cdr) {
2365  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->base->name);
2366  ast_assert(0);
2367  } else {
2368  int all_reject = 1;
2369 
2370  ao2_lock(cdr);
2371  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2372  it_cdr->lastevent = *stasis_message_timestamp(message);
2373  if (!it_cdr->fn_table->process_party_a) {
2374  continue;
2375  }
2376  all_reject &= it_cdr->fn_table->process_party_a(it_cdr, update->new_snapshot);
2377  }
2378  if (all_reject && check_new_cdr_needed(update->old_snapshot, update->new_snapshot)) {
2379  /* We're not hung up and we have a new snapshot - we need a new CDR */
2380  struct cdr_object *new_cdr;
2381 
2382  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
2383  if (new_cdr) {
2384  new_cdr->fn_table->process_party_a(new_cdr, update->new_snapshot);
2385  }
2386  }
2387  ao2_unlock(cdr);
2388  }
2389 
2390  if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2391  ao2_lock(cdr);
2392  CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->base->name);
2393  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2394  it_cdr->lastevent = *stasis_message_timestamp(message);
2395  cdr_object_finalize(it_cdr);
2396  }
2397  cdr_object_dispatch(cdr);
2398  ao2_unlock(cdr);
2399 
2400  cdr_all_unlink(cdr);
2402  }
2403 
2404  /* Handle Party B */
2405  if (update->new_snapshot) {
2406  ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,
2407  cdr_object_update_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2408  }
2409 
2410  if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2411  ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,
2412  cdr_object_finalize_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2413  }
2414 
2415  ao2_cleanup(cdr);
2416 }
struct ast_channel_snapshot_base * base
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
struct ast_flags settings
Definition: cdr.h:268
struct cdr_object * next
Definition: cdr.c:777
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:479
static struct cdr_object * cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
cdr_object constructor
Definition: cdr.c:1079
const ast_string_field uniqueid
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
Structure representing a change of snapshot of channel state.
int is_root
Definition: cdr.c:779
struct ast_flags flags
Definition: cdr.c:765
static void cdr_object_dispatch(struct cdr_object *cdr)
Dispatch a CDR.
Definition: cdr.c:1425
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
The configuration settings for this module.
Definition: cdr.c:264
Definition: cdr.h:226
#define ast_debug(level,...)
Log a DEBUG message.
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:407
struct timeval lastevent
Definition: cdr.c:763
struct ast_channel_snapshot * new_snapshot
struct ast_channel_snapshot * old_snapshot
struct ast_flags flags
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:410
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:1116
struct ast_cdr_config * general
Definition: cdr.c:265
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:2301
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1479
const ast_string_field name
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
static void handle_dial_message ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Handler for Stasis-Core dial messages.

Parameters
dataPassed on
subThe stasis subscription for this message callback
messageThe message

Definition at line 2143 of file cdr.c.

References ast_json_object_get(), ast_json_string_get(), ast_multi_channel_blob_get_channel(), ast_multi_channel_blob_get_json(), ast_channel_snapshot::base, ast_channel_snapshot::caller, CDR_DEBUG, cdr_object_create_and_append(), cdr_object::disposition, cdr_object::fn_table, cdr_object::lastevent, ast_channel_snapshot_base::name, cdr_object::next, OBJ_SEARCH_KEY, ast_channel_snapshot::peer, cdr_object_fn_table::process_dial_begin, cdr_object_fn_table::process_dial_end, stasis_message_data(), stasis_message_timestamp(), and ast_channel_snapshot_base::uniqueid.

2144 {
2145  struct cdr_object *cdr;
2146  struct ast_multi_channel_blob *payload = stasis_message_data(message);
2147  struct ast_channel_snapshot *caller;
2148  struct ast_channel_snapshot *peer;
2149  struct cdr_object *it_cdr;
2150  struct ast_json *dial_status_blob;
2151  const char *dial_status = NULL;
2152  int res = 1;
2153 
2154  caller = ast_multi_channel_blob_get_channel(payload, "caller");
2155  peer = ast_multi_channel_blob_get_channel(payload, "peer");
2156  if (!peer && !caller) {
2157  return;
2158  }
2159 
2160  if (peer && filter_channel_snapshot(peer)) {
2161  return;
2162  }
2163 
2164  if (caller && filter_channel_snapshot(caller)) {
2165  return;
2166  }
2167 
2168  dial_status_blob = ast_json_object_get(ast_multi_channel_blob_get_json(payload), "dialstatus");
2169  if (dial_status_blob) {
2170  dial_status = ast_json_string_get(dial_status_blob);
2171  }
2172 
2173  CDR_DEBUG("Dial %s message for %s, %s: %u.%08u\n",
2174  ast_strlen_zero(dial_status) ? "Begin" : "End",
2175  caller ? caller->base->name : "(none)",
2176  peer ? peer->base->name : "(none)",
2177  (unsigned int)stasis_message_timestamp(message)->tv_sec,
2178  (unsigned int)stasis_message_timestamp(message)->tv_usec);
2179 
2180  /* Figure out who is running this show */
2181  if (caller) {
2182  cdr = ao2_find(active_cdrs_master, caller->base->uniqueid, OBJ_SEARCH_KEY);
2183  } else {
2184  cdr = ao2_find(active_cdrs_master, peer->base->uniqueid, OBJ_SEARCH_KEY);
2185  }
2186  if (!cdr) {
2187  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->base->name : peer->base->name);
2188  ast_assert(0);
2189  return;
2190  }
2191 
2192  ao2_lock(cdr);
2193  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2194  it_cdr->lastevent = *stasis_message_timestamp(message);
2195  if (ast_strlen_zero(dial_status)) {
2196  if (!it_cdr->fn_table->process_dial_begin) {
2197  continue;
2198  }
2199  if (dial_changes_ignored) {
2200  CDR_DEBUG("%p - Ignoring Dial Begin message\n", it_cdr);
2201  continue;
2202  }
2203  CDR_DEBUG("%p - Processing Dial Begin message for channel %s, peer %s\n",
2204  it_cdr,
2205  caller ? caller->base->name : "(none)",
2206  peer ? peer->base->name : "(none)");
2207  res &= it_cdr->fn_table->process_dial_begin(it_cdr,
2208  caller,
2209  peer);
2210  } else if (dial_status_end(dial_status)) {
2211  if (!it_cdr->fn_table->process_dial_end) {
2212  continue;
2213  }
2214  if (dial_changes_ignored) {
2215  /* Set the disposition, and do nothing else. */
2216  it_cdr->disposition = dial_status_to_disposition(dial_status);
2217  CDR_DEBUG("%p - Setting disposition and that's it (%s)\n", it_cdr, dial_status);
2218  continue;
2219  }
2220  CDR_DEBUG("%p - Processing Dial End message for channel %s, peer %s\n",
2221  it_cdr,
2222  caller ? caller->base->name : "(none)",
2223  peer ? peer->base->name : "(none)");
2224  it_cdr->fn_table->process_dial_end(it_cdr,
2225  caller,
2226  peer,
2227  dial_status);
2228  }
2229  }
2230 
2231  /* If we're ignoring dial changes, don't allow multiple CDRs for this channel. */
2232  if (!dial_changes_ignored) {
2233  /* If no CDR handled a dial begin message, make a new one */
2234  if (res && ast_strlen_zero(dial_status)) {
2235  struct cdr_object *new_cdr;
2236 
2237  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
2238  if (new_cdr) {
2239  new_cdr->fn_table->process_dial_begin(new_cdr, caller, peer);
2240  }
2241  }
2242  }
2243 
2244  ao2_unlock(cdr);
2245  ao2_cleanup(cdr);
2246 }
struct ast_channel_snapshot_base * base
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
struct cdr_object * next
Definition: cdr.c:777
Structure representing a snapshot of channel state.
const ast_string_field uniqueid
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...
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's Party A h...
Definition: cdr.c:504
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
Definition: cdr.h:226
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
enum ast_cdr_disposition disposition
Definition: cdr.c:759
struct ast_channel_snapshot_caller * caller
An in-memory representation of an active CDR.
Definition: cdr.c:754
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:407
struct timeval lastevent
Definition: cdr.c:763
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
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.
A multi channel blob data structure for multi_channel_blob stasis messages.
Abstract JSON element (object, array, string, int, ...).
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:1116
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:522
const ast_string_field name
static void handle_parked_call_message ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Handler for when a channel is parked.

Parameters
dataPassed on
subThe stasis subscription for this message callback
messageThe message about who got parked

Definition at line 2814 of file cdr.c.

References ast_channel_snapshot::base, CDR_DEBUG, cdr_object_create_and_append(), ast_parked_call_payload::event_type, cdr_object::fn_table, cdr_object::lastevent, ast_channel_snapshot_base::name, cdr_object::next, OBJ_SEARCH_KEY, ast_parked_call_payload::parkee, cdr_object_fn_table::process_parked_channel, stasis_message_data(), stasis_message_timestamp(), and ast_channel_snapshot_base::uniqueid.

2816 {
2817  struct ast_parked_call_payload *payload = stasis_message_data(message);
2818  struct ast_channel_snapshot *channel = payload->parkee;
2819  struct cdr_object *cdr;
2820  int unhandled = 1;
2821  struct cdr_object *it_cdr;
2822 
2823  /* Anything other than getting parked will be handled by other updates */
2824  if (payload->event_type != PARKED_CALL) {
2825  return;
2826  }
2827 
2828  /* No one got parked? */
2829  if (!channel) {
2830  return;
2831  }
2832 
2833  if (filter_channel_snapshot(channel)) {
2834  return;
2835  }
2836 
2837  CDR_DEBUG("Parked Call message for channel %s: %u.%08u\n",
2838  channel->base->name,
2839  (unsigned int)stasis_message_timestamp(message)->tv_sec,
2840  (unsigned int)stasis_message_timestamp(message)->tv_usec);
2841 
2842  cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);
2843  if (!cdr) {
2844  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2845  ast_assert(0);
2846  return;
2847  }
2848 
2849  ao2_lock(cdr);
2850 
2851  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2852  it_cdr->lastevent = *stasis_message_timestamp(message);
2853  if (it_cdr->fn_table->process_parked_channel) {
2854  unhandled &= it_cdr->fn_table->process_parked_channel(it_cdr, payload);
2855  }
2856  }
2857 
2858  if (unhandled) {
2859  /* Nothing handled the messgae - we need a new one! */
2860  struct cdr_object *new_cdr;
2861 
2862  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
2863  if (new_cdr) {
2864  /* As the new CDR is created in the single state, it is guaranteed
2865  * to have a function for the parked call message and will handle
2866  * the message */
2867  new_cdr->fn_table->process_parked_channel(new_cdr, payload);
2868  }
2869  }
2870 
2871  ao2_unlock(cdr);
2872 
2873  ao2_cleanup(cdr);
2874 }
struct ast_channel_snapshot_base * base
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:588
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
struct cdr_object * next
Definition: cdr.c:777
Structure representing a snapshot of channel state.
const ast_string_field uniqueid
A parked call message payload.
Definition: parking.h:59
enum ast_parked_call_event_type event_type
Definition: parking.h:62
struct ast_channel_snapshot * parkee
Definition: parking.h:60
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
Definition: cdr.h:226
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:407
struct timeval lastevent
Definition: cdr.c:763
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:1116
const ast_string_field name
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 
)
static

Handle entering into a parking bridge.

Parameters
cdrThe CDR to operate on
bridgeThe bridge the channel just entered
channelThe channel snapshot
event_time

Definition at line 2650 of file cdr.c.

References ast_channel_snapshot::base, CDR_DEBUG, cdr_object_create_and_append(), cdr_object_transition_state(), cdr_object::fn_table, cdr_object::lastevent, ast_channel_snapshot_base::name, cdr_object::next, cdr_object_fn_table::process_parking_bridge_enter, and cdr_object_fn_table::process_party_a.

2654 {
2655  int res = 1;
2656  struct cdr_object *it_cdr;
2657  struct cdr_object *new_cdr;
2658 
2659  ao2_lock(cdr);
2660 
2661  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2662  it_cdr->lastevent = *event_time;
2663 
2664  if (it_cdr->fn_table->process_parking_bridge_enter) {
2665  res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
2666  }
2667  if (it_cdr->fn_table->process_party_a) {
2668  CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2669  channel->base->name);
2670  it_cdr->fn_table->process_party_a(it_cdr, channel);
2671  }
2672  }
2673 
2674  if (res) {
2675  /* No one handled it - we need a new one! */
2676  new_cdr = cdr_object_create_and_append(cdr, event_time);
2677  if (new_cdr) {
2678  /* Let the single state transition us to Parked */
2680  new_cdr->fn_table->process_parking_bridge_enter(new_cdr, bridge, channel);
2681  }
2682  }
2683  ao2_unlock(cdr);
2684 }
struct ast_channel_snapshot_base * base
struct cdr_object * next
Definition: cdr.c:777
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:479
Definition: cdr.h:226
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct cdr_object_fn_table single_state_fn_table
The virtual table for the Single state.
Definition: cdr.c:615
struct timeval lastevent
Definition: cdr.c:763
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:561
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:1116
const ast_string_field name
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:864
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 
)
static

Handle a bridge enter message for a 'normal' bridge.

Parameters
cdrThe CDR to operate on
bridgeThe bridge the channel just entered
channelThe channel snapshot
event_time

Definition at line 2692 of file cdr.c.

References ast_channel_snapshot::base, BRIDGE_ENTER_NEED_CDR, BRIDGE_ENTER_NO_PARTY_B, BRIDGE_ENTER_OBTAINED_PARTY_B, BRIDGE_ENTER_ONLY_PARTY, CDR_DEBUG, cdr_object_create_and_append(), cdr_object_finalize(), cdr_object::fn_table, handle_bridge_pairings(), cdr_object::lastevent, ast_channel_snapshot_base::name, cdr_object::next, cdr_object_fn_table::process_bridge_enter, and cdr_object_fn_table::process_party_a.

2696 {
2697  enum process_bridge_enter_results result;
2698  struct cdr_object *it_cdr;
2699  struct cdr_object *new_cdr;
2700  struct cdr_object *handled_cdr = NULL;
2701 
2702  ao2_lock(cdr);
2703 
2704 try_again:
2705  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2706  it_cdr->lastevent = *event_time;
2707 
2708  if (it_cdr->fn_table->process_party_a) {
2709  CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2710  channel->base->name);
2711  it_cdr->fn_table->process_party_a(it_cdr, channel);
2712  }
2713 
2714  /* Notify all states that they have entered a bridge */
2715  if (it_cdr->fn_table->process_bridge_enter) {
2716  CDR_DEBUG("%p - Processing bridge enter for %s\n", it_cdr,
2717  channel->base->name);
2718  result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
2719  switch (result) {
2721  /* Fall through */
2723  if (!handled_cdr) {
2724  handled_cdr = it_cdr;
2725  }
2726  break;
2727  case BRIDGE_ENTER_NEED_CDR:
2728  /* Pass */
2729  break;
2731  /* We didn't win on any - end this CDR. If someone else comes in later
2732  * that is Party B to this CDR, it can re-activate this CDR.
2733  */
2734  if (!handled_cdr) {
2735  handled_cdr = it_cdr;
2736  }
2737  cdr_object_finalize(cdr);
2738  break;
2739  }
2740  }
2741  }
2742 
2743  /* Create the new matchings, but only for either:
2744  * * The first CDR in the chain that handled it. This avoids issues with
2745  * forked CDRs.
2746  * * If no one handled it, the last CDR in the chain. This would occur if
2747  * a CDR joined a bridge and it wasn't Party A for anyone. We still need
2748  * to make pairings with everyone in the bridge.
2749  */
2750  if (handled_cdr) {
2751  handle_bridge_pairings(handled_cdr, bridge);
2752  } else {
2753  /* Nothing handled it - we need a new one! */
2754  new_cdr = cdr_object_create_and_append(cdr, event_time);
2755  if (new_cdr) {
2756  /* This is guaranteed to succeed: the new CDR is created in the single state
2757  * and will be able to handle the bridge enter message
2758  */
2759  goto try_again;
2760  }
2761  }
2762  ao2_unlock(cdr);
2763 }
struct ast_channel_snapshot_base * base
struct cdr_object * next
Definition: cdr.c:777
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:479
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:545
process_bridge_enter_results
Return types for process_bridge_enter functions.
Definition: cdr.c:433
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:2624
Definition: cdr.h:226
struct cdr_object_fn_table * fn_table
Definition: cdr.c:757
An in-memory representation of an active CDR.
Definition: cdr.c:754
struct timeval lastevent
Definition: cdr.c:763
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:1116
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1479
const ast_string_field name
static int init_batch ( void  )
static
Note
Don't call without cdr_batch_lock

Definition at line 3800 of file cdr.c.

References ast_malloc, and reset_batch().

3801 {
3802  /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
3803  if (!(batch = ast_malloc(sizeof(*batch))))
3804  return -1;
3805 
3806  reset_batch();
3807 
3808  return 0;
3809 }
static void reset_batch(void)
Definition: cdr.c:3792
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
static void reset_batch ( void  )
static
Note
Don't call without cdr_batch_lock

Definition at line 3792 of file cdr.c.

Referenced by init_batch().

3793 {
3794  batch->size = 0;
3795  batch->head = NULL;
3796  batch->tail = NULL;
3797 }
static int single_state_bridge_enter_comparison ( struct cdr_object cdr,
struct cdr_object cand_cdr 
)
static

Handle a comparison between our cdr_object and a cdr_object already in the bridge while in the Single state. The goal of this is to find a Party B for our CDR.

Parameters
cdrOur cdr_object in the Single state
cand_cdrThe cdr_object already in the Bridge state
Return values
0The cand_cdr had a Party A or Party B that we could use as our Party B
1No party in the cand_cdr could be used as our Party B

Definition at line 1731 of file cdr.c.

References ast_channel_snapshot::base, CDR_DEBUG, cdr_object_finalize(), cdr_object_pick_party_a(), cdr_object_snapshot_copy(), ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, and cdr_object_snapshot::snapshot.

1733 {
1734  struct cdr_object_snapshot *party_a;
1735 
1736  /* Don't match on ourselves */
1737  if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
1738  return 1;
1739  }
1740 
1741  /* Try the candidate CDR's Party A first */
1742  party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
1743  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1744  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1745  cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name);
1746  cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1747  cdr_all_relink(cdr);
1748  if (!cand_cdr->party_b.snapshot) {
1749  /* We just stole them - finalize their CDR. Note that this won't
1750  * transition their state, it just sets the end time and the
1751  * disposition - if we need to re-activate them later, we can.
1752  */
1753  cdr_object_finalize(cand_cdr);
1754  }
1755  return 0;
1756  }
1757 
1758  /* Try their Party B, unless it's us */
1759  if (!cand_cdr->party_b.snapshot
1760  || !strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name)) {
1761  return 1;
1762  }
1763  party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
1764  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1765  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1766  cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name);
1767  cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
1768  cdr_all_relink(cdr);
1769  return 0;
1770  }
1771 
1772  return 1;
1773 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:747
struct cdr_object_snapshot party_b
Definition: cdr.c:756
A wrapper object around a snapshot. Fields that are mutable by the CDR engine are replicated here...
Definition: cdr.c:746
struct cdr_object_snapshot party_a
Definition: cdr.c:755
Definition: cdr.h:226
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:1231
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:833
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1479
const ast_string_field name
static int snapshot_cep_changed ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot 
)
static

Return whether or not a channel has changed its state in the dialplan, subject to endbeforehexten logic.

Parameters
old_snapshotThe previous state
new_snapshotThe new state
Return values
0if the state has not changed
1if the state changed

Definition at line 1187 of file cdr.c.

References ast_channel_snapshot_dialplan::appl, AST_SOFTHANGUP_HANGUP_EXEC, CDR_END_BEFORE_H_EXTEN, ast_channel_snapshot_dialplan::context, ast_channel_snapshot::dialplan, ast_channel_snapshot_dialplan::exten, ast_channel_snapshot_dialplan::priority, and ast_channel_snapshot::softhangup_flags.

Referenced by check_new_cdr_needed().

1189 {
1190  /* If we ignore hangup logic, don't indicate that we're executing anything new */
1191  if (ast_test_flag(&new_snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)
1192  && is_cdr_flag_set(CDR_END_BEFORE_H_EXTEN)) {
1193  return 0;
1194  }
1195 
1196  /* When Party A is originated to an application and the application exits, the stack
1197  * will attempt to clear the application and restore the dummy originate application
1198  * of "AppDialX". Ignore application changes to AppDialX as a result.
1199  */
1200  if (strcmp(new_snapshot->dialplan->appl, old_snapshot->dialplan->appl)
1201  && strncasecmp(new_snapshot->dialplan->appl, "appdial", 7)
1202  && (strcmp(new_snapshot->dialplan->context, old_snapshot->dialplan->context)
1203  || strcmp(new_snapshot->dialplan->exten, old_snapshot->dialplan->exten)
1204  || new_snapshot->dialplan->priority != old_snapshot->dialplan->priority)) {
1205  return 1;
1206  }
1207 
1208  return 0;
1209 }
struct ast_channel_snapshot_dialplan * dialplan
const ast_string_field context
const ast_string_field appl
const ast_string_field exten
struct ast_flags softhangup_flags
static int snapshot_is_dialed ( struct ast_channel_snapshot snapshot)
static

Return whether or not a ast_channel_snapshot is for a channel that was created as the result of a dial operation.

Return values
0the channel was not created as the result of a dial
1the channel was created as the result of a dial

Definition at line 1218 of file cdr.c.

References AST_FLAG_ORIGINATED, AST_FLAG_OUTGOING, and ast_channel_snapshot::flags.

Referenced by cdr_object_create_public_records(), and cdr_object_pick_party_a().

1219 {
1220  return (ast_test_flag(&snapshot->flags, AST_FLAG_OUTGOING)
1221  && !(ast_test_flag(&snapshot->flags, AST_FLAG_ORIGINATED)));
1222 }
struct ast_flags flags
static void start_batch_mode ( void  )
static

Do not hold the batch lock while calling this function

Definition at line 3887 of file cdr.c.

References ast_sched_add_variable(), AST_SCHED_DEL, and cdr_pending_lock.

3888 {
3889  /* Prevent two deletes from happening at the same time */
3890  ast_mutex_lock(&cdr_sched_lock);
3891  /* this is okay since we are not being called from within the scheduler */
3892  AST_SCHED_DEL(sched, cdr_sched);
3893  /* schedule the submission to occur ASAP (1 ms) */
3894  cdr_sched = ast_sched_add_variable(sched, 1, submit_scheduled_batch, NULL, 1);
3895  ast_mutex_unlock(&cdr_sched_lock);
3896 
3897  /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
3898  ast_mutex_lock(&cdr_pending_lock);
3899  ast_cond_signal(&cdr_pending_cond);
3900  ast_mutex_unlock(&cdr_pending_lock);
3901 }
Definition: sched.c:76
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:526
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
static ast_mutex_t cdr_pending_lock
These are used to wake up the CDR thread when there's work to do.
Definition: cdr.c:403

Variable Documentation

struct cdr_object_fn_table bridge_state_fn_table

The virtual table for the Bridged state.

A cdr_object enters this state when it receives notification that the channel has entered a bridge.

A cdr_object from this state can go to:

Definition at line 701 of file cdr.c.

struct cdr_object_fn_table dial_state_fn_table

The virtual table for the Dial state.

A cdr_object that has begun a dial operation. This state is entered when the Party A for a CDR is determined to be dialing out to a Party B or when a CDR is for an originated channel (in which case the Party A information is the originated channel, and there is no Party B).

A cdr_object from this state can go in any of the following states:

Definition at line 646 of file cdr.c.

struct cdr_object_fn_table dialed_pending_state_fn_table

The virtual table for the Dialed Pending state.

A cdr_object that has successfully finished a dial operation, but we don't know what they're going to do yet. It's theoretically possible to dial a party and then have that party not be bridged with the caller; likewise, an origination can complete and the channel go off and execute dialplan. The pending state acts as a bridge between either:

  • Entering a bridge
  • Getting a new CDR for new dialplan execution
  • Switching from being originated to executing dialplan

A cdr_object from this state can go in any of the following states:

Definition at line 679 of file cdr.c.

struct cdr_object_fn_table finalized_state_fn_table

The virtual table for the finalized state.

Once in the finalized state, the CDR is done. No modifications can be made to the CDR.

Definition at line 736 of file cdr.c.

const char* ignore_categories[]
static

Config sections used by existing modules. Do not add to this list.

Definition at line 281 of file cdr.c.

struct aco_file module_file_conf
static
Initial value:
= {
.filename = "cdr.conf",
.types = ACO_TYPES(&general_option, &ignore_option),
}
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
static struct aco_type general_option
The type definition for general options.
Definition: cdr.c:272

The file definition.

Definition at line 306 of file cdr.c.

struct cdr_object_fn_table parked_state_fn_table

The virtual table for the Parked state.

Parking is weird. Unlike typical bridges, it has to be treated somewhat uniquely - a channel in a parking bridge (which is a subclass of a holding bridge) has to be handled as if the channel went into an application. However, when the channel comes out, we need a new CDR - unlike the Single state.

Definition at line 720 of file cdr.c.

struct cdr_object_fn_table single_state_fn_table

The virtual table for the Single state.

A cdr_object starts off in this state. This represents a channel that has no Party B information itself.

A cdr_object from this state can go into any of the following states:

Definition at line 615 of file cdr.c.