Asterisk - The Open Source Telephony Project  18.5.0
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"
Include dependency graph for cdr.c:

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_CONGESTION   "0"
 
#define DEFAULT_ENABLED   "1"
 
#define DEFAULT_END_BEFORE_H_EXTEN   "1"
 
#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. More...
 
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. More...
 
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. More...
 
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. More...
 
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_objects. It should only be used during shutdown, so that we get billing records for everything that we can. More...
 
static void cdr_object_dtor (void *obj)
 cdr_object Destructor More...
 
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. More...
 
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. More...
 
static long cdr_object_get_billsec (struct cdr_object *cdr)
 Compute the billsec for a cdr_object. More...
 
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. More...
 
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)
 
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. More...
 
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. More...
 
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. More...
 
static char * cli_complete_show (struct ast_cli_args *a)
 Complete user input for 'cdr show'. More...
 
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. More...
 
static void destroy_subscriptions (void)
 Destroy the active Stasis subscriptions. More...
 
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. More...
 
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. More...
 
static void module_config_destructor (void *obj)
 Dispose of a module config object. More...
 
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. More...
 
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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. More...
 
static struct ao2_containeractive_cdrs_master
 A container of the active master CDRs indexed by Party A channel uniqueid. More...
 
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. More...
 
static ast_mutex_t cdr_batch_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Lock protecting modifications to the batch queue. More...
 
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. More...
 
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. More...
 
static struct stasis_forwardchannel_subscription
 Our subscription for channels. More...
 
static struct ast_cli_entry cli_commands []
 
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. More...
 
static struct aco_typegeneral_options [] = ACO_TYPES(&general_option)
 
static int global_cdr_sequence = 0
 The global sequence counter used for CDRs. More...
 
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. More...
 
static struct ast_sched_contextsched
 Scheduler items. More...
 
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. More...
 

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

◆ CDR_DEBUG

#define CDR_DEBUG (   fmt,
  ... 
)

◆ cdr_set_debug_mode

#define cdr_set_debug_mode (   mod_cfg)
Value:
do { \
cdr_debug_enabled = ast_test_flag(&(mod_cfg)->general->settings, CDR_DEBUG); \
} while (0)
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210

Definition at line 203 of file cdr.c.

Referenced by ast_cdr_set_config(), handle_cli_debug(), module_config_post_apply(), and process_config().

◆ DEFAULT_BATCH_SAFE_SHUTDOWN

#define DEFAULT_BATCH_SAFE_SHUTDOWN   "1"

Definition at line 201 of file cdr.c.

Referenced by process_config().

◆ DEFAULT_BATCH_SCHEDULER_ONLY

#define DEFAULT_BATCH_SCHEDULER_ONLY   "0"

Definition at line 200 of file cdr.c.

Referenced by process_config().

◆ DEFAULT_BATCH_SIZE

#define DEFAULT_BATCH_SIZE   "100"

Definition at line 196 of file cdr.c.

Referenced by process_config().

◆ DEFAULT_BATCH_TIME

#define DEFAULT_BATCH_TIME   "300"

Definition at line 198 of file cdr.c.

Referenced by process_config().

◆ DEFAULT_BATCHMODE

#define DEFAULT_BATCHMODE   "0"

Definition at line 190 of file cdr.c.

Referenced by process_config().

◆ DEFAULT_CONGESTION

#define DEFAULT_CONGESTION   "0"

Definition at line 192 of file cdr.c.

◆ DEFAULT_ENABLED

#define DEFAULT_ENABLED   "1"

Definition at line 189 of file cdr.c.

Referenced by process_config().

◆ DEFAULT_END_BEFORE_H_EXTEN

#define DEFAULT_END_BEFORE_H_EXTEN   "1"

Definition at line 193 of file cdr.c.

Referenced by process_config().

◆ DEFAULT_INITIATED_SECONDS

#define DEFAULT_INITIATED_SECONDS   "0"

Definition at line 194 of file cdr.c.

Referenced by process_config().

◆ DEFAULT_UNANSWERED

#define DEFAULT_UNANSWERED   "0"

Definition at line 191 of file cdr.c.

Referenced by process_config().

◆ FORMAT_STRING [1/2]

#define FORMAT_STRING   "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"

◆ FORMAT_STRING [2/2]

#define FORMAT_STRING   "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"

◆ MAX_BATCH_SIZE

#define MAX_BATCH_SIZE   1000

Definition at line 197 of file cdr.c.

Referenced by process_config().

◆ MAX_BATCH_TIME

#define MAX_BATCH_TIME   86400

Definition at line 199 of file cdr.c.

Referenced by process_config().

◆ TITLE_STRING [1/2]

#define TITLE_STRING   "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"

◆ TITLE_STRING [2/2]

#define TITLE_STRING   "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"

Enumeration Type Documentation

◆ process_bridge_enter_results

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 391 of file cdr.c.

391  {
392  /*!
393  * The CDR was the only party in the bridge.
394  */
396  /*!
397  * The CDR was able to obtain a Party B from some other party already in the bridge
398  */
400  /*!
401  * The CDR was not able to obtain a Party B
402  */
404  /*!
405  * This CDR can't handle a bridge enter message and a new CDR needs to be created
406  */
408 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4651 of file cdr.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4651 of file cdr.c.

◆ AO2_GLOBAL_OBJ_STATIC()

static AO2_GLOBAL_OBJ_STATIC ( module_configs  )
static

The container for the module configuration.

◆ ast_cdr_alloc()

struct ast_cdr* ast_cdr_alloc ( void  )

Allocate a CDR record.

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

Definition at line 3422 of file cdr.c.

References ast_calloc.

Referenced by ast_cdr_dup().

3423 {
3424  struct ast_cdr *x;
3425 
3426  x = ast_calloc(1, sizeof(*x));
3427  return x;
3428 }
Responsible for call detail data.
Definition: cdr.h:276
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ ast_cdr_backend_suspend()

int ast_cdr_backend_suspend ( const char *  name)

Suspend a CDR backend temporarily.

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

Definition at line 2866 of file cdr.c.

References ast_debug, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cdr_beitem::name, and NULL.

Referenced by load_config(), my_unload_module(), and odbc_load_module().

2867 {
2868  int success = -1;
2869  struct cdr_beitem *i = NULL;
2870 
2872  AST_RWLIST_TRAVERSE(&be_list, i, list) {
2873  if (!strcasecmp(name, i->name)) {
2874  ast_debug(3, "Suspending CDR backend %s\n", i->name);
2875  i->suspended = 1;
2876  success = 0;
2877  }
2878  }
2880 
2881  return success;
2882 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define NULL
Definition: resample.c:96
Registration object for CDR backends.
Definition: cdr.c:321
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char name[20]
Definition: cdr.c:322
static const char name[]
Definition: cdr_mysql.c:74
List of registered backends.
Definition: cdr.c:330

◆ ast_cdr_backend_unsuspend()

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 2884 of file cdr.c.

References ast_debug, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cdr_beitem::name, and NULL.

Referenced by load_config(), my_load_module(), and odbc_load_module().

2885 {
2886  int success = -1;
2887  struct cdr_beitem *i = NULL;
2888 
2890  AST_RWLIST_TRAVERSE(&be_list, i, list) {
2891  if (!strcasecmp(name, i->name)) {
2892  ast_debug(3, "Unsuspending CDR backend %s\n", i->name);
2893  i->suspended = 0;
2894  success = 0;
2895  }
2896  }
2898 
2899  return success;
2900 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define NULL
Definition: resample.c:96
Registration object for CDR backends.
Definition: cdr.c:321
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char name[20]
Definition: cdr.c:322
static const char name[]
Definition: cdr_mysql.c:74
List of registered backends.
Definition: cdr.c:330

◆ ast_cdr_clear_property()

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 3575 of file cdr.c.

References ao2_cleanup, ao2_lock, ao2_unlock, ast_clear_flag, cdr_object_get_by_name(), cdr_object::flags, cdr_object::fn_table, and cdr_object::next.

Referenced by appcdr_callback(), AST_TEST_DEFINE(), and cdr_prop_write_callback().

3576 {
3577  struct cdr_object *cdr;
3578  struct cdr_object *it_cdr;
3579 
3580  cdr = cdr_object_get_by_name(channel_name);
3581  if (!cdr) {
3582  return -1;
3583  }
3584 
3585  ao2_lock(cdr);
3586  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3587  if (it_cdr->fn_table == &finalized_state_fn_table) {
3588  continue;
3589  }
3590  ast_clear_flag(&it_cdr->flags, option);
3591  }
3592  ao2_unlock(cdr);
3593 
3594  ao2_cleanup(cdr);
3595  return 0;
3596 }
struct cdr_object * next
Definition: cdr.c:735
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ast_flags flags
Definition: cdr.c:723
#define ao2_lock(a)
Definition: astobj2.h:718
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3312
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
#define ast_clear_flag(p, flag)
Definition: utils.h:77
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_cdr_disp2str()

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 3430 of file cdr.c.

References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_CONGESTION, AST_CDR_FAILED, AST_CDR_NOANSWER, and AST_CDR_NULL.

Referenced by ast_cdr_format_var(), beanstalk_put(), build_csv_record(), build_radius_record(), cdr_object_finalize(), cdr_read_callback(), execute_cb(), manager_log(), and tds_log().

3431 {
3432  switch (disposition) {
3433  case AST_CDR_NULL:
3434  return "NO ANSWER"; /* by default, for backward compatibility */
3435  case AST_CDR_NOANSWER:
3436  return "NO ANSWER";
3437  case AST_CDR_FAILED:
3438  return "FAILED";
3439  case AST_CDR_BUSY:
3440  return "BUSY";
3441  case AST_CDR_ANSWERED:
3442  return "ANSWERED";
3443  case AST_CDR_CONGESTION:
3444  return "CONGESTION";
3445  }
3446  return "UNKNOWN";
3447 }
enum ast_cdr_disposition disposition
Definition: cdr.c:717

◆ ast_cdr_dup()

struct ast_cdr* ast_cdr_dup ( struct ast_cdr cdr)

Duplicate a public CDR.

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

Definition at line 2998 of file cdr.c.

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

Referenced by custom_log(), load_values_config(), manager_log(), and syslog_log().

2999 {
3000  struct ast_cdr *newcdr;
3001 
3002  if (!cdr) {
3003  return NULL;
3004  }
3005  newcdr = ast_cdr_alloc();
3006  if (!newcdr) {
3007  return NULL;
3008  }
3009 
3010  *newcdr = *cdr;
3012  copy_variables(&newcdr->varshead, &cdr->varshead);
3013  newcdr->next = NULL;
3014 
3015  return newcdr;
3016 }
struct ast_cdr * next
Definition: cdr.h:325
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:3422
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:746
#define NULL
Definition: resample.c:96
struct varshead varshead
Definition: cdr.h:323
Responsible for call detail data.
Definition: cdr.h:276
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680

◆ ast_cdr_engine_term()

void ast_cdr_engine_term ( void  )

Submit any remaining CDRs and prepare for shutdown

Definition at line 4577 of file cdr.c.

References ao2_alloc, ao2_cleanup, ao2_global_obj_ref, ast_debug, ast_test_flag, BATCH_MODE_SAFE_SHUTDOWN, CDR_BATCHMODE, cdr_submit_batch(), NULL, RAII_VAR, stasis_message_create(), and stasis_message_router_publish_sync().

Referenced by can_safely_quit(), and finalize_batch_mode().

4578 {
4579  RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
4580 
4581  /* Since this is called explicitly during process shutdown, we might not have ever
4582  * been initialized. If so, the config object will be NULL.
4583  */
4584  if (!mod_cfg) {
4585  return;
4586  }
4587 
4588  if (cdr_sync_message_type()) {
4589  void *payload;
4590  struct stasis_message *message;
4591 
4592  if (!stasis_router) {
4593  return;
4594  }
4595 
4596  /* Make sure we have the needed items */
4597  payload = ao2_alloc(sizeof(*payload), NULL);
4598  if (!payload) {
4599  return;
4600  }
4601 
4602  ast_debug(1, "CDR Engine termination request received; waiting on messages...\n");
4603 
4604  message = stasis_message_create(cdr_sync_message_type(), payload);
4605  if (message) {
4607  }
4608  ao2_cleanup(message);
4609  ao2_cleanup(payload);
4610  }
4611 
4612  if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4613  cdr_submit_batch(ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SAFE_SHUTDOWN));
4614  }
4615 }
static struct stasis_message_router * stasis_router
Message router for stasis messages regarding channel state.
Definition: cdr.c:371
#define ast_test_flag(p, flag)
Definition: utils.h:63
void stasis_message_router_publish_sync(struct stasis_message_router *router, struct stasis_message *message)
Publish a message to a message router&#39;s subscription synchronously.
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
static void cdr_submit_batch(int shutdown)
Definition: cdr.c:3766
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
The configuration settings for this module.
Definition: cdr.c:222
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_cdr_fork()

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 3637 of file cdr.c.

References cdr_object::answer, ao2_cleanup, ao2_ref, cdr_object::appl, AST_CDR_FLAG_FINALIZE, AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_RESET, AST_CDR_FLAG_SET_ANSWER, AST_CDR_LOCK_APP, ast_clear_flag, ast_debug, AST_STATE_UP, ast_string_field_set, ast_test_flag, ast_tvnow(), ast_channel_snapshot::base, cdr_object::bridge, cdr_all_relink(), cdr_object_create_and_append(), cdr_object_finalize(), cdr_object_get_by_name(), cdr_object_transition_state(), context, cdr_object::context, copy_variables(), cdr_object::data, exten, cdr_object::exten, cdr_object_snapshot::flags, cdr_object::flags, cdr_object::fn_table, free_variables(), cdr_object::last, cdr_object::lastevent, lock, ast_channel_snapshot_base::name, 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.

Referenced by AST_TEST_DEFINE(), and forkcdr_callback().

3638 {
3639  RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
3640  struct cdr_object *new_cdr;
3641  struct cdr_object *it_cdr;
3642  struct cdr_object *cdr_obj;
3643 
3644  if (!cdr) {
3645  return -1;
3646  }
3647 
3648  {
3649  SCOPED_AO2LOCK(lock, cdr);
3650  struct timeval now = ast_tvnow();
3651 
3652  cdr_obj = cdr->last;
3653  if (cdr_obj->fn_table == &finalized_state_fn_table) {
3654  /* If the last CDR in the chain is finalized, don't allow a fork -
3655  * things are already dying at this point
3656  */
3657  return -1;
3658  }
3659 
3660  /* Copy over the basic CDR information. The Party A information is
3661  * copied over automatically as part of the append
3662  */
3663  ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->base->name);
3664  new_cdr = cdr_object_create_and_append(cdr, &now);
3665  if (!new_cdr) {
3666  return -1;
3667  }
3668  new_cdr->fn_table = cdr_obj->fn_table;
3669  ast_string_field_set(new_cdr, bridge, cdr->bridge);
3670  ast_string_field_set(new_cdr, appl, cdr->appl);
3671  ast_string_field_set(new_cdr, data, cdr->data);
3672  ast_string_field_set(new_cdr, context, cdr->context);
3673  ast_string_field_set(new_cdr, exten, cdr->exten);
3674  new_cdr->flags = cdr->flags;
3675  /* Explicitly clear the AST_CDR_LOCK_APP flag - we want
3676  * the application to be changed on the new CDR if the
3677  * dialplan demands it
3678  */
3680 
3681  /* If there's a Party B, copy it over as well */
3682  if (cdr_obj->party_b.snapshot) {
3683  new_cdr->party_b.snapshot = cdr_obj->party_b.snapshot;
3684  ao2_ref(new_cdr->party_b.snapshot, +1);
3685  cdr_all_relink(new_cdr);
3686  strcpy(new_cdr->party_b.userfield, cdr_obj->party_b.userfield);
3687  new_cdr->party_b.flags = cdr_obj->party_b.flags;
3688  if (ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3689  copy_variables(&new_cdr->party_b.variables, &cdr_obj->party_b.variables);
3690  }
3691  }
3692  new_cdr->start = cdr_obj->start;
3693  new_cdr->answer = cdr_obj->answer;
3694  new_cdr->lastevent = ast_tvnow();
3695 
3696  /* Modify the times based on the flags passed in */
3698  && new_cdr->party_a.snapshot->state == AST_STATE_UP) {
3699  new_cdr->answer = ast_tvnow();
3700  }
3701  if (ast_test_flag(options, AST_CDR_FLAG_RESET)) {
3702  new_cdr->answer = ast_tvnow();
3703  new_cdr->start = ast_tvnow();
3704  }
3705 
3706  /* Create and append, by default, copies over the variables */
3707  if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
3708  free_variables(&new_cdr->party_a.variables);
3709  }
3710 
3711  /* Finalize any current CDRs */
3712  if (ast_test_flag(options, AST_CDR_FLAG_FINALIZE)) {
3713  for (it_cdr = cdr; it_cdr != new_cdr; it_cdr = it_cdr->next) {
3714  if (it_cdr->fn_table == &finalized_state_fn_table) {
3715  continue;
3716  }
3717  /* Force finalization on the CDR. This will bypass any checks for
3718  * end before 'h' extension.
3719  */
3720  cdr_object_finalize(it_cdr);
3722  }
3723  }
3724  }
3725 
3726  return 0;
3727 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
struct varshead variables
Definition: cdr.c:708
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
unsigned int flags
Definition: utils.h:200
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct timeval answer
Definition: cdr.c:719
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
struct timeval start
Definition: cdr.c:718
unsigned int flags
Definition: cdr.c:707
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:746
struct cdr_object_snapshot party_a
Definition: cdr.c:713
const ast_string_field appl
Definition: cdr.c:734
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:706
struct ast_flags flags
Definition: cdr.c:723
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3312
static void free_variables(struct varshead *headp)
Delete all variables from a variable list.
Definition: cdr.c:777
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct cdr_object * last
Definition: cdr.c:736
const ast_string_field data
Definition: cdr.c:734
struct timeval lastevent
Definition: cdr.c:721
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
enum ast_channel_state state
#define ast_clear_flag(p, flag)
Definition: utils.h:77
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static struct cdr_object * cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
Create a new cdr_object and append it to an existing chain.
Definition: cdr.c:1075
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
const ast_string_field bridge
Definition: cdr.c:734
static void cdr_all_relink(struct cdr_object *cdr)
Definition: cdr.c:949
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ ast_cdr_format_var()

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 extraced, provide epoch seconds. Otherwise format as a date/time stamp

Definition at line 3050 of file cdr.c.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_disp2str(), ast_channel_amaflags2string(), ast_copy_string(), ast_strlen_zero, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_cdr::billsec, cdr_format_var_internal(), cdr_get_tv(), ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::linkedid, NULL, ast_cdr::peeraccount, ast_cdr::sequence, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.

Referenced by cdr_handler(), cdr_read_callback(), cdr_retrieve_time(), mysql_log(), odbc_log(), and pgsql_log().

3051 {
3052  const char *fmt = "%Y-%m-%d %T";
3053  const char *varbuf;
3054 
3055  if (!cdr) {
3056  return;
3057  }
3058 
3059  *ret = NULL;
3060 
3061  if (!strcasecmp(name, "clid")) {
3062  ast_copy_string(workspace, cdr->clid, workspacelen);
3063  } else if (!strcasecmp(name, "src")) {
3064  ast_copy_string(workspace, cdr->src, workspacelen);
3065  } else if (!strcasecmp(name, "dst")) {
3066  ast_copy_string(workspace, cdr->dst, workspacelen);
3067  } else if (!strcasecmp(name, "dcontext")) {
3068  ast_copy_string(workspace, cdr->dcontext, workspacelen);
3069  } else if (!strcasecmp(name, "channel")) {
3070  ast_copy_string(workspace, cdr->channel, workspacelen);
3071  } else if (!strcasecmp(name, "dstchannel")) {
3072  ast_copy_string(workspace, cdr->dstchannel, workspacelen);
3073  } else if (!strcasecmp(name, "lastapp")) {
3074  ast_copy_string(workspace, cdr->lastapp, workspacelen);
3075  } else if (!strcasecmp(name, "lastdata")) {
3076  ast_copy_string(workspace, cdr->lastdata, workspacelen);
3077  } else if (!strcasecmp(name, "start")) {
3078  cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
3079  } else if (!strcasecmp(name, "answer")) {
3080  cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
3081  } else if (!strcasecmp(name, "end")) {
3082  cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
3083  } else if (!strcasecmp(name, "duration")) {
3084  snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
3085  } else if (!strcasecmp(name, "billsec")) {
3086  snprintf(workspace, workspacelen, "%ld", (cdr->billsec || !ast_tvzero(cdr->end) || ast_tvzero(cdr->answer)) ? cdr->billsec : (long)ast_tvdiff_ms(ast_tvnow(), cdr->answer) / 1000);
3087  } else if (!strcasecmp(name, "disposition")) {
3088  if (raw) {
3089  snprintf(workspace, workspacelen, "%ld", cdr->disposition);
3090  } else {
3091  ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
3092  }
3093  } else if (!strcasecmp(name, "amaflags")) {
3094  if (raw) {
3095  snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
3096  } else {
3097  ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
3098  }
3099  } else if (!strcasecmp(name, "accountcode")) {
3100  ast_copy_string(workspace, cdr->accountcode, workspacelen);
3101  } else if (!strcasecmp(name, "peeraccount")) {
3102  ast_copy_string(workspace, cdr->peeraccount, workspacelen);
3103  } else if (!strcasecmp(name, "uniqueid")) {
3104  ast_copy_string(workspace, cdr->uniqueid, workspacelen);
3105  } else if (!strcasecmp(name, "linkedid")) {
3106  ast_copy_string(workspace, cdr->linkedid, workspacelen);
3107  } else if (!strcasecmp(name, "userfield")) {
3108  ast_copy_string(workspace, cdr->userfield, workspacelen);
3109  } else if (!strcasecmp(name, "sequence")) {
3110  snprintf(workspace, workspacelen, "%d", cdr->sequence);
3111  } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
3112  ast_copy_string(workspace, varbuf, workspacelen);
3113  } else {
3114  workspace[0] = '\0';
3115  }
3116 
3117  if (!ast_strlen_zero(workspace)) {
3118  *ret = workspace;
3119  }
3120 }
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:308
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:288
long int billsec
Definition: cdr.h:302
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:284
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
int sequence
Definition: cdr.h:320
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
Definition: channel.c:4418
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:292
long int amaflags
Definition: cdr.h:306
char linkedid[AST_MAX_UNIQUEID]
Definition: cdr.h:316
char uniqueid[AST_MAX_UNIQUEID]
Definition: cdr.h:314
static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
Definition: cdr.c:3035
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:282
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:286
static const char * cdr_format_var_internal(struct ast_cdr *cdr, const char *name)
Definition: cdr.c:3018
struct timeval answer
Definition: cdr.h:296
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:290
struct timeval start
Definition: cdr.h:294
static const char name[]
Definition: cdr_mysql.c:74
long int duration
Definition: cdr.h:300
char src[AST_MAX_EXTENSION]
Definition: cdr.h:280
char peeraccount[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:310
struct timeval end
Definition: cdr.h:298
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
long int disposition
Definition: cdr.h:304
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:278
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:318
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3430

◆ ast_cdr_free()

void ast_cdr_free ( struct ast_cdr cdr)

Free a CDR record.

Parameters
cdrast_cdr structure to free Returns nothing

Definition at line 3411 of file cdr.c.

References ast_free, free_variables(), ast_cdr::next, and ast_cdr::varshead.

Referenced by ast_channel_destructor(), ast_dummy_channel_destructor(), cdr_detach(), clear_mock_cdr_backend(), and do_batch_backend_process().

3412 {
3413  while (cdr) {
3414  struct ast_cdr *next = cdr->next;
3415 
3416  free_variables(&cdr->varshead);
3417  ast_free(cdr);
3418  cdr = next;
3419  }
3420 }
struct ast_cdr * next
Definition: cdr.h:325
struct varshead varshead
Definition: cdr.h:323
static void free_variables(struct varshead *headp)
Delete all variables from a variable list.
Definition: cdr.c:777
Responsible for call detail data.
Definition: cdr.h:276
#define ast_free(a)
Definition: astmm.h:182

◆ ast_cdr_generic_unregister()

static int ast_cdr_generic_unregister ( struct be_list generic_list,
const char *  name 
)
static

Definition at line 2953 of file cdr.c.

References ao2_container_count(), ast_free, ast_log, AST_LOG_WARNING, AST_RWLIST_REMOVE, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, match(), cdr_beitem::name, and NULL.

Referenced by ast_cdr_modifier_unregister(), and ast_cdr_unregister().

2954 {
2955  struct cdr_beitem *match = NULL;
2956  int active_count;
2957 
2958  AST_RWLIST_WRLOCK(generic_list);
2959  AST_RWLIST_TRAVERSE(generic_list, match, list) {
2960  if (!strcasecmp(name, match->name)) {
2961  break;
2962  }
2963  }
2964 
2965  if (!match) {
2966  AST_RWLIST_UNLOCK(generic_list);
2967  return 0;
2968  }
2969 
2970  active_count = ao2_container_count(active_cdrs_master);
2971 
2972  if (!match->suspended && active_count != 0) {
2973  AST_RWLIST_UNLOCK(generic_list);
2974  ast_log(AST_LOG_WARNING, "Unable to unregister CDR backend %s; %d CDRs are still active\n",
2975  name, active_count);
2976  return -1;
2977  }
2978 
2979  AST_RWLIST_REMOVE(generic_list, match, list);
2980  AST_RWLIST_UNLOCK(generic_list);
2981 
2982  ast_verb(2, "Unregistered '%s' CDR backend\n", name);
2983  ast_free(match);
2984 
2985  return 0;
2986 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_LOG_WARNING
Definition: logger.h:279
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
Registration object for CDR backends.
Definition: cdr.c:321
#define ast_log
Definition: astobj2.c:42
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char name[20]
Definition: cdr.c:322
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:884

◆ ast_cdr_get_config()

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
Thecurrent CDR configuration

Definition at line 2826 of file cdr.c.

References ao2_bump, ao2_cleanup, ao2_global_obj_ref, module_config::general, and NULL.

Referenced by test_cdr_init_cb().

2827 {
2828  struct ast_cdr_config *general;
2829  struct module_config *mod_cfg;
2830 
2831  mod_cfg = ao2_global_obj_ref(module_configs);
2832  if (!mod_cfg) {
2833  return NULL;
2834  }
2835  general = ao2_bump(mod_cfg->general);
2836  ao2_cleanup(mod_cfg);
2837  return general;
2838 }
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
The configuration settings for this module.
Definition: cdr.c:222
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
The global options available for CDRs.
Definition: cdr.h:264
struct ast_cdr_config * general
Definition: cdr.c:223

◆ ast_cdr_getvar()

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 3324 of file cdr.c.

References ao2_cleanup, ao2_lock, ao2_unlock, ast_log, AST_LOG_ERROR, ast_strlen_zero, cdr_object_format_property(), cdr_object_format_var_internal(), cdr_object_get_by_name(), and cdr_object::last.

Referenced by AST_TEST_DEFINE(), cdr_read_callback(), and cdr_retrieve_time().

3325 {
3326  struct cdr_object *cdr;
3327  struct cdr_object *cdr_obj;
3328 
3329  if (ast_strlen_zero(name)) {
3330  return 1;
3331  }
3332 
3333  cdr = cdr_object_get_by_name(channel_name);
3334  if (!cdr) {
3335  ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3336  return 1;
3337  }
3338 
3339  ao2_lock(cdr);
3340 
3341  cdr_obj = cdr->last;
3342  if (cdr_object_format_property(cdr_obj, name, value, length)) {
3343  /* Property failed; attempt variable */
3344  cdr_object_format_var_internal(cdr_obj, name, value, length);
3345  }
3346 
3347  ao2_unlock(cdr);
3348 
3349  ao2_cleanup(cdr);
3350  return 0;
3351 }
static void cdr_object_format_var_internal(struct cdr_object *cdr, const char *name, char *value, size_t length)
Format a variable on a cdr_object.
Definition: cdr.c:3226
#define ao2_unlock(a)
Definition: astobj2.h:730
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
Format one of the standard properties on a cdr_object.
Definition: cdr.c:3243
#define ao2_lock(a)
Definition: astobj2.h:718
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3312
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct cdr_object * last
Definition: cdr.c:736
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_cdr_is_enabled()

int ast_cdr_is_enabled ( void  )

Return TRUE if CDR subsystem is enabled.

Definition at line 2861 of file cdr.c.

References CDR_ENABLED, and is_cdr_flag_set().

Referenced by action_coresettings(), and handle_show_settings().

2862 {
2863  return is_cdr_flag_set(CDR_ENABLED);
2864 }
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127

◆ ast_cdr_message_router()

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
thestasis_message_router otherwise

Definition at line 4291 of file cdr.c.

References ao2_bump, NULL, and stasis_router.

Referenced by cdr_prop_write(), cdr_read(), cdr_write(), forkcdr_exec(), load_module(), publish_app_cdr_message(), and unload_module().

4292 {
4293  if (!stasis_router) {
4294  return NULL;
4295  }
4296 
4298  return stasis_router;
4299 }
static struct stasis_message_router * stasis_router
Message router for stasis messages regarding channel state.
Definition: cdr.c:371
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491

◆ ast_cdr_modifier_register()

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 2948 of file cdr.c.

References cdr_generic_register().

2949 {
2950  return cdr_generic_register((struct be_list *)&mo_list, name, desc, be);
2951 }
static const char desc[]
Definition: cdr_mysql.c:73
char * be
Definition: eagi_proxy.c:73
static int cdr_generic_register(struct be_list *generic_list, const char *name, const char *desc, ast_cdrbe be)
Definition: cdr.c:2902
List of registered modifiers.
Definition: cdr.c:333
static const char name[]
Definition: cdr_mysql.c:74
List of registered backends.
Definition: cdr.c:330

◆ ast_cdr_modifier_unregister()

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 2993 of file cdr.c.

References ast_cdr_generic_unregister().

2994 {
2995  return ast_cdr_generic_unregister((struct be_list *)&mo_list, name);
2996 }
static int ast_cdr_generic_unregister(struct be_list *generic_list, const char *name)
Definition: cdr.c:2953
List of registered modifiers.
Definition: cdr.c:333
static const char name[]
Definition: cdr_mysql.c:74
List of registered backends.
Definition: cdr.c:330

◆ ast_cdr_register()

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 2943 of file cdr.c.

References cdr_generic_register().

Referenced by load_module(), load_values_config(), my_load_module(), odbc_load_module(), and unload_module().

2944 {
2945  return cdr_generic_register(&be_list, name, desc, be);
2946 }
static const char desc[]
Definition: cdr_mysql.c:73
char * be
Definition: eagi_proxy.c:73
static int cdr_generic_register(struct be_list *generic_list, const char *name, const char *desc, ast_cdrbe be)
Definition: cdr.c:2902
static const char name[]
Definition: cdr_mysql.c:74
List of registered backends.
Definition: cdr.c:330

◆ ast_cdr_reset()

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 3598 of file cdr.c.

References cdr_object::answer, ao2_cleanup, ao2_lock, ao2_unlock, AST_LIST_REMOVE_HEAD, ast_tvnow(), ast_var_delete(), cdr_object_check_party_a_answer(), cdr_object_get_by_name(), 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 appcdr_callback(), and dial_exec_full().

3599 {
3600  struct cdr_object *cdr;
3601  struct ast_var_t *vardata;
3602  struct cdr_object *it_cdr;
3603 
3604  cdr = cdr_object_get_by_name(channel_name);
3605  if (!cdr) {
3606  return -1;
3607  }
3608 
3609  ao2_lock(cdr);
3610  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3611  /* clear variables */
3612  if (!keep_variables) {
3613  while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
3614  ast_var_delete(vardata);
3615  }
3616  if (cdr->party_b.snapshot) {
3617  while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
3618  ast_var_delete(vardata);
3619  }
3620  }
3621  }
3622 
3623  /* Reset to initial state */
3624  memset(&it_cdr->start, 0, sizeof(it_cdr->start));
3625  memset(&it_cdr->end, 0, sizeof(it_cdr->end));
3626  memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
3627  it_cdr->start = ast_tvnow();
3628  it_cdr->lastevent = it_cdr->start;
3630  }
3631  ao2_unlock(cdr);
3632 
3633  ao2_cleanup(cdr);
3634  return 0;
3635 }
struct varshead variables
Definition: cdr.c:708
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct timeval answer
Definition: cdr.c:719
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_unlock(a)
Definition: astobj2.h:730
struct timeval start
Definition: cdr.c:718
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define ao2_lock(a)
Definition: astobj2.h:718
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3312
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
An in-memory representation of an active CDR.
Definition: cdr.c:712
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
struct timeval lastevent
Definition: cdr.c:721
struct timeval end
Definition: cdr.c:720
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static void cdr_object_check_party_a_answer(struct cdr_object *cdr)
Check to see if a CDR needs to be answered based on its Party A. Note that this is safe to call as mu...
Definition: cdr.c:1494

◆ ast_cdr_serialize_variables()

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
Return values
thetotal number of serialized variables

Definition at line 3353 of file cdr.c.

References ao2_cleanup, ao2_lock, ao2_unlock, ast_assert, AST_LIST_TRAVERSE, ast_log, AST_LOG_ERROR, ast_str_append(), ast_str_reset(), ast_strlen_zero, ast_var_name(), ast_var_value(), CDR_ENABLED, cdr_object_format_property(), cdr_object_get_by_name(), ast_var_t::entries, is_cdr_flag_set(), LOG_ERROR, cdr_object::next, cdr_object::party_a, S_OR, total, var, and cdr_object_snapshot::variables.

Referenced by handle_showchan().

3354 {
3355  struct cdr_object *cdr;
3356  struct cdr_object *it_cdr;
3357  struct ast_var_t *variable;
3358  const char *var;
3359  char workspace[256];
3360  int total = 0, x = 0, i;
3361 
3362  cdr = cdr_object_get_by_name(channel_name);
3363  if (!cdr) {
3365  ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3366  }
3367  return 0;
3368  }
3369 
3370  ast_str_reset(*buf);
3371 
3372  ao2_lock(cdr);
3373  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3374  if (++x > 1) {
3375  ast_str_append(buf, 0, "\n");
3376  }
3377 
3378  AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
3379  if (!(var = ast_var_name(variable))) {
3380  continue;
3381  }
3382 
3383  if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
3384  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3385  break;
3386  }
3387 
3388  total++;
3389  }
3390 
3391  for (i = 0; cdr_readonly_vars[i]; i++) {
3392  if (cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace))) {
3393  /* Unhandled read-only CDR variable. */
3394  ast_assert(0);
3395  continue;
3396  }
3397 
3398  if (!ast_strlen_zero(workspace)
3399  && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
3400  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
3401  break;
3402  }
3403  total++;
3404  }
3405  }
3406  ao2_unlock(cdr);
3407  ao2_cleanup(cdr);
3408  return total;
3409 }
struct varshead variables
Definition: cdr.c:708
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
struct cdr_object * next
Definition: cdr.c:735
#define var
Definition: ast_expr2f.c:614
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *name, char *value, size_t length)
Format one of the standard properties on a cdr_object.
Definition: cdr.c:3243
#define ao2_lock(a)
Definition: astobj2.h:718
static const char *const cdr_readonly_vars[]
Definition: cdr.c:3154
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3312
An in-memory representation of an active CDR.
Definition: cdr.c:712
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_var_t::@249 entries
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static int total
Definition: res_adsi.c:968

◆ ast_cdr_set_config()

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 2840 of file cdr.c.

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

Referenced by test_cdr_cleanup_cb().

2841 {
2842  struct module_config *mod_cfg;
2843 
2844  if (!config) {
2845  return;
2846  }
2847 
2848  mod_cfg = ao2_global_obj_ref(module_configs);
2849  if (!mod_cfg) {
2850  return;
2851  }
2852 
2853  ao2_replace(mod_cfg->general, config);
2854 
2855  cdr_set_debug_mode(mod_cfg);
2857 
2858  ao2_cleanup(mod_cfg);
2859 }
#define cdr_set_debug_mode(mod_cfg)
Definition: cdr.c:203
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
The configuration settings for this module.
Definition: cdr.c:222
#define ao2_replace(dst, src)
Definition: astobj2.h:517
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_cdr_config * general
Definition: cdr.c:223
static int cdr_toggle_runtime_options(void)
Checks if CDRs are enabled and enables/disables the necessary options.
Definition: cdr.c:4488

◆ ast_cdr_set_property()

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 enum 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 3548 of file cdr.c.

References ao2_cleanup, ao2_lock, ao2_unlock, ast_set_flag, cdr_object_get_by_name(), cdr_object::flags, cdr_object::fn_table, cdr_object::next, and cdr_object::party_a.

Referenced by appcdr_callback(), AST_TEST_DEFINE(), and cdr_prop_write_callback().

3549 {
3550  struct cdr_object *cdr;
3551  struct cdr_object *it_cdr;
3552 
3553  cdr = cdr_object_get_by_name(channel_name);
3554  if (!cdr) {
3555  return -1;
3556  }
3557 
3558  ao2_lock(cdr);
3559  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3560  if (it_cdr->fn_table == &finalized_state_fn_table) {
3561  continue;
3562  }
3563  /* Note: in general, set the flags on both the CDR record as well as the
3564  * Party A. Sometimes all we have is the Party A to look at.
3565  */
3566  ast_set_flag(&it_cdr->flags, option);
3567  ast_set_flag(&it_cdr->party_a, option);
3568  }
3569  ao2_unlock(cdr);
3570 
3571  ao2_cleanup(cdr);
3572  return 0;
3573 }
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct cdr_object * next
Definition: cdr.c:735
#define ao2_unlock(a)
Definition: astobj2.h:730
struct cdr_object_snapshot party_a
Definition: cdr.c:713
struct ast_flags flags
Definition: cdr.c:723
#define ao2_lock(a)
Definition: astobj2.h:718
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3312
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_cdr_setuserfield()

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 3477 of file cdr.c.

References ao2_callback_data, ao2_cleanup, ao2_lock, ao2_unlock, ast_copy_string(), cdr_object_get_by_name(), cdr_object_update_party_b_userfield_cb(), party_b_userfield_update::channel_name, cdr_object::fn_table, cdr_object::next, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_SEARCH_KEY, cdr_object::party_a, cdr_object_snapshot::userfield, and party_b_userfield_update::userfield.

Referenced by AST_TEST_DEFINE(), cdr_write_callback(), handle_request_info(), and start_monitor_exec().

3478 {
3479  struct cdr_object *cdr;
3480  struct party_b_userfield_update party_b_info = {
3482  .userfield = userfield,
3483  };
3484  struct cdr_object *it_cdr;
3485 
3486  /* Handle Party A */
3487  cdr = cdr_object_get_by_name(channel_name);
3488  if (cdr) {
3489  ao2_lock(cdr);
3490  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3491  if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3492  continue;
3493  }
3494  ast_copy_string(it_cdr->party_a.userfield, userfield,
3495  sizeof(it_cdr->party_a.userfield));
3496  }
3497  ao2_unlock(cdr);
3498  }
3499 
3500  /* Handle Party B */
3503  &party_b_info);
3504 
3505  ao2_cleanup(cdr);
3506 }
static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, void *data, int flags)
Callback used to update the userfield on Party B on all CDRs.
Definition: cdr.c:3455
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct cdr_object * next
Definition: cdr.c:735
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct cdr_object_snapshot party_a
Definition: cdr.c:713
const char * userfield
Definition: cdr.c:3451
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:706
#define ao2_lock(a)
Definition: astobj2.h:718
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3312
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
const char * channel_name
Definition: cdr.c:3450
An in-memory representation of an active CDR.
Definition: cdr.c:712
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static struct ao2_container * active_cdrs_all
A container of all active CDRs with a Party B indexed by Party B channel name.
Definition: cdr.c:368

◆ ast_cdr_setvar()

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 3178 of file cdr.c.

References ao2_callback, ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_log, AST_LOG_ERROR, ast_strdupa, ast_channel_snapshot::base, cdr_object_select_all_by_name_cb(), cdr_object::fn_table, LOG_ERROR, ast_channel_snapshot_base::name, cdr_object::next, NULL, OBJ_MULTIPLE, cdr_object::party_a, cdr_object::party_b, set_variable(), cdr_object_snapshot::snapshot, and cdr_object_snapshot::variables.

Referenced by AST_TEST_DEFINE(), and cdr_write_callback().

3179 {
3180  struct cdr_object *cdr;
3181  struct cdr_object *it_cdr;
3182  struct ao2_iterator *it_cdrs;
3183  char *arg = ast_strdupa(channel_name);
3184  int x;
3185 
3186  for (x = 0; cdr_readonly_vars[x]; x++) {
3187  if (!strcasecmp(name, cdr_readonly_vars[x])) {
3188  ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
3189  return -1;
3190  }
3191  }
3192 
3194  if (!it_cdrs) {
3195  ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
3196  return -1;
3197  }
3198 
3199  for (; (cdr = ao2_iterator_next(it_cdrs)); ao2_unlock(cdr), ao2_cleanup(cdr)) {
3200  ao2_lock(cdr);
3201  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
3202  struct varshead *headp = NULL;
3203 
3204  if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
3205  continue;
3206  }
3207  if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->base->name)) {
3208  headp = &it_cdr->party_a.variables;
3209  } else if (it_cdr->party_b.snapshot
3210  && !strcasecmp(channel_name, it_cdr->party_b.snapshot->base->name)) {
3211  headp = &it_cdr->party_b.variables;
3212  }
3213  if (headp) {
3214  set_variable(headp, name, value);
3215  }
3216  }
3217  }
3218  ao2_iterator_destroy(it_cdrs);
3219 
3220  return 0;
3221 }
struct ast_channel_snapshot_base * base
struct varshead variables
Definition: cdr.c:708
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
static void set_variable(struct varshead *headp, const char *name, const char *value)
Definition: cdr.c:1262
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
static int cdr_object_select_all_by_name_cb(void *obj, void *arg, int flags)
Definition: cdr.c:3126
int value
Definition: syslog.c:37
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static const char *const cdr_readonly_vars[]
Definition: cdr.c:3154
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
#define LOG_ERROR
Definition: logger.h:285
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static const char name[]
Definition: cdr_mysql.c:74
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const ast_string_field name

◆ ast_cdr_unregister()

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 2988 of file cdr.c.

References ast_cdr_generic_unregister().

Referenced by load_module(), load_values_config(), my_unload_module(), reload(), tds_unload_module(), and unload_module().

2989 {
2991 }
static int ast_cdr_generic_unregister(struct be_list *generic_list, const char *name)
Definition: cdr.c:2953
static const char name[]
Definition: cdr_mysql.c:74
List of registered backends.
Definition: cdr.c:330

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 4651 of file cdr.c.

◆ base_process_bridge_enter()

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

Definition at line 1611 of file cdr.c.

References BRIDGE_ENTER_NEED_CDR.

1612 {
1613  /* Base process bridge enter simply indicates that we can't handle it */
1614  return BRIDGE_ENTER_NEED_CDR;
1615 }

◆ base_process_bridge_leave()

static int base_process_bridge_leave ( struct cdr_object cdr,
struct ast_bridge_snapshot bridge,
struct ast_channel_snapshot channel 
)
static

Definition at line 1601 of file cdr.c.

1602 {
1603  return 0;
1604 }

◆ base_process_dial_end()

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

Definition at line 1606 of file cdr.c.

1607 {
1608  return 0;
1609 }

◆ base_process_parked_channel()

static int base_process_parked_channel ( struct cdr_object cdr,
struct ast_parked_call_payload parking_info 
)
static

Definition at line 1617 of file cdr.c.

References ast_assert, AST_CDR_LOCK_APP, ast_set_flag, ast_string_field_set, ast_channel_snapshot::base, cdr_object::flags, cdr_object::fn_table, ast_channel_snapshot_base::name, ast_parked_call_payload::parkee, ast_parked_call_payload::parkinglot, ast_parked_call_payload::parkingspace, cdr_object::party_a, cdr_object_fn_table::process_party_a, and cdr_object_snapshot::snapshot.

1618 {
1619  char park_info[128];
1620 
1621  ast_assert(!strcasecmp(parking_info->parkee->base->name, cdr->party_a.snapshot->base->name));
1622 
1623  /* Update Party A information regardless */
1624  cdr->fn_table->process_party_a(cdr, parking_info->parkee);
1625 
1626  /* Fake out where we're parked */
1627  ast_string_field_set(cdr, appl, "Park");
1628  snprintf(park_info, sizeof(park_info), "%s:%u", parking_info->parkinglot, parking_info->parkingspace);
1629  ast_string_field_set(cdr, data, park_info);
1630 
1631  /* Prevent any further changes to the App/Data fields for this record */
1633 
1634  return 0;
1635 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
#define ast_set_flag(p, flag)
Definition: utils.h:70
int(*const process_party_a)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party A update for the cdr_object.
Definition: cdr.c:437
#define ast_assert(a)
Definition: utils.h:695
struct cdr_object_snapshot party_a
Definition: cdr.c:713
struct ast_flags flags
Definition: cdr.c:723
struct ast_channel_snapshot * parkee
Definition: parking.h:60
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
unsigned int parkingspace
Definition: parking.h:65
const ast_string_field parkinglot
Definition: parking.h:69
const ast_string_field name
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ base_process_party_a()

static int base_process_party_a ( struct cdr_object cdr,
struct ast_channel_snapshot snapshot 
)
static

Definition at line 1540 of file cdr.c.

References ast_channel_snapshot_dialplan::appl, cdr_object::appl, ast_assert, AST_CDR_LOCK_APP, AST_FLAG_SUBROUTINE_EXEC, ast_set_flag, AST_SOFTHANGUP_HANGUP_EXEC, ast_string_field_set, ast_strlen_zero, ast_test_flag, ast_channel_snapshot::base, CDR_END_BEFORE_H_EXTEN, cdr_object_check_party_a_answer(), cdr_object_check_party_a_hangup(), cdr_object_finalize(), cdr_object_swap_snapshot(), ast_channel_snapshot_dialplan::context, context, cdr_object::context, ast_channel_snapshot_dialplan::data, cdr_object::data, ast_channel_snapshot::dialplan, ast_channel_snapshot_dialplan::exten, exten, cdr_object::exten, ast_channel_snapshot::flags, cdr_object::flags, is_cdr_flag_set(), ast_channel_snapshot_peer::linkedid, ast_cdr::linkedid, cdr_object::linkedid, ast_channel_snapshot_base::name, cdr_object::party_a, ast_channel_snapshot::peer, cdr_object_snapshot::snapshot, and ast_channel_snapshot::softhangup_flags.

Referenced by dialed_pending_state_process_party_a(), and single_state_process_dial_begin().

1541 {
1542  ast_assert(strcasecmp(snapshot->base->name, cdr->party_a.snapshot->base->name) == 0);
1543 
1544  /* Finalize the CDR if we're in hangup logic and we're set to do so */
1547  cdr_object_finalize(cdr);
1548  return 0;
1549  }
1550 
1551  /*
1552  * Only record the context and extension if we aren't in a subroutine, or if
1553  * we are executing hangup logic.
1554  */
1555  if (!ast_test_flag(&snapshot->flags, AST_FLAG_SUBROUTINE_EXEC)
1557  if (strcmp(cdr->context, snapshot->dialplan->context)) {
1558  ast_string_field_set(cdr, context, snapshot->dialplan->context);
1559  }
1560  if (strcmp(cdr->exten, snapshot->dialplan->exten)) {
1561  ast_string_field_set(cdr, exten, snapshot->dialplan->exten);
1562  }
1563  }
1564 
1565  cdr_object_swap_snapshot(&cdr->party_a, snapshot);
1566 
1567  /* When Party A is originated to an application and the application exits, the stack
1568  * will attempt to clear the application and restore the dummy originate application
1569  * of "AppDialX". Prevent that, and any other application changes we might not want
1570  * here.
1571  */
1572  if (!ast_test_flag(&cdr->flags, AST_CDR_LOCK_APP)
1573  && !ast_strlen_zero(snapshot->dialplan->appl)
1574  && (strncasecmp(snapshot->dialplan->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))) {
1575  if (strcmp(cdr->appl, snapshot->dialplan->appl)) {
1576  ast_string_field_set(cdr, appl, snapshot->dialplan->appl);
1577  }
1578  if (strcmp(cdr->data, snapshot->dialplan->data)) {
1579  ast_string_field_set(cdr, data, snapshot->dialplan->data);
1580  }
1581 
1582  /* Dial (app_dial) is a special case. Because pre-dial handlers, which
1583  * execute before the dial begins, will alter the application/data to
1584  * something people typically don't want to see, if we see a channel enter
1585  * into Dial here, we set the appl/data accordingly and lock it.
1586  */
1587  if (!strcmp(snapshot->dialplan->appl, "Dial")) {
1589  }
1590  }
1591 
1592  if (strcmp(cdr->linkedid, snapshot->peer->linkedid)) {
1593  ast_string_field_set(cdr, linkedid, snapshot->peer->linkedid);
1594  }
1597 
1598  return 0;
1599 }
const ast_string_field data
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
struct ast_channel_snapshot_base * base
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127
#define ast_set_flag(p, flag)
Definition: utils.h:70
const ast_string_field exten
Definition: cdr.c:734
#define ast_assert(a)
Definition: utils.h:695
struct ast_channel_snapshot_dialplan * dialplan
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define ast_strlen_zero(foo)
Definition: strings.h:52
const ast_string_field appl
Definition: cdr.c:734
const ast_string_field context
Definition: cdr.c:734
const ast_string_field context
struct ast_flags flags
Definition: cdr.c:723
const ast_string_field appl
const ast_string_field linkedid
Definition: cdr.c:734
const ast_string_field exten
struct ast_flags softhangup_flags
const ast_string_field data
Definition: cdr.c:734
static void cdr_object_check_party_a_hangup(struct cdr_object *cdr)
Check to see if a CDR needs to move to the finalized state because its Party A hungup.
Definition: cdr.c:1477
struct ast_flags flags
static void cdr_object_check_party_a_answer(struct cdr_object *cdr)
Check to see if a CDR needs to be answered based on its Party A. Note that this is safe to call as mu...
Definition: cdr.c:1494
static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Swap an old cdr_object_snapshot&#39;s ast_channel_snapshot for a new ast_channel_snapshot.
Definition: cdr.c:1531
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_channel_snapshot_peer * peer
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
const ast_string_field name
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ bridge_candidate_add_to_cdr()

static void bridge_candidate_add_to_cdr ( struct cdr_object cdr,
struct cdr_object_snapshot party_b 
)
static

Definition at line 2472 of file cdr.c.

References ast_string_field_set, ast_channel_snapshot::base, cdr_object::bridge, cdr_all_relink(), CDR_DEBUG, cdr_object_check_party_a_answer(), cdr_object_create_and_append(), cdr_object_snapshot_copy(), cdr_object_transition_state(), cdr_object::lastevent, ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, and cdr_object_snapshot::snapshot.

Referenced by bridge_candidate_process().

2474 {
2475  struct cdr_object *new_cdr;
2476 
2477  new_cdr = cdr_object_create_and_append(cdr, &cdr->lastevent);
2478  if (!new_cdr) {
2479  return;
2480  }
2481  cdr_object_snapshot_copy(&new_cdr->party_b, party_b);
2482  cdr_all_relink(new_cdr);
2484  ast_string_field_set(new_cdr, bridge, cdr->bridge);
2486  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
2487  new_cdr, new_cdr->party_a.snapshot->base->name,
2488  party_b->snapshot->base->name);
2489 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct timeval lastevent
Definition: cdr.c:721
static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
Copy a snapshot and its details.
Definition: cdr.c:791
static void cdr_object_check_party_a_answer(struct cdr_object *cdr)
Check to see if a CDR needs to be answered based on its Party A. Note that this is safe to call as mu...
Definition: cdr.c:1494
struct cdr_object_fn_table bridge_state_fn_table
The virtual table for the Bridged state.
Definition: cdr.c:659
static struct cdr_object * cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
Create a new cdr_object and append it to an existing chain.
Definition: cdr.c:1075
const ast_string_field bridge
Definition: cdr.c:734
const ast_string_field name
static void cdr_all_relink(struct cdr_object *cdr)
Definition: cdr.c:949
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ bridge_candidate_process()

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_obj being processed
cand_cdrThe cdr_object that is a candidate

Definition at line 2503 of file cdr.c.

References ao2_lock, ao2_unlock, ast_channel_snapshot::base, cdr_object::bridge, bridge_candidate_add_to_cdr(), cdr_all_relink(), 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().

2504 {
2505  struct cdr_object_snapshot *party_a;
2506  struct cdr_object *cand_cdr;
2507 
2508  ao2_lock(base_cand_cdr);
2509 
2510  for (cand_cdr = base_cand_cdr; cand_cdr; cand_cdr = cand_cdr->next) {
2511  /* Skip any records that are not in this bridge */
2512  if (strcmp(cand_cdr->bridge, cdr->bridge)) {
2513  continue;
2514  }
2515 
2516  /* If the candidate is us or someone we've taken on, pass on by */
2517  if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)
2518  || (cdr->party_b.snapshot
2519  && !strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name))) {
2520  break;
2521  }
2522 
2523  party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
2524  /* We're party A - make a new CDR, append it to us, and set the candidate as
2525  * Party B */
2526  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2527  bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);
2528  break;
2529  }
2530 
2531  /* We're Party B. Check if we can add ourselves immediately or if we need
2532  * a new CDR for them (they already have a Party B) */
2533  if (cand_cdr->party_b.snapshot
2534  && strcasecmp(cand_cdr->party_b.snapshot->base->name, cdr->party_a.snapshot->base->name)) {
2535  bridge_candidate_add_to_cdr(cand_cdr, &cdr->party_a);
2536  } else {
2537  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
2538  cand_cdr, cand_cdr->party_a.snapshot->base->name,
2539  cdr->party_a.snapshot->base->name);
2540  cdr_object_snapshot_copy(&cand_cdr->party_b, &cdr->party_a);
2541  cdr_all_relink(cand_cdr);
2542  /* It's possible that this joined at one point and was never chosen
2543  * as party A. Clear their end time, as it would be set in such a
2544  * case.
2545  */
2546  memset(&cand_cdr->end, 0, sizeof(cand_cdr->end));
2547  }
2548 
2549  break;
2550  }
2551 
2552  ao2_unlock(base_cand_cdr);
2553 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
A wrapper object around a snapshot. Fields that are mutable by the CDR engine are replicated here...
Definition: cdr.c:704
#define ao2_unlock(a)
Definition: astobj2.h:730
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
static void bridge_candidate_add_to_cdr(struct cdr_object *cdr, struct cdr_object_snapshot *party_b)
Definition: cdr.c:2472
#define ao2_lock(a)
Definition: astobj2.h:718
static struct cdr_object_snapshot * cdr_object_pick_party_a(struct cdr_object_snapshot *left, struct cdr_object_snapshot *right)
Given two CDR snapshots, figure out who should be Party A for the resulting CDR.
Definition: cdr.c:1192
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct timeval end
Definition: cdr.c:720
static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
Copy a snapshot and its details.
Definition: cdr.c:791
const ast_string_field bridge
Definition: cdr.c:734
const ast_string_field name
static void cdr_all_relink(struct cdr_object *cdr)
Definition: cdr.c:949

◆ bridge_state_process_bridge_leave()

static int bridge_state_process_bridge_leave ( struct cdr_object cdr,
struct ast_bridge_snapshot bridge,
struct ast_channel_snapshot channel 
)
static

Definition at line 2015 of file cdr.c.

References ast_channel_snapshot::base, cdr_object::bridge, cdr_object_transition_state(), ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, cdr_object_snapshot::snapshot, and ast_bridge_snapshot::uniqueid.

2016 {
2017  if (strcmp(cdr->bridge, bridge->uniqueid)) {
2018  return 1;
2019  }
2020  if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)
2021  && cdr->party_b.snapshot
2022  && strcasecmp(cdr->party_b.snapshot->base->name, channel->base->name)) {
2023  return 1;
2024  }
2026 
2027  return 0;
2028 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct cdr_object_snapshot party_a
Definition: cdr.c:713
const ast_string_field uniqueid
Definition: bridge.h:336
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
const ast_string_field bridge
Definition: cdr.c:734
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:821

◆ bridge_state_process_party_b()

static void bridge_state_process_party_b ( struct cdr_object cdr,
struct ast_channel_snapshot snapshot 
)
static

Definition at line 2002 of file cdr.c.

References ast_assert, AST_FLAG_DEAD, ast_test_flag, ast_channel_snapshot::base, cdr_object_swap_snapshot(), cdr_object_transition_state(), ast_channel_snapshot::flags, ast_channel_snapshot_base::name, cdr_object::party_b, and cdr_object_snapshot::snapshot.

2003 {
2005  && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
2006 
2007  cdr_object_swap_snapshot(&cdr->party_b, snapshot);
2008 
2009  /* If party B hangs up, finalize this CDR */
2012  }
2013 }
struct ast_channel_snapshot_base * base
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
#define ast_assert(a)
Definition: utils.h:695
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
struct ast_flags flags
static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Swap an old cdr_object_snapshot&#39;s ast_channel_snapshot for a new ast_channel_snapshot.
Definition: cdr.c:1531
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:821

◆ cdr_all_cmp_fn()

static int cdr_all_cmp_fn ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 912 of file cdr.c.

References ast_assert, CMP_MATCH, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, OBJ_SEARCH_PARTIAL_KEY, and cdr_object::party_b_name.

Referenced by load_module().

913 {
914  struct cdr_object *left = obj;
915  struct cdr_object *right = arg;
916  const char *right_key = arg;
917  int cmp;
918 
919  switch (flags & OBJ_SEARCH_MASK) {
920  case OBJ_SEARCH_OBJECT:
921  right_key = right->party_b_name;
922  /* Fall through */
923  case OBJ_SEARCH_KEY:
924  cmp = strcasecmp(left->party_b_name, right_key);
925  break;
927  /*
928  * We could also use a partial key struct containing a length
929  * so strlen() does not get called for every comparison instead.
930  */
931  cmp = strncasecmp(left->party_b_name, right_key, strlen(right_key));
932  break;
933  default:
934  /* Sort can only work on something with a full or partial key. */
935  ast_assert(0);
936  cmp = 0;
937  break;
938  }
939  return cmp ? 0 : CMP_MATCH;
940 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
struct ast_flags flags
Definition: cdr.c:723
An in-memory representation of an active CDR.
Definition: cdr.c:712
const ast_string_field party_b_name
Definition: cdr.c:734
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076

◆ cdr_all_hash_fn()

static int cdr_all_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 888 of file cdr.c.

References ast_assert, ast_str_case_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and cdr_object::party_b_name.

Referenced by load_module().

889 {
890  const struct cdr_object *cdr;
891  const char *key;
892 
893  switch (flags & OBJ_SEARCH_MASK) {
894  case OBJ_SEARCH_KEY:
895  key = obj;
896  break;
897  case OBJ_SEARCH_OBJECT:
898  cdr = obj;
899  key = cdr->party_b_name;
900  break;
901  default:
902  ast_assert(0);
903  return 0;
904  }
905  return ast_str_case_hash(key);
906 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
struct ast_flags flags
Definition: cdr.c:723
An in-memory representation of an active CDR.
Definition: cdr.c:712
const ast_string_field party_b_name
Definition: cdr.c:734
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1250

◆ cdr_all_print_fn()

static void cdr_all_print_fn ( void *  v_obj,
void *  where,
ao2_prnt_fn prnt 
)
static

Definition at line 4472 of file cdr.c.

References ast_channel_snapshot::base, cdr_object::bridge, ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, and cdr_object_snapshot::snapshot.

Referenced by load_module().

4473 {
4474  struct cdr_object *cdr = v_obj;
4475 
4476  if (!cdr) {
4477  return;
4478  }
4479  prnt(where, "Party A: %s; Party B: %s; Bridge %s",
4480  cdr->party_a.snapshot->base->name,
4481  cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<unknown>",
4482  cdr->bridge);
4483 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct cdr_object_snapshot party_a
Definition: cdr.c:713
An in-memory representation of an active CDR.
Definition: cdr.c:712
const ast_string_field bridge
Definition: cdr.c:734
const ast_string_field name

◆ cdr_all_relink()

static void cdr_all_relink ( struct cdr_object cdr)
static

Definition at line 949 of file cdr.c.

References ao2_link_flags, ao2_lock, ao2_unlink_flags, ao2_unlock, ast_string_field_set, ast_channel_snapshot::base, ast_channel_snapshot_base::name, OBJ_NOLOCK, cdr_object::party_b, cdr_object::party_b_name, and cdr_object_snapshot::snapshot.

Referenced by ast_cdr_fork(), bridge_candidate_add_to_cdr(), bridge_candidate_process(), single_state_bridge_enter_comparison(), and single_state_process_dial_begin().

950 {
952  if (cdr->party_b.snapshot) {
953  if (strcasecmp(cdr->party_b_name, cdr->party_b.snapshot->base->name)) {
957  }
958  } else {
961  }
963 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ao2_lock(a)
Definition: astobj2.h:718
const ast_string_field party_b_name
Definition: cdr.c:734
static struct ao2_container * active_cdrs_all
A container of all active CDRs with a Party B indexed by Party B channel name.
Definition: cdr.c:368
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622
const ast_string_field name
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ cdr_all_unlink()

static void cdr_all_unlink ( struct cdr_object cdr)
static

Definition at line 972 of file cdr.c.

References ao2_lock, ao2_ref, ao2_unlink_flags, ao2_unlock, ast_assert, ast_string_field_set, cdr_object::is_root, cdr_object::next, OBJ_NOLOCK, and cdr_object::party_b_name.

Referenced by cdr_object_dispatch_all_cb(), and handle_channel_snapshot_update_message().

973 {
974  struct cdr_object *cur;
975  struct cdr_object *next;
976 
977  ast_assert(cdr->is_root);
978 
979  /* Hold a ref to the root CDR to ensure the list members don't go away on us. */
980  ao2_ref(cdr, +1);
982  for (cur = cdr; cur; cur = next) {
983  next = cur->next;
985  /*
986  * It is safe to still use cur after unlinking because the
987  * root CDR holds a ref to all the CDRs in the list and we
988  * have a ref to the root CDR.
989  */
991  }
993  ao2_ref(cdr, -1);
994 }
struct cdr_object * next
Definition: cdr.c:735
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
int is_root
Definition: cdr.c:737
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
An in-memory representation of an active CDR.
Definition: cdr.c:712
const ast_string_field party_b_name
Definition: cdr.c:734
static struct ao2_container * active_cdrs_all
A container of all active CDRs with a Party B indexed by Party B channel name.
Definition: cdr.c:368
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ cdr_detach()

static void cdr_detach ( struct ast_cdr cdr)
static

Definition at line 3841 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_calloc, ast_cdr_free(), ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_test_flag, batch, cdr_batch_item::cdr, cdr_batch_lock, CDR_BATCHMODE, CDR_ENABLED, cdr_batch::head, init_batch(), cdr_batch_item::next, post_cdr(), RAII_VAR, cdr_batch::size, start_batch_mode(), and cdr_batch::tail.

Referenced by cdr_object_dispatch().

3842 {
3843  struct cdr_batch_item *newtail;
3844  int curr;
3845  RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
3846  int submit_batch = 0;
3847 
3848  if (!cdr) {
3849  return;
3850  }
3851 
3852  /* maybe they disabled CDR stuff completely, so just drop it */
3853  if (!mod_cfg || !ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
3854  ast_debug(1, "Dropping CDR !\n");
3855  ast_cdr_free(cdr);
3856  return;
3857  }
3858 
3859  /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
3860  if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
3861  post_cdr(cdr);
3862  ast_cdr_free(cdr);
3863  return;
3864  }
3865 
3866  /* otherwise, each CDR gets put into a batch list (at the end) */
3867  ast_debug(1, "CDR detaching from this thread\n");
3868 
3869  /* we'll need a new tail for every CDR */
3870  if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
3871  post_cdr(cdr);
3872  ast_cdr_free(cdr);
3873  return;
3874  }
3875 
3876  /* don't traverse a whole list (just keep track of the tail) */
3878  if (!batch)
3879  init_batch();
3880  if (!batch->head) {
3881  /* new batch is empty, so point the head at the new tail */
3882  batch->head = newtail;
3883  } else {
3884  /* already got a batch with something in it, so just append a new tail */
3885  batch->tail->next = newtail;
3886  }
3887  newtail->cdr = cdr;
3888  batch->tail = newtail;
3889  curr = batch->size++;
3890 
3891  /* if we have enough stuff to post, then do it */
3892  if (curr >= (mod_cfg->general->batch_settings.size - 1)) {
3893  submit_batch = 1;
3894  }
3896 
3897  /* Don't submit a batch with cdr_batch_lock held */
3898  if (submit_batch) {
3899  start_batch_mode();
3900  }
3901 }
struct cdr_batch_item * tail
Definition: cdr.c:345
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void post_cdr(struct ast_cdr *cdr)
Definition: cdr.c:3508
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct ast_cdr * cdr
Definition: cdr.c:337
void ast_cdr_free(struct ast_cdr *cdr)
Free a CDR record.
Definition: cdr.c:3411
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct cdr_batch_item * next
Definition: cdr.c:338
static int init_batch(void)
Definition: cdr.c:3738
The configuration settings for this module.
Definition: cdr.c:222
static struct cdr_batch * batch
Queued CDR waiting to be batched.
Definition: cdr.c:336
static ast_mutex_t cdr_batch_lock
Lock protecting modifications to the batch queue.
Definition: cdr.c:358
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static void start_batch_mode(void)
Definition: cdr.c:3825
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct cdr_batch_item * head
Definition: cdr.c:344
int size
Definition: cdr.c:343
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ cdr_enable_batch_mode()

static void cdr_enable_batch_mode ( struct ast_cdr_config config)
static

Definition at line 4416 of file cdr.c.

References ast_cond_init, ast_log, ast_pthread_create_background, AST_PTHREADT_NULL, ast_cdr_config::batch_settings, cdr_pending_cond, cdr_thread, do_cdr(), LOG_ERROR, LOG_NOTICE, NULL, ast_cdr_config::batch_settings::size, start_batch_mode(), and ast_cdr_config::batch_settings::time.

Referenced by cdr_toggle_runtime_options().

4417 {
4418  /* Only create the thread level portions once */
4419  if (cdr_thread == AST_PTHREADT_NULL) {
4422  ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
4423  return;
4424  }
4425  }
4426 
4427  /* Start the batching process */
4428  start_batch_mode();
4429 
4430  ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %u or time %u seconds.\n",
4431  config->batch_settings.size, config->batch_settings.time);
4432 }
static void * do_cdr(void *data)
Definition: cdr.c:3903
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define NULL
Definition: resample.c:96
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
#define ast_log
Definition: astobj2.c:42
#define AST_PTHREADT_NULL
Definition: lock.h:66
struct ast_cdr_config::batch_settings batch_settings
#define LOG_ERROR
Definition: logger.h:285
static ast_cond_t cdr_pending_cond
Definition: cdr.c:362
#define LOG_NOTICE
Definition: logger.h:263
static void start_batch_mode(void)
Definition: cdr.c:3825
static pthread_t cdr_thread
Definition: cdr.c:355

◆ cdr_engine_shutdown()

static void cdr_engine_shutdown ( void  )
static

Definition at line 4385 of file cdr.c.

References aco_info_destroy(), ao2_callback, ao2_cleanup, ao2_container_unregister(), ao2_global_obj_release, ARRAY_LEN, ast_cli_unregister_multiple(), ast_free, ast_sched_context_destroy(), batch, cdr_object_dispatch_all_cb(), finalize_batch_mode(), NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, stasis_message_router_unsubscribe_and_join(), and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module().

4386 {
4388  stasis_router = NULL;
4389 
4391  cdr_topic = NULL;
4392 
4393  STASIS_MESSAGE_TYPE_CLEANUP(cdr_sync_message_type);
4394 
4400  sched = NULL;
4401  ast_free(batch);
4402  batch = NULL;
4403 
4404  aco_info_destroy(&cfg_info);
4405  ao2_global_obj_release(module_configs);
4406 
4407  ao2_container_unregister("cdrs_master");
4410 
4411  ao2_container_unregister("cdrs_all");
4414 }
static struct stasis_message_router * stasis_router
Message router for stasis messages regarding channel state.
Definition: cdr.c:371
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
void stasis_message_router_unsubscribe_and_join(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic, blocking until the final message has been processed...
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
Definition: sched.c:76
static struct stasis_topic * cdr_topic
The parent topic for all topics we want to aggregate for CDRs.
Definition: cdr.c:383
#define NULL
Definition: resample.c:96
static int cdr_object_dispatch_all_cb(void *obj, void *arg, int flags)
This dispatches all cdr_objects. It should only be used during shutdown, so that we get billing recor...
Definition: cdr.c:4260
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
static struct ast_cli_entry cli_commands[]
Definition: cdr.c:4249
static struct cdr_batch * batch
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
#define ast_free(a)
Definition: astmm.h:182
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * active_cdrs_all
A container of all active CDRs with a Party B indexed by Party B channel name.
Definition: cdr.c:368
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:269
static void finalize_batch_mode(void)
Definition: cdr.c:4277

◆ cdr_format_var_internal()

static const char* cdr_format_var_internal ( struct ast_cdr cdr,
const char *  name 
)
static

Definition at line 3018 of file cdr.c.

References AST_LIST_TRAVERSE, ast_strlen_zero, ast_var_name(), ast_var_value(), ast_var_t::entries, NULL, and ast_cdr::varshead.

Referenced by ast_cdr_format_var().

3019 {
3020  struct ast_var_t *variables;
3021 
3022  if (ast_strlen_zero(name)) {
3023  return NULL;
3024  }
3025 
3026  AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
3027  if (!strcasecmp(name, ast_var_name(variables))) {
3028  return ast_var_value(variables);
3029  }
3030  }
3031 
3032  return NULL;
3033 }
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct varshead varshead
Definition: cdr.h:323
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
Definition: cdr_mysql.c:74
struct ast_var_t::@249 entries

◆ cdr_generic_register()

static int cdr_generic_register ( struct be_list generic_list,
const char *  name,
const char *  desc,
ast_cdrbe  be 
)
static

Definition at line 2902 of file cdr.c.

References ast_calloc, ast_copy_string(), ast_free, ast_log, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, be, cdr_beitem::be, cdr_beitem::desc, LOG_WARNING, and cdr_beitem::name.

Referenced by ast_cdr_modifier_register(), and ast_cdr_register().

2903 {
2904  struct cdr_beitem *i;
2905  struct cdr_beitem *cur;
2906 
2907  if (!name) {
2908  return -1;
2909  }
2910 
2911  if (!be) {
2912  ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
2913 
2914  return -1;
2915  }
2916 
2917  i = ast_calloc(1, sizeof(*i));
2918  if (!i) {
2919  return -1;
2920  }
2921 
2922  i->be = be;
2923  ast_copy_string(i->name, name, sizeof(i->name));
2924  ast_copy_string(i->desc, desc, sizeof(i->desc));
2925 
2926  AST_RWLIST_WRLOCK(generic_list);
2927  AST_RWLIST_TRAVERSE(generic_list, cur, list) {
2928  if (!strcasecmp(name, cur->name)) {
2929  ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
2930  AST_RWLIST_UNLOCK(generic_list);
2931  ast_free(i);
2932 
2933  return -1;
2934  }
2935  }
2936 
2937  AST_RWLIST_INSERT_HEAD(generic_list, i, list);
2938  AST_RWLIST_UNLOCK(generic_list);
2939 
2940  return 0;
2941 }
char desc[80]
Definition: cdr.c:323
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:274
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static const char desc[]
Definition: cdr_mysql.c:73
char * be
Definition: eagi_proxy.c:73
Registration object for CDR backends.
Definition: cdr.c:321
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:717
#define ast_log
Definition: astobj2.c:42
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char name[20]
Definition: cdr.c:322
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
ast_cdrbe be
Definition: cdr.c:324

◆ cdr_get_tv()

static void cdr_get_tv ( struct timeval  when,
const char *  fmt,
char *  buf,
int  bufsize 
)
static

Definition at line 3035 of file cdr.c.

References ast_localtime(), ast_strftime(), and NULL.

Referenced by ast_cdr_format_var(), cdr_object_format_property(), cli_show_channel(), and cli_show_channels().

3036 {
3037  if (fmt == NULL) { /* raw mode */
3038  snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec);
3039  } else {
3040  buf[0] = '\0';/* Ensure the buffer is initialized. */
3041  if (when.tv_sec) {
3042  struct ast_tm tm;
3043 
3044  ast_localtime(&when, &tm, NULL);
3045  ast_strftime(buf, bufsize, fmt, &tm);
3046  }
3047  }
3048 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
#define NULL
Definition: resample.c:96
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524

◆ cdr_master_cmp_fn()

static int cdr_master_cmp_fn ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 854 of file cdr.c.

References ast_assert, CMP_MATCH, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, OBJ_SEARCH_PARTIAL_KEY, and cdr_object::uniqueid.

Referenced by load_module().

855 {
856  struct cdr_object *left = obj;
857  struct cdr_object *right = arg;
858  const char *right_key = arg;
859  int cmp;
860 
861  switch (flags & OBJ_SEARCH_MASK) {
862  case OBJ_SEARCH_OBJECT:
863  right_key = right->uniqueid;
864  /* Fall through */
865  case OBJ_SEARCH_KEY:
866  cmp = strcmp(left->uniqueid, right_key);
867  break;
869  /*
870  * We could also use a partial key struct containing a length
871  * so strlen() does not get called for every comparison instead.
872  */
873  cmp = strncmp(left->uniqueid, right_key, strlen(right_key));
874  break;
875  default:
876  /* Sort can only work on something with a full or partial key. */
877  ast_assert(0);
878  cmp = 0;
879  break;
880  }
881  return cmp ? 0 : CMP_MATCH;
882 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
struct ast_flags flags
Definition: cdr.c:723
An in-memory representation of an active CDR.
Definition: cdr.c:712
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
const ast_string_field uniqueid
Definition: cdr.c:734

◆ cdr_master_hash_fn()

static int cdr_master_hash_fn ( const void *  obj,
const int  flags 
)
static

Definition at line 830 of file cdr.c.

References ast_assert, ast_str_case_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and cdr_object::uniqueid.

Referenced by load_module().

831 {
832  const struct cdr_object *cdr;
833  const char *key;
834 
835  switch (flags & OBJ_SEARCH_MASK) {
836  case OBJ_SEARCH_KEY:
837  key = obj;
838  break;
839  case OBJ_SEARCH_OBJECT:
840  cdr = obj;
841  key = cdr->uniqueid;
842  break;
843  default:
844  ast_assert(0);
845  return 0;
846  }
847  return ast_str_case_hash(key);
848 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_assert(a)
Definition: utils.h:695
struct ast_flags flags
Definition: cdr.c:723
An in-memory representation of an active CDR.
Definition: cdr.c:712
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
Search option field mask.
Definition: astobj2.h:1076
const ast_string_field uniqueid
Definition: cdr.c:734
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1250

◆ cdr_master_print_fn()

static void cdr_master_print_fn ( void *  v_obj,
void *  where,
ao2_prnt_fn prnt 
)
static

Definition at line 4445 of file cdr.c.

References ast_channel_snapshot::base, cdr_object::bridge, ast_channel_snapshot_base::name, cdr_object::next, cdr_object::party_a, cdr_object::party_b, and cdr_object_snapshot::snapshot.

Referenced by load_module().

4446 {
4447  struct cdr_object *cdr = v_obj;
4448  struct cdr_object *it_cdr;
4449 
4450  if (!cdr) {
4451  return;
4452  }
4453  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4454  prnt(where, "Party A: %s; Party B: %s; Bridge %s\n",
4455  it_cdr->party_a.snapshot->base->name,
4456  it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<unknown>",
4457  it_cdr->bridge);
4458  }
4459 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct cdr_object_snapshot party_a
Definition: cdr.c:713
An in-memory representation of an active CDR.
Definition: cdr.c:712
const ast_string_field bridge
Definition: cdr.c:734
const ast_string_field name

◆ cdr_object_alloc()

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

This implicitly sets the state of the newly created CDR to the Single state (single_state_fn_table)

Definition at line 1039 of file cdr.c.

References ao2_alloc, ao2_cleanup, ao2_t_ref, ast_assert, ast_atomic_fetchadd_int(), AST_CDR_NULL, ast_string_field_init, ast_string_field_set, ast_channel_snapshot::base, CDR_DEBUG, cdr_object_dtor(), cdr_object_transition_state(), cdr_object::disposition, global_cdr_sequence, cdr_object::last, cdr_object::lastevent, ast_channel_snapshot_peer::linkedid, cdr_object::linkedid, name, ast_channel_snapshot_base::name, NULL, 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().

1040 {
1041  struct cdr_object *cdr;
1042 
1043  ast_assert(chan != NULL);
1044 
1045  cdr = ao2_alloc(sizeof(*cdr), cdr_object_dtor);
1046  if (!cdr) {
1047  return NULL;
1048  }
1049  cdr->last = cdr;
1050  if (ast_string_field_init(cdr, 64)) {
1051  ao2_cleanup(cdr);
1052  return NULL;
1053  }
1055  ast_string_field_set(cdr, name, chan->base->name);
1057  cdr->disposition = AST_CDR_NULL;
1059  cdr->lastevent = *event_time;
1060 
1061  cdr->party_a.snapshot = chan;
1062  ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
1063 
1064  CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->base->name);
1065 
1067 
1068  return cdr;
1069 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
static void cdr_object_dtor(void *obj)
cdr_object Destructor
Definition: cdr.c:999
const ast_string_field uniqueid
unsigned int sequence
Definition: cdr.c:722
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
struct cdr_object_snapshot party_a
Definition: cdr.c:713
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
static int global_cdr_sequence
The global sequence counter used for CDRs.
Definition: cdr.c:349
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
const ast_string_field linkedid
Definition: cdr.c:734
enum ast_cdr_disposition disposition
Definition: cdr.c:717
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct cdr_object * last
Definition: cdr.c:736
struct cdr_object_fn_table single_state_fn_table
The virtual table for the Single state.
Definition: cdr.c:573
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct timeval lastevent
Definition: cdr.c:721
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const ast_string_field uniqueid
Definition: cdr.c:734
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:821
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ cdr_object_check_party_a_answer()

static void cdr_object_check_party_a_answer ( struct cdr_object cdr)
static

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.

Definition at line 1494 of file cdr.c.

References cdr_object::answer, AST_STATE_UP, ast_tvzero(), CDR_DEBUG, cdr_object::lastevent, cdr_object::party_a, cdr_object_snapshot::snapshot, and ast_channel_snapshot::state.

Referenced by ast_cdr_reset(), base_process_party_a(), bridge_candidate_add_to_cdr(), and single_state_init_function().

1495 {
1496  if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
1497  cdr->answer = cdr->lastevent;
1498  /* tv_usec is suseconds_t, which could be int or long */
1499  CDR_DEBUG("%p - Set answered time to %ld.%06ld\n", cdr,
1500  (long)cdr->answer.tv_sec,
1501  (long)cdr->answer.tv_usec);
1502  }
1503 }
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct timeval answer
Definition: cdr.c:719
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
struct timeval lastevent
Definition: cdr.c:721
enum ast_channel_state state

◆ cdr_object_check_party_a_hangup()

static void cdr_object_check_party_a_hangup ( struct cdr_object cdr)
static

Check to see if a CDR needs to move to the finalized state because its Party A hungup.

Definition at line 1477 of file cdr.c.

References AST_FLAG_DEAD, AST_SOFTHANGUP_HANGUP_EXEC, ast_test_flag, CDR_END_BEFORE_H_EXTEN, cdr_object_finalize(), cdr_object_transition_state(), ast_channel_snapshot::flags, cdr_object::fn_table, is_cdr_flag_set(), cdr_object::party_a, cdr_object_snapshot::snapshot, and ast_channel_snapshot::softhangup_flags.

Referenced by base_process_party_a().

1478 {
1481  cdr_object_finalize(cdr);
1482  }
1483 
1485  && cdr->fn_table != &finalized_state_fn_table) {
1487  }
1488 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127
struct cdr_object_snapshot party_a
Definition: cdr.c:713
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
struct ast_flags softhangup_flags
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
struct ast_flags flags
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821

◆ cdr_object_create_and_append()

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

Definition at line 1075 of file cdr.c.

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

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

1076 {
1077  struct cdr_object *new_cdr;
1078  struct cdr_object *it_cdr;
1079  struct cdr_object *cdr_last;
1080 
1081  cdr_last = cdr->last;
1082  new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot, event_time);
1083  if (!new_cdr) {
1084  return NULL;
1085  }
1086  new_cdr->disposition = AST_CDR_NULL;
1087 
1088  /* Copy over the linkedid, as it may have changed */
1089  ast_string_field_set(new_cdr, linkedid, cdr_last->linkedid);
1090  ast_string_field_set(new_cdr, appl, cdr_last->appl);
1091  ast_string_field_set(new_cdr, data, cdr_last->data);
1092  ast_string_field_set(new_cdr, context, cdr_last->context);
1093  ast_string_field_set(new_cdr, exten, cdr_last->exten);
1094 
1095  /*
1096  * If the current CDR says to disable all future ones,
1097  * keep the disable chain going
1098  */
1099  if (ast_test_flag(&cdr_last->flags, AST_CDR_FLAG_DISABLE_ALL)) {
1101  }
1102 
1103  /* Copy over other Party A information */
1104  cdr_object_snapshot_copy(&new_cdr->party_a, &cdr_last->party_a);
1105 
1106  /* Append the CDR to the end of the list */
1107  for (it_cdr = cdr; it_cdr->next; it_cdr = it_cdr->next) {
1108  it_cdr->last = new_cdr;
1109  }
1110  it_cdr->last = new_cdr;
1111  it_cdr->next = new_cdr;
1112 
1113  return new_cdr;
1114 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct cdr_object * next
Definition: cdr.c:735
const ast_string_field exten
Definition: cdr.c:734
static struct cdr_object * cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
cdr_object constructor
Definition: cdr.c:1039
#define NULL
Definition: resample.c:96
struct cdr_object_snapshot party_a
Definition: cdr.c:713
const ast_string_field appl
Definition: cdr.c:734
const ast_string_field context
Definition: cdr.c:734
struct ast_flags flags
Definition: cdr.c:723
const ast_string_field linkedid
Definition: cdr.c:734
enum ast_cdr_disposition disposition
Definition: cdr.c:717
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct cdr_object * last
Definition: cdr.c:736
const ast_string_field data
Definition: cdr.c:734
static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
Copy a snapshot and its details.
Definition: cdr.c:791
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ cdr_object_create_public_records()

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
Return values
Achain of ast_cdr objects on success
NULLon failure

Definition at line 1287 of file cdr.c.

References ast_channel_snapshot_base::accountcode, ast_cdr::accountcode, ast_channel_snapshot::amaflags, ast_cdr::amaflags, ast_cdr::answer, cdr_object::answer, cdr_object::appl, ast_assert, ast_callerid_merge(), ast_calloc, ast_copy_flags, ast_copy_string(), ast_debug, AST_FLAGS_ALL, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strlen_zero, ast_var_assign, ast_var_name(), ast_var_value(), ast_channel_snapshot::base, ast_cdr::billsec, ast_channel_snapshot::caller, cdr_object_get_billsec(), cdr_object_get_duration(), ast_cdr::channel, 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, ast_cdr::end, cdr_object::end, ast_var_t::entries, 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, ast_cdr::next, cdr_object::next, NULL, 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, ast_cdr::start, 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().

1288 {
1289  struct ast_cdr *pub_cdr = NULL, *cdr_prev = NULL;
1290  struct cdr_object *it_cdr;
1291  struct ast_var_t *it_var, *it_copy_var;
1292  struct ast_channel_snapshot *party_a;
1293  struct ast_channel_snapshot *party_b;
1294 
1295  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
1296  struct ast_cdr *cdr_copy;
1297 
1298  /* Don't create records for CDRs where the party A was a dialed channel */
1299  if (snapshot_is_dialed(it_cdr->party_a.snapshot) && !it_cdr->party_b.snapshot) {
1300  ast_debug(1, "CDR for %s is dialed and has no Party B; discarding\n",
1301  it_cdr->party_a.snapshot->base->name);
1302  continue;
1303  }
1304 
1305  cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
1306  if (!cdr_copy) {
1307  ast_free(pub_cdr);
1308  return NULL;
1309  }
1310 
1311  party_a = it_cdr->party_a.snapshot;
1312  party_b = it_cdr->party_b.snapshot;
1313 
1314  /* Party A */
1315  ast_assert(party_a != NULL);
1316  ast_copy_string(cdr_copy->accountcode, party_a->base->accountcode, sizeof(cdr_copy->accountcode));
1317  cdr_copy->amaflags = party_a->amaflags;
1318  ast_copy_string(cdr_copy->channel, party_a->base->name, sizeof(cdr_copy->channel));
1319  ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller->name, party_a->caller->number, "");
1320  ast_copy_string(cdr_copy->src, party_a->caller->number, sizeof(cdr_copy->src));
1321  ast_copy_string(cdr_copy->uniqueid, party_a->base->uniqueid, sizeof(cdr_copy->uniqueid));
1322  ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
1323  ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
1324  ast_copy_string(cdr_copy->dst, it_cdr->exten, sizeof(cdr_copy->dst));
1325  ast_copy_string(cdr_copy->dcontext, it_cdr->context, sizeof(cdr_copy->dcontext));
1326 
1327  /* Party B */
1328  if (party_b) {
1329  ast_copy_string(cdr_copy->dstchannel, party_b->base->name, sizeof(cdr_copy->dstchannel));
1330  ast_copy_string(cdr_copy->peeraccount, party_b->base->accountcode, sizeof(cdr_copy->peeraccount));
1331  if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
1332  snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
1333  }
1334  }
1335  if (ast_strlen_zero(cdr_copy->userfield) && !ast_strlen_zero(it_cdr->party_a.userfield)) {
1336  ast_copy_string(cdr_copy->userfield, it_cdr->party_a.userfield, sizeof(cdr_copy->userfield));
1337  }
1338 
1339  /* Timestamps/durations */
1340  cdr_copy->start = it_cdr->start;
1341  cdr_copy->answer = it_cdr->answer;
1342  cdr_copy->end = it_cdr->end;
1343  cdr_copy->billsec = cdr_object_get_billsec(it_cdr);
1344  cdr_copy->duration = cdr_object_get_duration(it_cdr);
1345 
1346  /* Flags and IDs */
1347  ast_copy_flags(cdr_copy, &it_cdr->flags, AST_FLAGS_ALL);
1348  ast_copy_string(cdr_copy->linkedid, it_cdr->linkedid, sizeof(cdr_copy->linkedid));
1349  cdr_copy->disposition = it_cdr->disposition;
1350  cdr_copy->sequence = it_cdr->sequence;
1351 
1352  /* Variables */
1353  copy_variables(&cdr_copy->varshead, &it_cdr->party_a.variables);
1354  AST_LIST_TRAVERSE(&it_cdr->party_b.variables, it_var, entries) {
1355  int found = 0;
1356  struct ast_var_t *newvariable;
1357  AST_LIST_TRAVERSE(&cdr_copy->varshead, it_copy_var, entries) {
1358  if (!strcasecmp(ast_var_name(it_var), ast_var_name(it_copy_var))) {
1359  found = 1;
1360  break;
1361  }
1362  }
1363  if (!found && (newvariable = ast_var_assign(ast_var_name(it_var), ast_var_value(it_var)))) {
1364  AST_LIST_INSERT_TAIL(&cdr_copy->varshead, newvariable, entries);
1365  }
1366  }
1367 
1368  if (!pub_cdr) {
1369  pub_cdr = cdr_copy;
1370  cdr_prev = pub_cdr;
1371  } else {
1372  cdr_prev->next = cdr_copy;
1373  cdr_prev = cdr_copy;
1374  }
1375  }
1376 
1377  return pub_cdr;
1378 }
static long cdr_object_get_billsec(struct cdr_object *cdr)
Compute the billsec for a cdr_object.
Definition: cdr.c:1235
char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:308
struct ast_channel_snapshot_base * base
struct varshead variables
Definition: cdr.c:708
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:288
const ast_string_field name
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
long int billsec
Definition: cdr.h:302
struct ast_cdr * next
Definition: cdr.h:325
char dcontext[AST_MAX_EXTENSION]
Definition: cdr.h:284
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
Structure representing a snapshot of channel state.
int sequence
Definition: cdr.h:320
const ast_string_field accountcode
const ast_string_field exten
Definition: cdr.c:734
struct timeval answer
Definition: cdr.c:719
const ast_string_field uniqueid
unsigned int sequence
Definition: cdr.c:722
#define ast_assert(a)
Definition: utils.h:695
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
struct timeval start
Definition: cdr.c:718
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:746
#define NULL
Definition: resample.c:96
static long cdr_object_get_duration(struct cdr_object *cdr)
Definition: cdr.c:1227
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define ast_strlen_zero(foo)
Definition: strings.h:52
const ast_string_field appl
Definition: cdr.c:734
struct varshead varshead
Definition: cdr.h:323
const ast_string_field context
Definition: cdr.c:734
char lastdata[AST_MAX_EXTENSION]
Definition: cdr.h:292
long int amaflags
Definition: cdr.h:306
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:706
struct ast_flags flags
Definition: cdr.c:723
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1073
char linkedid[AST_MAX_UNIQUEID]
Definition: cdr.h:316
const ast_string_field linkedid
Definition: cdr.c:734
char uniqueid[AST_MAX_UNIQUEID]
Definition: cdr.h:314
char dst[AST_MAX_EXTENSION]
Definition: cdr.h:282
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:286
enum ast_cdr_disposition disposition
Definition: cdr.c:717
struct ast_channel_snapshot_caller * caller
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct timeval answer
Definition: cdr.h:296
Responsible for call detail data.
Definition: cdr.h:276
char lastapp[AST_MAX_EXTENSION]
Definition: cdr.h:290
const ast_string_field data
Definition: cdr.c:734
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
Return whether or not a ast_channel_snapshot is for a channel that was created as the result of a dia...
Definition: cdr.c:1179
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct timeval end
Definition: cdr.c:720
struct timeval start
Definition: cdr.h:294
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_var_t::@249 entries
#define AST_FLAGS_ALL
Definition: utils.h:196
#define ast_var_assign(name, value)
Definition: chanvars.h:40
long int duration
Definition: cdr.h:300
char src[AST_MAX_EXTENSION]
Definition: cdr.h:280
char peeraccount[AST_MAX_ACCOUNT_CODE]
Definition: cdr.h:310
struct timeval end
Definition: cdr.h:298
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:401
long int disposition
Definition: cdr.h:304
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:278
const ast_string_field name
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.h:318

◆ cdr_object_dispatch()

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 1386 of file cdr.c.

References ast_channel_snapshot::base, CDR_DEBUG, cdr_detach(), 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().

1387 {
1388  struct ast_cdr *pub_cdr;
1389 
1390  CDR_DEBUG("%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
1391  cdr->party_a.snapshot->base->name,
1392  cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<none>");
1393  pub_cdr = cdr_object_create_public_records(cdr);
1394  cdr_detach(pub_cdr);
1395 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
static void cdr_detach(struct ast_cdr *cdr)
Definition: cdr.c:3841
Responsible for call detail data.
Definition: cdr.h:276
static struct ast_cdr * cdr_object_create_public_records(struct cdr_object *cdr)
Create a chain of ast_cdr objects from a chain of cdr_object suitable for consumption by the register...
Definition: cdr.c:1287
const ast_string_field name

◆ cdr_object_dispatch_all_cb()

static int cdr_object_dispatch_all_cb ( void *  obj,
void *  arg,
int  flags 
)
static

This dispatches all cdr_objects. It should only be used during shutdown, so that we get billing records for everything that we can.

Definition at line 4260 of file cdr.c.

References ao2_lock, ao2_unlock, cdr_all_unlink(), cdr_object_dispatch(), cdr_object_transition_state(), CMP_MATCH, and cdr_object::next.

Referenced by cdr_engine_shutdown().

4261 {
4262  struct cdr_object *cdr = obj;
4263  struct cdr_object *it_cdr;
4264 
4265  ao2_lock(cdr);
4266  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4268  }
4269  cdr_object_dispatch(cdr);
4270  ao2_unlock(cdr);
4271 
4272  cdr_all_unlink(cdr);
4273 
4274  return CMP_MATCH;
4275 }
static void cdr_all_unlink(struct cdr_object *cdr)
Definition: cdr.c:972
struct cdr_object * next
Definition: cdr.c:735
#define ao2_unlock(a)
Definition: astobj2.h:730
static void cdr_object_dispatch(struct cdr_object *cdr)
Dispatch a CDR.
Definition: cdr.c:1386
#define ao2_lock(a)
Definition: astobj2.h:718
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821

◆ cdr_object_dtor()

static void cdr_object_dtor ( void *  obj)
static

cdr_object Destructor

Definition at line 999 of file cdr.c.

References ao2_cleanup, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_var_delete(), ast_var_t::entries, cdr_object::is_root, cdr_object::next, cdr_object::party_a, cdr_object::party_b, cdr_object_snapshot::snapshot, and cdr_object_snapshot::variables.

Referenced by cdr_object_alloc().

1000 {
1001  struct cdr_object *cdr = obj;
1002  struct ast_var_t *it_var;
1003 
1006  while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_a.variables, entries))) {
1007  ast_var_delete(it_var);
1008  }
1009  while ((it_var = AST_LIST_REMOVE_HEAD(&cdr->party_b.variables, entries))) {
1010  ast_var_delete(it_var);
1011  }
1013 
1014  /* CDR destruction used to work by calling ao2_cleanup(next) and
1015  * allowing the chain to destroy itself neatly. Unfortunately, for
1016  * really long chains, this can result in a stack overflow. So now
1017  * when the root CDR is destroyed, it is responsible for unreffing
1018  * all CDRs in the chain
1019  */
1020  if (cdr->is_root) {
1021  struct cdr_object *curr = cdr->next;
1022  struct cdr_object *next;
1023 
1024  while (curr) {
1025  next = curr->next;
1026  ao2_cleanup(curr);
1027  curr = next;
1028  }
1029  }
1030 }
struct varshead variables
Definition: cdr.c:708
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct cdr_object_snapshot party_a
Definition: cdr.c:713
int is_root
Definition: cdr.c:737
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
An in-memory representation of an active CDR.
Definition: cdr.c:712
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
struct ast_var_t::@249 entries
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ cdr_object_finalize()

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_object'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
cdr_objectThe CDR to finalize

Definition at line 1440 of file cdr.c.

References cdr_object::answer, AST_CDR_ANSWERED, ast_cdr_disp2str(), AST_CDR_FAILED, AST_CDR_NULL, 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(), base_process_party_a(), cdr_object_check_party_a_hangup(), cdr_object_finalize_party_b(), cdr_object_party_b_left_bridge_cb(), dial_state_process_bridge_enter(), finalized_state_init_function(), handle_channel_snapshot_update_message(), handle_standard_bridge_enter_message(), and single_state_bridge_enter_comparison().

1441 {
1442  if (!ast_tvzero(cdr->end)) {
1443  return;
1444  }
1445  cdr->end = cdr->lastevent;
1446 
1447  if (cdr->disposition == AST_CDR_NULL) {
1448  if (!ast_tvzero(cdr->answer)) {
1450  } else if (cdr->party_a.snapshot->hangup->cause) {
1452  } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangup->cause) {
1454  } else {
1455  cdr->disposition = AST_CDR_FAILED;
1456  }
1457  }
1458 
1459  /* tv_usec is suseconds_t, which could be int or long */
1460  ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dur %.3f bill %.3f dispo %s\n",
1461  cdr->party_a.snapshot->base->name,
1462  (long)cdr->start.tv_sec,
1463  (long)cdr->start.tv_usec,
1464  (long)cdr->answer.tv_sec,
1465  (long)cdr->answer.tv_usec,
1466  (long)cdr->end.tv_sec,
1467  (long)cdr->end.tv_usec,
1468  (double)ast_tvdiff_ms(cdr->end, cdr->start) / 1000.0,
1469  (double)ast_tvdiff_ms(cdr->end, cdr->answer) / 1000.0,
1471 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct timeval answer
Definition: cdr.c:719
static void cdr_object_set_disposition(struct cdr_object *cdr, int hangupcause)
Set the disposition on a cdr_object based on a hangupcause code.
Definition: cdr.c:1402
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
struct timeval start
Definition: cdr.c:718
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct ast_channel_snapshot_hangup * hangup
enum ast_cdr_disposition disposition
Definition: cdr.c:717
struct timeval lastevent
Definition: cdr.c:721
struct timeval end
Definition: cdr.c:720
const ast_string_field name
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3430

◆ cdr_object_finalize_party_b()

static int cdr_object_finalize_party_b ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 2196 of file cdr.c.

References ast_assert, ast_channel_snapshot::base, cdr_object_finalize(), ast_channel_snapshot_base::name, cdr_object::party_b, cdr_object::party_b_name, and cdr_object_snapshot::snapshot.

Referenced by handle_channel_snapshot_update_message().

2197 {
2198  struct cdr_object *cdr = obj;
2199 
2200  if (!strcasecmp(cdr->party_b_name, arg)) {
2201 #ifdef AST_DEVMODE
2202  struct ast_channel_snapshot *party_b = data;
2203 
2204  /*
2205  * For sanity's sake we also assert the party_b snapshot
2206  * is consistent with the key.
2207  */
2209  && !strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name));
2210 #endif
2211 
2212  /* Don't transition to the finalized state - let the Party A do
2213  * that when its ready
2214  */
2215  cdr_object_finalize(cdr);
2216  }
2217  return 0;
2218 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
Structure representing a snapshot of channel state.
#define ast_assert(a)
Definition: utils.h:695
An in-memory representation of an active CDR.
Definition: cdr.c:712
const ast_string_field party_b_name
Definition: cdr.c:734
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
const ast_string_field name

◆ cdr_object_format_property()

static int cdr_object_format_property ( struct cdr_object cdr_obj,
const char *  name,
char *  value,
size_t  length 
)
static

Format one of the standard properties on a cdr_object.

Definition at line 3243 of file cdr.c.

References ast_channel_snapshot_base::accountcode, ast_channel_snapshot::amaflags, cdr_object::answer, ast_channel_snapshot_dialplan::appl, ast_callerid_merge(), ast_copy_string(), ast_channel_snapshot::base, ast_channel_snapshot::caller, cdr_get_tv(), cdr_object_get_billsec(), cdr_object_get_duration(), ast_channel_snapshot_dialplan::context, ast_channel_snapshot_dialplan::data, ast_channel_snapshot::dialplan, cdr_object::disposition, cdr_object::end, ast_channel_snapshot_dialplan::exten, cdr_object::linkedid, ast_channel_snapshot_caller::name, ast_channel_snapshot_base::name, NULL, ast_channel_snapshot_caller::number, cdr_object::party_a, cdr_object::party_b, cdr_object::sequence, cdr_object_snapshot::snapshot, cdr_object::start, ast_channel_snapshot_base::uniqueid, and cdr_object_snapshot::userfield.

Referenced by ast_cdr_getvar(), and ast_cdr_serialize_variables().

3244 {
3245  struct ast_channel_snapshot *party_a = cdr_obj->party_a.snapshot;
3246  struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;
3247 
3248  if (!strcasecmp(name, "clid")) {
3249  ast_callerid_merge(value, length, party_a->caller->name, party_a->caller->number, "");
3250  } else if (!strcasecmp(name, "src")) {
3251  ast_copy_string(value, party_a->caller->number, length);
3252  } else if (!strcasecmp(name, "dst")) {
3253  ast_copy_string(value, party_a->dialplan->exten, length);
3254  } else if (!strcasecmp(name, "dcontext")) {
3255  ast_copy_string(value, party_a->dialplan->context, length);
3256  } else if (!strcasecmp(name, "channel")) {
3257  ast_copy_string(value, party_a->base->name, length);
3258  } else if (!strcasecmp(name, "dstchannel")) {
3259  if (party_b) {
3260  ast_copy_string(value, party_b->base->name, length);
3261  } else {
3262  ast_copy_string(value, "", length);
3263  }
3264  } else if (!strcasecmp(name, "lastapp")) {
3265  ast_copy_string(value, party_a->dialplan->appl, length);
3266  } else if (!strcasecmp(name, "lastdata")) {
3267  ast_copy_string(value, party_a->dialplan->data, length);
3268  } else if (!strcasecmp(name, "start")) {
3269  cdr_get_tv(cdr_obj->start, NULL, value, length);
3270  } else if (!strcasecmp(name, "answer")) {
3271  cdr_get_tv(cdr_obj->answer, NULL, value, length);
3272  } else if (!strcasecmp(name, "end")) {
3273  cdr_get_tv(cdr_obj->end, NULL, value, length);
3274  } else if (!strcasecmp(name, "duration")) {
3275  snprintf(value, length, "%ld", cdr_object_get_duration(cdr_obj));
3276  } else if (!strcasecmp(name, "billsec")) {
3277  snprintf(value, length, "%ld", cdr_object_get_billsec(cdr_obj));
3278  } else if (!strcasecmp(name, "disposition")) {
3279  snprintf(value, length, "%u", cdr_obj->disposition);
3280  } else if (!strcasecmp(name, "amaflags")) {
3281  snprintf(value, length, "%d", party_a->amaflags);
3282  } else if (!strcasecmp(name, "accountcode")) {
3283  ast_copy_string(value, party_a->base->accountcode, length);
3284  } else if (!strcasecmp(name, "peeraccount")) {
3285  if (party_b) {
3286  ast_copy_string(value, party_b->base->accountcode, length);
3287  } else {
3288  ast_copy_string(value, "", length);
3289  }
3290  } else if (!strcasecmp(name, "uniqueid")) {
3291  ast_copy_string(value, party_a->base->uniqueid, length);
3292  } else if (!strcasecmp(name, "linkedid")) {
3293  ast_copy_string(value, cdr_obj->linkedid, length);
3294  } else if (!strcasecmp(name, "userfield")) {
3295  ast_copy_string(value, cdr_obj->party_a.userfield, length);
3296  } else if (!strcasecmp(name, "sequence")) {
3297  snprintf(value, length, "%u", cdr_obj->sequence);
3298  } else {
3299  return 1;
3300  }
3301 
3302  return 0;
3303 }
const ast_string_field data
static long cdr_object_get_billsec(struct cdr_object *cdr)
Compute the billsec for a cdr_object.
Definition: cdr.c:1235
struct ast_channel_snapshot_base * base
const ast_string_field name
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
Structure representing a snapshot of channel state.
const ast_string_field accountcode
struct timeval answer
Definition: cdr.c:719
const ast_string_field uniqueid
unsigned int sequence
Definition: cdr.c:722
struct timeval start
Definition: cdr.c:718
#define NULL
Definition: resample.c:96
static long cdr_object_get_duration(struct cdr_object *cdr)
Definition: cdr.c:1227
int value
Definition: syslog.c:37
struct ast_channel_snapshot_dialplan * dialplan
struct cdr_object_snapshot party_a
Definition: cdr.c:713
const ast_string_field context
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:706
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1073
const ast_string_field appl
const ast_string_field linkedid
Definition: cdr.c:734
const ast_string_field exten
static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
Definition: cdr.c:3035
enum ast_cdr_disposition disposition
Definition: cdr.c:717
struct ast_channel_snapshot_caller * caller
struct timeval end
Definition: cdr.c:720
static const char name[]
Definition: cdr_mysql.c:74
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:401
const ast_string_field name

◆ cdr_object_format_var_internal()

static void cdr_object_format_var_internal ( struct cdr_object cdr,
const char *  name,
char *  value,
size_t  length 
)
static

Format a variable on a cdr_object.

Definition at line 3226 of file cdr.c.

References ast_copy_string(), AST_LIST_TRAVERSE, ast_var_name(), ast_var_value(), ast_var_t::entries, cdr_object::party_a, and cdr_object_snapshot::variables.

Referenced by ast_cdr_getvar().

3227 {
3228  struct ast_var_t *variable;
3229 
3230  AST_LIST_TRAVERSE(&cdr->party_a.variables, variable, entries) {
3231  if (!strcasecmp(name, ast_var_name(variable))) {
3232  ast_copy_string(value, ast_var_value(variable), length);
3233  return;
3234  }
3235  }
3236 
3237  *value = '\0';
3238 }
struct varshead variables
Definition: cdr.c:708
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
int value
Definition: syslog.c:37
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
Definition: cdr_mysql.c:74
struct ast_var_t::@249 entries
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ cdr_object_get_billsec()

static long cdr_object_get_billsec ( struct cdr_object cdr)
static

Compute the billsec for a cdr_object.

Definition at line 1235 of file cdr.c.

References cdr_object::answer, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), CDR_INITIATED_SECONDS, cdr_object::end, and is_cdr_flag_set().

Referenced by cdr_object_create_public_records(), and cdr_object_format_property().

1236 {
1237  long int ms;
1238 
1239  if (ast_tvzero(cdr->answer)) {
1240  return 0;
1241  }
1242 
1243  ms = ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->answer);
1244  if (ms % 1000 >= 500
1246  ms = (ms / 1000) + 1;
1247  } else {
1248  ms = ms / 1000;
1249  }
1250 
1251  return ms;
1252 }
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct timeval answer
Definition: cdr.c:719
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
struct timeval end
Definition: cdr.c:720

◆ cdr_object_get_by_name()

static struct cdr_object* cdr_object_get_by_name ( const char *  name)
static

Definition at line 3312 of file cdr.c.

References ao2_callback, ast_strdupa, ast_strlen_zero, cdr_object_get_by_name_cb(), and NULL.

Referenced by ast_cdr_clear_property(), ast_cdr_fork(), ast_cdr_getvar(), ast_cdr_reset(), ast_cdr_serialize_variables(), ast_cdr_set_property(), ast_cdr_setuserfield(), and cli_show_channel().

3313 {
3314  char *param;
3315 
3316  if (ast_strlen_zero(name)) {
3317  return NULL;
3318  }
3319 
3320  param = ast_strdupa(name);
3322 }
static int cdr_object_get_by_name_cb(void *obj, void *arg, int flags)
Definition: cdr.c:3142
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
static const char name[]
Definition: cdr_mysql.c:74

◆ cdr_object_get_by_name_cb()

static int cdr_object_get_by_name_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 3142 of file cdr.c.

References ast_channel_snapshot::base, CMP_MATCH, name, ast_channel_snapshot_base::name, cdr_object::party_a, and cdr_object_snapshot::snapshot.

Referenced by cdr_object_get_by_name().

3143 {
3144  struct cdr_object *cdr = obj;
3145  const char *name = arg;
3146 
3147  if (!strcasecmp(cdr->party_a.snapshot->base->name, name)) {
3148  return CMP_MATCH;
3149  }
3150  return 0;
3151 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_a
Definition: cdr.c:713
An in-memory representation of an active CDR.
Definition: cdr.c:712
static const char name[]
Definition: cdr_mysql.c:74
const ast_string_field name

◆ cdr_object_get_duration()

static long cdr_object_get_duration ( struct cdr_object cdr)
static

Compute the duration for a cdr_object

Definition at line 1227 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().

1228 {
1229  return (long)(ast_tvdiff_ms(ast_tvzero(cdr->end) ? ast_tvnow() : cdr->end, cdr->start) / 1000);
1230 }
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
struct timeval start
Definition: cdr.c:718
struct timeval end
Definition: cdr.c:720

◆ cdr_object_party_b_left_bridge_cb()

static int cdr_object_party_b_left_bridge_cb ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Callback used to notify CDRs of a Party B leaving the bridge.

Definition at line 2361 of file cdr.c.

References ast_assert, ast_channel_snapshot::base, cdr_object::bridge, bridge_leave_data::bridge, cdr_object_finalize(), bridge_leave_data::channel, cdr_object::fn_table, cdr_object::lastevent, bridge_leave_data::lastevent, ast_channel_snapshot_base::name, cdr_object::party_b, cdr_object::party_b_name, cdr_object_snapshot::snapshot, and ast_bridge_snapshot::uniqueid.

Referenced by handle_bridge_leave_message().

2362 {
2363  struct cdr_object *cdr = obj;
2364  struct bridge_leave_data *leave_data = data;
2365 
2366  if (cdr->fn_table == &bridge_state_fn_table
2367  && !strcmp(cdr->bridge, leave_data->bridge->uniqueid)
2368  && !strcasecmp(cdr->party_b_name, arg)) {
2369  /*
2370  * For sanity's sake we also assert the party_b snapshot
2371  * is consistent with the key.
2372  */
2374  && !strcasecmp(cdr->party_b.snapshot->base->name, leave_data->channel->base->name));
2375 
2376  /* It is our Party B, in our bridge. Set the last event and let the handler
2377  * transition our CDR appropriately when we leave the bridge.
2378  */
2379  cdr->lastevent = *leave_data->lastevent;
2380  cdr_object_finalize(cdr);
2381  }
2382  return 0;
2383 }
struct ast_bridge_snapshot * bridge
Definition: cdr.c:2355
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
#define ast_assert(a)
Definition: utils.h:695
struct ast_channel_snapshot * channel
Definition: cdr.c:2356
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
const ast_string_field party_b_name
Definition: cdr.c:734
struct timeval lastevent
Definition: cdr.c:721
const ast_string_field uniqueid
Definition: bridge.h:336
const struct timeval * lastevent
Definition: cdr.c:2357
struct cdr_object_fn_table bridge_state_fn_table
The virtual table for the Bridged state.
Definition: cdr.c:659
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
const ast_string_field bridge
Definition: cdr.c:734
const ast_string_field name

◆ cdr_object_pick_party_a()

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
Return values
Thesnapshot that won

Definition at line 1192 of file cdr.c.

References AST_CDR_FLAG_PARTY_A, ast_test_flag, 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().

1193 {
1194  /* Check whether or not the party is dialed. A dialed party is never the
1195  * Party A with a party that was not dialed.
1196  */
1197  if (!snapshot_is_dialed(left->snapshot) && snapshot_is_dialed(right->snapshot)) {
1198  return left;
1199  } else if (snapshot_is_dialed(left->snapshot) && !snapshot_is_dialed(right->snapshot)) {
1200  return right;
1201  }
1202 
1203  /* Try the Party A flag */
1205  return left;
1206  } else if (!ast_test_flag(right, AST_CDR_FLAG_PARTY_A) && ast_test_flag(right, AST_CDR_FLAG_PARTY_A)) {
1207  return right;
1208  }
1209 
1210  /* Neither party is dialed and neither has the Party A flag - defer to
1211  * creation time */
1212  if (left->snapshot->base->creationtime.tv_sec < right->snapshot->base->creationtime.tv_sec) {
1213  return left;
1214  } else if (left->snapshot->base->creationtime.tv_sec > right->snapshot->base->creationtime.tv_sec) {
1215  return right;
1216  } else if (left->snapshot->base->creationtime.tv_usec > right->snapshot->base->creationtime.tv_usec) {
1217  return right;
1218  } else {
1219  /* Okay, fine, take the left one */
1220  return left;
1221  }
1222 }
struct ast_channel_snapshot_base * base
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
Return whether or not a ast_channel_snapshot is for a channel that was created as the result of a dia...
Definition: cdr.c:1179

◆ cdr_object_select_all_by_name_cb()

static int cdr_object_select_all_by_name_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 3126 of file cdr.c.

References ast_channel_snapshot::base, CMP_MATCH, name, ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, and cdr_object_snapshot::snapshot.

Referenced by ast_cdr_setvar().

3127 {
3128  struct cdr_object *cdr = obj;
3129  const char *name = arg;
3130 
3131  if (!strcasecmp(cdr->party_a.snapshot->base->name, name) ||
3132  (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->base->name, name))) {
3133  return CMP_MATCH;
3134  }
3135  return 0;
3136 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct cdr_object_snapshot party_a
Definition: cdr.c:713
An in-memory representation of an active CDR.
Definition: cdr.c:712
static const char name[]
Definition: cdr_mysql.c:74
const ast_string_field name

◆ cdr_object_set_disposition()

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 1402 of file cdr.c.

References AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_UNREGISTERED, AST_CDR_BUSY, AST_CDR_CONGESTION, AST_CDR_FAILED, AST_CDR_NOANSWER, CDR_CONGESTION, cdr_object::disposition, and is_cdr_flag_set().

Referenced by cdr_object_finalize().

1403 {
1404  /* Change the disposition based on the hang up cause */
1405  switch (hangupcause) {
1406  case AST_CAUSE_BUSY:
1407  cdr->disposition = AST_CDR_BUSY;
1408  break;
1409  case AST_CAUSE_CONGESTION:
1411  cdr->disposition = AST_CDR_FAILED;
1412  } else {
1414  }
1415  break;
1418  cdr->disposition = AST_CDR_FAILED;
1419  break;
1421  case AST_CAUSE_NO_ANSWER:
1423  break;
1424  default:
1425  break;
1426  }
1427 }
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:108
enum ast_cdr_disposition disposition
Definition: cdr.c:717
#define AST_CAUSE_UNREGISTERED
Definition: causes.h:153
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition: causes.h:99
#define AST_CAUSE_BUSY
Definition: causes.h:148
#define AST_CAUSE_CONGESTION
Definition: causes.h:152

◆ cdr_object_snapshot_copy()

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 791 of file cdr.c.

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

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

792 {
793  ao2_t_replace(dst->snapshot, src->snapshot, "CDR snapshot copy");
794  strcpy(dst->userfield, src->userfield);
795  dst->flags = src->flags;
796  copy_variables(&dst->variables, &src->variables);
797 }
struct varshead variables
Definition: cdr.c:708
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
#define ao2_t_replace(dst, src, tag)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:503
unsigned int flags
Definition: cdr.c:707
static int copy_variables(struct varshead *to_list, struct varshead *from_list)
Copy variables from one list to another.
Definition: cdr.c:746
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:706

◆ cdr_object_swap_snapshot()

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 1531 of file cdr.c.

References ao2_t_replace, cdr_object_update_cid(), and cdr_object_snapshot::snapshot.

Referenced by base_process_party_a(), bridge_state_process_party_b(), dial_state_process_dial_end(), dial_state_process_party_b(), and single_state_process_dial_begin().

1533 {
1534  cdr_object_update_cid(old_snapshot, new_snapshot);
1535  ao2_t_replace(old_snapshot->snapshot, new_snapshot, "Swap CDR shapshot");
1536 }
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
#define ao2_t_replace(dst, src, tag)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:503
static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Definition: cdr.c:1506

◆ cdr_object_transition_state()

static void cdr_object_transition_state ( struct cdr_object cdr,
struct cdr_object_fn_table fn_table 
)
static

◆ cdr_object_transition_state_init()

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

Definition at line 804 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(), and dialed_pending_state_process_party_a().

805 {
806  CDR_DEBUG("%p - Transitioning CDR for %s from state %s to %s\n",
807  cdr, cdr->party_a.snapshot->base->name,
808  cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
809  cdr->fn_table = fn_table;
810 
811  if (cdr->fn_table->init_function && do_init) {
812  cdr->fn_table->init_function(cdr);
813  }
814 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_a
Definition: cdr.c:713
void(*const init_function)(struct cdr_object *cdr)
An initialization function. This will be called automatically when a cdr_object is switched to this t...
Definition: cdr.c:427
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
const char * name
Name of the subclass.
Definition: cdr.c:418
const ast_string_field name

◆ cdr_object_update_cid()

static void cdr_object_update_cid ( struct cdr_object_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot 
)
static

Definition at line 1506 of file cdr.c.

References ast_channel_snapshot::caller, ast_channel_snapshot_caller::dialed_subaddr, ast_channel_snapshot_caller::dnid, set_variable(), cdr_object_snapshot::snapshot, ast_channel_snapshot_caller::subaddr, and cdr_object_snapshot::variables.

Referenced by cdr_object_swap_snapshot().

1507 {
1508  if (!old_snapshot->snapshot) {
1509  set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
1510  set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
1511  set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
1512  return;
1513  }
1514  if (strcmp(old_snapshot->snapshot->caller->dnid, new_snapshot->caller->dnid)) {
1515  set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
1516  }
1517  if (strcmp(old_snapshot->snapshot->caller->subaddr, new_snapshot->caller->subaddr)) {
1518  set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
1519  }
1520  if (strcmp(old_snapshot->snapshot->caller->dialed_subaddr, new_snapshot->caller->dialed_subaddr)) {
1521  set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
1522  }
1523 }
struct varshead variables
Definition: cdr.c:708
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
static void set_variable(struct varshead *headp, const char *name, const char *value)
Definition: cdr.c:1262
const ast_string_field dialed_subaddr
const ast_string_field subaddr
struct ast_channel_snapshot_caller * caller
const ast_string_field dnid

◆ cdr_object_update_party_b()

static int cdr_object_update_party_b ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 2220 of file cdr.c.

References ast_log, ast_channel_snapshot::base, cdr_object::fn_table, cdr_object::linkedid, LOG_NOTICE, ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, cdr_object::party_b_name, cdr_object_fn_table::process_party_b, and cdr_object_snapshot::snapshot.

Referenced by handle_channel_snapshot_update_message().

2221 {
2222  struct cdr_object *cdr = obj;
2223 
2224  if (cdr->fn_table->process_party_b
2225  && !strcasecmp(cdr->party_b_name, arg)) {
2226  struct ast_channel_snapshot *party_b = data;
2227 
2228  /*
2229  * For sanity's sake we also check the party_b snapshot
2230  * for consistency with the key. The callback needs and
2231  * asserts the snapshot to be this way.
2232  */
2233  if (!cdr->party_b.snapshot
2234  || strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name)) {
2236  "CDR for Party A %s(%s) has inconsistent Party B %s name. Message can be ignored but this shouldn't happen.\n",
2237  cdr->linkedid,
2238  cdr->party_a.snapshot->base->name,
2239  cdr->party_b_name);
2240  return 0;
2241  }
2242 
2243  cdr->fn_table->process_party_b(cdr, party_b);
2244  }
2245  return 0;
2246 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
Structure representing a snapshot of channel state.
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define ast_log
Definition: astobj2.c:42
const ast_string_field linkedid
Definition: cdr.c:734
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
void(*const process_party_b)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party B update for the cdr_object.
Definition: cdr.c:446
#define LOG_NOTICE
Definition: logger.h:263
const ast_string_field party_b_name
Definition: cdr.c:734
const ast_string_field name

◆ cdr_object_update_party_b_userfield_cb()

static int cdr_object_update_party_b_userfield_cb ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Callback used to update the userfield on Party B on all CDRs.

Definition at line 3455 of file cdr.c.

References ast_assert, ast_copy_string(), ast_channel_snapshot::base, party_b_userfield_update::channel_name, cdr_object::fn_table, sip_to_pjsip::info(), ast_channel_snapshot_base::name, cdr_object::next, cdr_object::party_b, cdr_object::party_b_name, cdr_object_snapshot::snapshot, cdr_object_snapshot::userfield, and party_b_userfield_update::userfield.

Referenced by ast_cdr_setuserfield().

3456 {
3457  struct cdr_object *cdr = obj;
3458 
3459  if ((cdr->fn_table != &finalized_state_fn_table || !cdr->next)
3460  && !strcasecmp(cdr->party_b_name, arg)) {
3461  struct party_b_userfield_update *info = data;
3462 
3463  /*
3464  * For sanity's sake we also assert the party_b snapshot
3465  * is consistent with the key.
3466  */
3468  && !strcasecmp(cdr->party_b.snapshot->base->name, info->channel_name));
3469 
3471  sizeof(cdr->party_b.userfield));
3472  }
3473 
3474  return 0;
3475 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
#define ast_assert(a)
Definition: utils.h:695
const char * userfield
Definition: cdr.c:3451
char userfield[AST_MAX_USER_FIELD]
Definition: cdr.c:706
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
const char * channel_name
Definition: cdr.c:3450
An in-memory representation of an active CDR.
Definition: cdr.c:712
def info(msg)
const ast_string_field party_b_name
Definition: cdr.c:734
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const ast_string_field name

◆ cdr_submit_batch()

static void cdr_submit_batch ( int  shutdown)
static

Definition at line 3766 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_debug, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached_background, AST_PTHREADT_NULL, ast_test_flag, batch, BATCH_MODE_SCHEDULER_ONLY, ast_cdr_config::batch_settings, cdr_batch_lock, do_batch_backend_process(), module_config::general, cdr_batch::head, LOG_WARNING, NULL, reset_batch(), and ast_cdr_config::batch_settings::settings.

Referenced by ast_cdr_engine_term(), and submit_scheduled_batch().

3767 {
3768  struct module_config *mod_cfg;
3769  struct cdr_batch_item *oldbatchitems = NULL;
3770  pthread_t batch_post_thread = AST_PTHREADT_NULL;
3771 
3772  /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
3773  if (!batch || !batch->head) {
3774  return;
3775  }
3776 
3777  /* move the old CDRs aside, and prepare a new CDR batch */
3779  oldbatchitems = batch->head;
3780  reset_batch();
3782 
3783  mod_cfg = ao2_global_obj_ref(module_configs);
3784 
3785  /* if configured, spawn a new thread to post these CDRs,
3786  also try to save as much as possible if we are shutting down safely */
3787  if (!mod_cfg
3789  || do_shutdown) {
3790  ast_debug(1, "CDR single-threaded batch processing begins now\n");
3791  do_batch_backend_process(oldbatchitems);
3792  } else {
3793  if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
3794  ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
3795  do_batch_backend_process(oldbatchitems);
3796  } else {
3797  ast_debug(1, "CDR multi-threaded batch processing begins now\n");
3798  }
3799  }
3800 
3801  ao2_cleanup(mod_cfg);
3802 }
static void reset_batch(void)
Definition: cdr.c:3730
static void * do_batch_backend_process(void *data)
Definition: cdr.c:3749
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:274
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:572
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_PTHREADT_NULL
Definition: lock.h:66
struct ast_cdr_config::batch_settings batch_settings
The configuration settings for this module.
Definition: cdr.c:222
static struct cdr_batch * batch
Queued CDR waiting to be batched.
Definition: cdr.c:336
static ast_mutex_t cdr_batch_lock
Lock protecting modifications to the batch queue.
Definition: cdr.c:358
struct ast_flags settings
Definition: cdr.h:269
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct cdr_batch_item * head
Definition: cdr.c:344
struct ast_cdr_config * general
Definition: cdr.c:223
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ cdr_toggle_runtime_options()

static int cdr_toggle_runtime_options ( void  )
static

Checks if CDRs are enabled and enables/disables the necessary options.

Definition at line 4488 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_log, AST_LOG_ERROR, ast_test_flag, CDR_BATCHMODE, cdr_enable_batch_mode(), CDR_ENABLED, create_subscriptions(), destroy_subscriptions(), module_config::general, LOG_NOTICE, and ast_cdr_config::settings.

Referenced by ast_cdr_set_config(), load_module(), and reload_module().

4489 {
4490  struct module_config *mod_cfg;
4491 
4492  mod_cfg = ao2_global_obj_ref(module_configs);
4493  if (mod_cfg
4494  && ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4495  if (create_subscriptions()) {
4497  ast_log(AST_LOG_ERROR, "Failed to create Stasis subscriptions\n");
4498  ao2_cleanup(mod_cfg);
4499  return -1;
4500  }
4501  if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4502  cdr_enable_batch_mode(mod_cfg->general);
4503  } else {
4504  ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
4505  }
4506  } else {
4508  ast_log(LOG_NOTICE, "CDR logging disabled.\n");
4509  }
4510  ao2_cleanup(mod_cfg);
4511 
4512  return mod_cfg ? 0 : -1;
4513 }
struct ast_flags settings
Definition: cdr.h:265
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void destroy_subscriptions(void)
Destroy the active Stasis subscriptions.
Definition: cdr.c:4304
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
static int create_subscriptions(void)
Create the Stasis subcriptions for CDRs.
Definition: cdr.c:4314
The configuration settings for this module.
Definition: cdr.c:222
#define LOG_NOTICE
Definition: logger.h:263
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static void cdr_enable_batch_mode(struct ast_cdr_config *config)
Definition: cdr.c:4416
struct ast_cdr_config * general
Definition: cdr.c:223

◆ check_new_cdr_needed()

static int check_new_cdr_needed ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot 
)
static

Determine if we need to add a new CDR based on snapshots.

Definition at line 2249 of file cdr.c.

References ast_channel_snapshot_dialplan::appl, AST_SOFTHANGUP_HANGUP_EXEC, ast_strlen_zero, ast_test_flag, CDR_END_BEFORE_H_EXTEN, ast_channel_snapshot::dialplan, is_cdr_flag_set(), snapshot_cep_changed(), and ast_channel_snapshot::softhangup_flags.

Referenced by handle_channel_snapshot_update_message().

2251 {
2252  /* If we're dead, we don't need a new CDR */
2253  if (!new_snapshot
2256  return 0;
2257  }
2258 
2259  /* Auto-fall through will increment the priority but have no application */
2260  if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
2261  return 0;
2262  }
2263 
2264  if (old_snapshot && !snapshot_cep_changed(old_snapshot, new_snapshot)) {
2265  return 0;
2266  }
2267 
2268  return 1;
2269 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127
struct ast_channel_snapshot_dialplan * dialplan
#define ast_strlen_zero(foo)
Definition: strings.h:52
const ast_string_field appl
static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Return whether or not a channel has changed its state in the dialplan, subject to endbeforehexten log...
Definition: cdr.c:1148
struct ast_flags softhangup_flags

◆ cli_complete_show()

static char* cli_complete_show ( struct ast_cli_args a)
static

Complete user input for 'cdr show'.

Definition at line 3970 of file cdr.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli_completion_add(), ast_strdup, ast_channel_snapshot::base, ast_channel_snapshot_base::name, NULL, cdr_object::party_a, cdr_object_snapshot::snapshot, and ast_cli_args::word.

Referenced by handle_cli_show().

3971 {
3972  int wordlen = strlen(a->word);
3973  struct ao2_iterator it_cdrs;
3974  struct cdr_object *cdr;
3975 
3976  it_cdrs = ao2_iterator_init(active_cdrs_master, 0);
3977  while ((cdr = ao2_iterator_next(&it_cdrs))) {
3978  if (!strncasecmp(a->word, cdr->party_a.snapshot->base->name, wordlen)) {
3980  ao2_ref(cdr, -1);
3981  break;
3982  }
3983  }
3984  ao2_ref(cdr, -1);
3985  }
3986  ao2_iterator_destroy(&it_cdrs);
3987 
3988  return NULL;
3989 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define ao2_ref(o, delta)
Definition: astobj2.h:464
An in-memory representation of an active CDR.
Definition: cdr.c:712
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
const char * word
Definition: cli.h:163
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2726
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
const ast_string_field name

◆ cli_show_channel()

static void cli_show_channel ( struct ast_cli_args a)
static

Definition at line 4055 of file cdr.c.

References ast_channel_snapshot_base::accountcode, cdr_object::answer, ao2_cleanup, ao2_lock, ao2_unlock, cdr_object::appl, ast_cli_args::argv, ast_callerid_merge(), ast_cli(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_channel_snapshot::base, ast_channel_snapshot::caller, cdr_get_tv(), cdr_object_get_by_name(), cdr_object::data, cdr_object::end, ast_cli_args::fd, FORMAT_STRING, 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, cdr_object_snapshot::snapshot, snapshot_is_dialed(), cdr_object::start, and TITLE_STRING.

Referenced by handle_cli_show().

4056 {
4057  struct cdr_object *it_cdr;
4058  char clid[64];
4059  char start_time_buffer[64];
4060  char answer_time_buffer[64];
4061  char end_time_buffer[64];
4062  const char *channel_name = a->argv[3];
4063  struct cdr_object *cdr;
4064 
4065 #define TITLE_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
4066 #define FORMAT_STRING "%-10.10s %-20.20s %-25.25s %-15.15s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
4067 
4068  cdr = cdr_object_get_by_name(channel_name);
4069  if (!cdr) {
4070  ast_cli(a->fd, "Unknown channel: %s\n", channel_name);
4071  return;
4072  }
4073 
4074  ast_cli(a->fd, "\n");
4075  ast_cli(a->fd, "Call Detail Record (CDR) Information for %s\n", channel_name);
4076  ast_cli(a->fd, "--------------------------------------------------\n");
4077  ast_cli(a->fd, TITLE_STRING, "AccountCode", "CallerID", "Dst. Channel", "LastApp", "Data", "Start", "Answer", "End", "Billsec", "Duration");
4078 
4079  ao2_lock(cdr);
4080  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4081  struct timeval end;
4082 
4083  if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
4084  continue;
4085  }
4086  ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller->name, it_cdr->party_a.snapshot->caller->number, "");
4087  if (ast_tvzero(it_cdr->end)) {
4088  end = ast_tvnow();
4089  } else {
4090  end = it_cdr->end;
4091  }
4092  cdr_get_tv(it_cdr->start, "%T", start_time_buffer, sizeof(start_time_buffer));
4093  cdr_get_tv(it_cdr->answer, "%T", answer_time_buffer, sizeof(answer_time_buffer));
4094  cdr_get_tv(end, "%T", end_time_buffer, sizeof(end_time_buffer));
4095  ast_cli(a->fd, FORMAT_STRING,
4096  it_cdr->party_a.snapshot->base->accountcode,
4097  clid,
4098  it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
4099  it_cdr->appl,
4100  it_cdr->data,
4101  start_time_buffer,
4102  answer_time_buffer,
4103  end_time_buffer,
4104  (long)ast_tvdiff_ms(end, it_cdr->answer) / 1000,
4105  (long)ast_tvdiff_ms(end, it_cdr->start) / 1000);
4106  }
4107  ao2_unlock(cdr);
4108 
4109  ao2_cleanup(cdr);
4110 
4111 #undef FORMAT_STRING
4112 #undef TITLE_STRING
4113 }
struct ast_channel_snapshot_base * base
const ast_string_field name
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
#define FORMAT_STRING
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
const ast_string_field accountcode
struct timeval answer
Definition: cdr.c:719
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_unlock(a)
Definition: astobj2.h:730
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
struct timeval start
Definition: cdr.c:718
char * end
Definition: eagi_proxy.c:73
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
struct cdr_object_snapshot party_a
Definition: cdr.c:713
const ast_string_field appl
Definition: cdr.c:734
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1073
const int fd
Definition: cli.h:159
#define ao2_lock(a)
Definition: astobj2.h:718
static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
Definition: cdr.c:3035
static struct cdr_object * cdr_object_get_by_name(const char *name)
Definition: cdr.c:3312
struct ast_channel_snapshot_caller * caller
const char *const * argv
Definition: cli.h:161
An in-memory representation of an active CDR.
Definition: cdr.c:712
const ast_string_field data
Definition: cdr.c:734
static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
Return whether or not a ast_channel_snapshot is for a channel that was created as the result of a dia...
Definition: cdr.c:1179
struct timeval end
Definition: cdr.c:720
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const ast_string_field number
#define TITLE_STRING
const ast_string_field name

◆ cli_show_channels()

static void cli_show_channels ( struct ast_cli_args a)
static

Definition at line 3991 of file cdr.c.

References cdr_object::answer, ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, cdr_object::appl, ast_cli(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_channel_snapshot::base, cdr_get_tv(), cdr_object::end, ast_cli_args::fd, FORMAT_STRING, cdr_object::last, lock, ast_channel_snapshot_base::name, cdr_object::next, cdr_object::party_a, cdr_object::party_b, SCOPED_AO2LOCK, cdr_object_snapshot::snapshot, snapshot_is_dialed(), cdr_object::start, and TITLE_STRING.

Referenced by handle_cli_show().

3992 {
3993  struct ao2_iterator it_cdrs;
3994  struct cdr_object *cdr;
3995  char start_time_buffer[64];
3996  char answer_time_buffer[64];
3997  char end_time_buffer[64];
3998 
3999 #define TITLE_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8s %-8.8s\n"
4000 #define FORMAT_STRING "%-25.25s %-25.25s %-15.15s %-8.8s %-8.8s %-8.8s %-8.8ld %-8.8ld\n"
4001 
4002  ast_cli(a->fd, "\n");
4003  ast_cli(a->fd, "Channels with Call Detail Record (CDR) Information\n");
4004  ast_cli(a->fd, "--------------------------------------------------\n");
4005  ast_cli(a->fd, TITLE_STRING, "Channel", "Dst. Channel", "LastApp", "Start", "Answer", "End", "Billsec", "Duration");
4006 
4007  it_cdrs = ao2_iterator_init(active_cdrs_master, 0);
4008  for (; (cdr = ao2_iterator_next(&it_cdrs)); ao2_cleanup(cdr)) {
4009  struct cdr_object *it_cdr;
4010  struct timeval start_time = { 0, };
4011  struct timeval answer_time = { 0, };
4012  struct timeval end_time = { 0, };
4013 
4014  SCOPED_AO2LOCK(lock, cdr);
4015 
4016  /* Calculate the start, end, answer, billsec, and duration over the
4017  * life of all of the CDR entries
4018  */
4019  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
4020  if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
4021  continue;
4022  }
4023  if (ast_tvzero(start_time)) {
4024  start_time = it_cdr->start;
4025  }
4026  if (!ast_tvzero(it_cdr->answer) && ast_tvzero(answer_time)) {
4027  answer_time = it_cdr->answer;
4028  }
4029  }
4030 
4031  /* If there was no start time, then all CDRs were for a dialed channel; skip */
4032  if (ast_tvzero(start_time)) {
4033  continue;
4034  }
4035  it_cdr = cdr->last;
4036 
4037  end_time = ast_tvzero(it_cdr->end) ? ast_tvnow() : it_cdr->end;
4038  cdr_get_tv(start_time, "%T", start_time_buffer, sizeof(start_time_buffer));
4039  cdr_get_tv(answer_time, "%T", answer_time_buffer, sizeof(answer_time_buffer));
4040  cdr_get_tv(end_time, "%T", end_time_buffer, sizeof(end_time_buffer));
4041  ast_cli(a->fd, FORMAT_STRING, it_cdr->party_a.snapshot->base->name,
4042  it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
4043  it_cdr->appl,
4044  start_time_buffer,
4045  answer_time_buffer,
4046  end_time_buffer,
4047  ast_tvzero(answer_time) ? 0 : (long)ast_tvdiff_ms(end_time, answer_time) / 1000,
4048  (long)ast_tvdiff_ms(end_time, start_time) / 1000);
4049  }
4050  ao2_iterator_destroy(&it_cdrs);
4051 #undef FORMAT_STRING
4052 #undef TITLE_STRING
4053 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
#define FORMAT_STRING
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct timeval answer
Definition: cdr.c:719
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
struct timeval start
Definition: cdr.c:718
char * end
Definition: eagi_proxy.c:73
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
struct cdr_object_snapshot party_a
Definition: cdr.c:713
const ast_string_field appl
Definition: cdr.c:734
const int fd
Definition: cli.h:159
ast_mutex_t lock
Definition: app_meetme.c:1091
static void cdr_get_tv(struct timeval when, const char *fmt, char *buf, int bufsize)
Definition: cdr.c:3035
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct cdr_object * last
Definition: cdr.c:736
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static int snapshot_is_dialed(struct ast_channel_snapshot *snapshot)
Return whether or not a ast_channel_snapshot is for a channel that was created as the result of a dia...
Definition: cdr.c:1179
struct timeval end
Definition: cdr.c:720
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define TITLE_STRING
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
const ast_string_field name

◆ CONFIG_INFO_CORE()

CONFIG_INFO_CORE ( "cdr"  ,
cfg_info  ,
module_configs  ,
module_config_alloc  ,
files = ACO_FILES(&module_file_conf),
post_apply_config = module_config_post_apply 
)

◆ copy_variables()

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
Return values
Thenumber of copied variables

Definition at line 746 of file cdr.c.

References AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strlen_zero, ast_var_assign, ast_var_name(), ast_var_value(), ast_var_t::entries, and var.

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

747 {
748  struct ast_var_t *variables;
749  struct ast_var_t *newvariable;
750  const char *var;
751  const char *val;
752  int x = 0;
753 
754  AST_LIST_TRAVERSE(from_list, variables, entries) {
755  var = ast_var_name(variables);
756  if (ast_strlen_zero(var)) {
757  continue;
758  }
759  val = ast_var_value(variables);
760  if (ast_strlen_zero(val)) {
761  continue;
762  }
763  newvariable = ast_var_assign(var, val);
764  if (newvariable) {
765  AST_LIST_INSERT_HEAD(to_list, newvariable, entries);
766  ++x;
767  }
768  }
769 
770  return x;
771 }
Definition: ast_expr2.c:325
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
#define var
Definition: ast_expr2f.c:614
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
struct ast_var_t::@249 entries
#define ast_var_assign(name, value)
Definition: chanvars.h:40

◆ create_subscriptions()

static int create_subscriptions ( void  )
static

Create the Stasis subcriptions for CDRs.

Definition at line 4314 of file cdr.c.

References ast_bridge_topic_all(), ast_channel_topic_all(), ast_parking_topic(), and stasis_forward_all().

Referenced by cdr_toggle_runtime_options().

4315 {
4316  if (!cdr_topic) {
4317  return -1;
4318  }
4319 
4321  return 0;
4322  }
4323 
4325  if (!channel_subscription) {
4326  return -1;
4327  }
4329  if (!bridge_subscription) {
4330  return -1;
4331  }
4333  if (!parking_subscription) {
4334  return -1;
4335  }
4336 
4337  return 0;
4338 }
static struct stasis_topic * cdr_topic
The parent topic for all topics we want to aggregate for CDRs.
Definition: cdr.c:383
static struct stasis_forward * bridge_subscription
Our subscription for bridges.
Definition: cdr.c:374
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
struct stasis_topic * ast_parking_topic(void)
accessor for the parking stasis topic
Definition: parking.c:67
static struct stasis_forward * channel_subscription
Our subscription for channels.
Definition: cdr.c:377
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
Definition: stasis.c:1578
static struct stasis_forward * parking_subscription
Our subscription for parking.
Definition: cdr.c:380

◆ destroy_subscriptions()

static void destroy_subscriptions ( void  )
static

Destroy the active Stasis subscriptions.

Definition at line 4304 of file cdr.c.

References stasis_forward_cancel().

Referenced by cdr_toggle_runtime_options(), and unload_module().

4305 {
4309 }
static struct stasis_forward * bridge_subscription
Our subscription for bridges.
Definition: cdr.c:374
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
Definition: stasis.c:1548
static struct stasis_forward * channel_subscription
Our subscription for channels.
Definition: cdr.c:377
static struct stasis_forward * parking_subscription
Our subscription for parking.
Definition: cdr.c:380

◆ dial_state_process_bridge_enter()

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

Definition at line 1880 of file cdr.c.

References ao2_cleanup, ao2_container_count(), ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_string_field_set, ast_channel_snapshot::base, cdr_object::bridge, BRIDGE_ENTER_NO_PARTY_B, BRIDGE_ENTER_OBTAINED_PARTY_B, BRIDGE_ENTER_ONLY_PARTY, cdr_object_finalize(), cdr_object_snapshot_copy(), cdr_object_transition_state(), ast_bridge_snapshot::channels, cdr_object::fn_table, ast_channel_snapshot_base::name, cdr_object::next, OBJ_SEARCH_KEY, cdr_object::party_a, cdr_object::party_b, cdr_object_snapshot::snapshot, and ast_bridge_snapshot::uniqueid.

1881 {
1882  int success = 0;
1883 
1884  ast_string_field_set(cdr, bridge, bridge->uniqueid);
1885 
1886  /* Get parties in the bridge */
1887  if (ao2_container_count(bridge->channels) == 1) {
1888  /* No one in the bridge yet but us! */
1890  return BRIDGE_ENTER_ONLY_PARTY;
1891  }
1892 
1893  /* If we don't have a Party B (originated channel), skip it */
1894  if (cdr->party_b.snapshot) {
1895  struct ao2_iterator it_cdrs;
1896  char *channel_id;
1897 
1898  for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
1899  !success && (channel_id = ao2_iterator_next(&it_cdrs));
1900  ao2_ref(channel_id, -1)) {
1901  struct cdr_object *cand_cdr_master;
1902  struct cdr_object *cand_cdr;
1903 
1904  cand_cdr_master = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
1905  if (!cand_cdr_master) {
1906  continue;
1907  }
1908 
1909  ao2_lock(cand_cdr_master);
1910  for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1911  /* Skip any records that are not in a bridge or in this bridge.
1912  * I'm not sure how that would happen, but it pays to be careful. */
1913  if (cand_cdr->fn_table != &bridge_state_fn_table
1914  || strcmp(cdr->bridge, cand_cdr->bridge)) {
1915  continue;
1916  }
1917 
1918  /* Skip any records that aren't our Party B */
1919  if (strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
1920  continue;
1921  }
1922  cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1923  /* If they have a Party B, they joined up with someone else as their
1924  * Party A. Don't finalize them as they're active. Otherwise, we
1925  * have stolen them so they need to be finalized.
1926  */
1927  if (!cand_cdr->party_b.snapshot) {
1928  cdr_object_finalize(cand_cdr);
1929  }
1930  success = 1;
1931  break;
1932  }
1933  ao2_unlock(cand_cdr_master);
1934  ao2_cleanup(cand_cdr_master);
1935  }
1936  ao2_iterator_destroy(&it_cdrs);
1937  }
1938 
1939  /* We always transition state, even if we didn't get a peer */
1941 
1942  /* Success implies that we have a Party B */
1943  if (success) {
1945  }
1946  return BRIDGE_ENTER_NO_PARTY_B;
1947 }
struct ao2_container * channels
Definition: bridge.h:339
struct ast_channel_snapshot_base * base
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object * next
Definition: cdr.c:735
struct cdr_object_snapshot party_b
Definition: cdr.c:714
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
Copy a snapshot and its details.
Definition: cdr.c:791
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const ast_string_field uniqueid
Definition: bridge.h:336
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct cdr_object_fn_table bridge_state_fn_table
The virtual table for the Bridged state.
Definition: cdr.c:659
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
const ast_string_field bridge
Definition: cdr.c:734
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:821
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ dial_state_process_dial_begin()

static int dial_state_process_dial_begin ( struct cdr_object cdr,
struct ast_channel_snapshot caller,
struct ast_channel_snapshot peer 
)
static

Definition at line 1816 of file cdr.c.

1817 {
1818  /* Don't process a begin dial here. A party A already in the dial state will
1819  * who receives a dial begin for something else will be handled by the
1820  * message router callback and will add a new CDR for the party A */
1821  return 1;
1822 }

◆ dial_state_process_dial_end()

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

Definition at line 1848 of file cdr.c.

References ast_assert, AST_CDR_ANSWERED, ast_channel_snapshot::base, ast_channel_snapshot::caller, cdr_object_swap_snapshot(), cdr_object_transition_state(), dial_status_to_disposition(), cdr_object::disposition, ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, ast_channel_snapshot::peer, and cdr_object_snapshot::snapshot.

1849 {
1850  struct ast_channel_snapshot *party_a;
1851 
1852  if (caller) {
1853  party_a = caller;
1854  } else {
1855  party_a = peer;
1856  }
1857  ast_assert(!strcasecmp(cdr->party_a.snapshot->base->name, party_a->base->name));
1858  cdr_object_swap_snapshot(&cdr->party_a, party_a);
1859 
1860  if (cdr->party_b.snapshot) {
1861  if (strcasecmp(cdr->party_b.snapshot->base->name, peer->base->name)) {
1862  /* Not the status for this CDR - defer back to the message router */
1863  return 1;
1864  }
1865  cdr_object_swap_snapshot(&cdr->party_b, peer);
1866  }
1867 
1868  /* Set the disposition based on the dial string. */
1869  cdr->disposition = dial_status_to_disposition(dial_status);
1870  if (cdr->disposition == AST_CDR_ANSWERED) {
1871  /* Switch to dial pending to wait and see what the caller does */
1873  } else {
1875  }
1876 
1877  return 0;
1878 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
Structure representing a snapshot of channel state.
#define ast_assert(a)
Definition: utils.h:695
struct cdr_object_snapshot party_a
Definition: cdr.c:713
struct cdr_object_fn_table dialed_pending_state_fn_table
The virtual table for the Dialed Pending state.
Definition: cdr.c:637
enum ast_cdr_disposition disposition
Definition: cdr.c:717
struct ast_channel_snapshot_caller * caller
static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_status)
Definition: cdr.c:1828
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Swap an old cdr_object_snapshot&#39;s ast_channel_snapshot for a new ast_channel_snapshot.
Definition: cdr.c:1531
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:821

◆ dial_state_process_party_b()

static void dial_state_process_party_b ( struct cdr_object cdr,
struct ast_channel_snapshot snapshot 
)
static

Definition at line 1802 of file cdr.c.

References ast_assert, AST_FLAG_DEAD, ast_test_flag, ast_channel_snapshot::base, cdr_object_swap_snapshot(), cdr_object_transition_state(), ast_channel_snapshot::flags, ast_channel_snapshot_base::name, NULL, cdr_object::party_b, and cdr_object_snapshot::snapshot.

1803 {
1804  ast_assert(snapshot != NULL);
1806  && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
1807 
1808  cdr_object_swap_snapshot(&cdr->party_b, snapshot);
1809 
1810  /* If party B hangs up, finalize this CDR */
1813  }
1814 }
struct ast_channel_snapshot_base * base
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
struct ast_flags flags
static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Swap an old cdr_object_snapshot&#39;s ast_channel_snapshot for a new ast_channel_snapshot.
Definition: cdr.c:1531
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:821

◆ dial_status_end()

static int dial_status_end ( const char *  dialstatus)
static

Definition at line 2089 of file cdr.c.

Referenced by handle_dial_message().

2090 {
2091  return (strcmp(dialstatus, "RINGING") &&
2092  strcmp(dialstatus, "PROCEEDING") &&
2093  strcmp(dialstatus, "PROGRESS"));
2094 }

◆ dial_status_to_disposition()

static enum ast_cdr_disposition dial_status_to_disposition ( const char *  dial_status)
static

Definition at line 1828 of file cdr.c.

References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_CONGESTION, AST_CDR_FAILED, AST_CDR_NOANSWER, CDR_CONGESTION, and is_cdr_flag_set().

Referenced by dial_state_process_dial_end().

1829 {
1830  if (!strcmp(dial_status, "ANSWER")) {
1831  return AST_CDR_ANSWERED;
1832  } else if (!strcmp(dial_status, "BUSY")) {
1833  return AST_CDR_BUSY;
1834  } else if (!strcmp(dial_status, "CANCEL") || !strcmp(dial_status, "NOANSWER")) {
1835  return AST_CDR_NOANSWER;
1836  } else if (!strcmp(dial_status, "CONGESTION")) {
1838  return AST_CDR_FAILED;
1839  } else {
1840  return AST_CDR_CONGESTION;
1841  }
1842  } else if (!strcmp(dial_status, "FAILED")) {
1843  return AST_CDR_FAILED;
1844  }
1845  return AST_CDR_FAILED;
1846 }
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127

◆ dialed_pending_state_process_bridge_enter()

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

Definition at line 1976 of file cdr.c.

References cdr_object_transition_state(), cdr_object::fn_table, and cdr_object_fn_table::process_bridge_enter.

1977 {
1979  return cdr->fn_table->process_bridge_enter(cdr, bridge, channel);
1980 }
enum process_bridge_enter_results(*const process_bridge_enter)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process the entering of a bridge by this CDR. The purpose of this callback is to have the CDR prepare...
Definition: cdr.c:503
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
struct cdr_object_fn_table dial_state_fn_table
The virtual table for the Dial state.
Definition: cdr.c:604
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821

◆ dialed_pending_state_process_dial_begin()

static int dialed_pending_state_process_dial_begin ( struct cdr_object cdr,
struct ast_channel_snapshot caller,
struct ast_channel_snapshot peer 
)
static

Definition at line 1992 of file cdr.c.

References cdr_object_transition_state().

1993 {
1995 
1996  /* Ask for a new CDR */
1997  return 1;
1998 }
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821

◆ dialed_pending_state_process_parking_bridge_enter()

static int dialed_pending_state_process_parking_bridge_enter ( struct cdr_object cdr,
struct ast_bridge_snapshot bridge,
struct ast_channel_snapshot channel 
)
static

Definition at line 1982 of file cdr.c.

References cdr_object_transition_state(), cdr_object::party_b, and cdr_object_snapshot::snapshot.

1983 {
1984  if (cdr->party_b.snapshot) {
1985  /* We can't handle this as we have a Party B - ask for a new one */
1986  return 1;
1987  }
1989  return 0;
1990 }
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct cdr_object_fn_table parked_state_fn_table
The virtual table for the Parked state.
Definition: cdr.c:678
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821

◆ dialed_pending_state_process_party_a()

static int dialed_pending_state_process_party_a ( struct cdr_object cdr,
struct ast_channel_snapshot snapshot 
)
static

Definition at line 1951 of file cdr.c.

References base_process_party_a(), cdr_object_transition_state(), cdr_object_transition_state_init(), cdr_object::fn_table, cdr_object::party_a, cdr_object::party_b, cdr_object_fn_table::process_party_a, cdr_object_snapshot::snapshot, and snapshot_cep_changed().

1952 {
1953  /* If we get a CEP change, we're executing dialplan. If we have a Party B
1954  * that means we need a new CDR; otherwise, switch us over to single.
1955  */
1956  if (snapshot_cep_changed(cdr->party_a.snapshot, snapshot)) {
1957  if (cdr->party_b.snapshot) {
1959  cdr->fn_table->process_party_a(cdr, snapshot);
1960  return 1;
1961  } else {
1962  /* The CDR does not need to be reinitialized when transitioning
1963  * to its single state as this would overwrite the start time,
1964  * causing potentially both the answer and the start time to be
1965  * the same which is incorrect.
1966  */
1968  cdr->fn_table->process_party_a(cdr, snapshot);
1969  return 0;
1970  }
1971  }
1972  base_process_party_a(cdr, snapshot);
1973  return 0;
1974 }
static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:1540
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
int(*const process_party_a)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party A update for the cdr_object.
Definition: cdr.c:437
struct cdr_object_snapshot party_a
Definition: cdr.c:713
static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Return whether or not a channel has changed its state in the dialplan, subject to endbeforehexten log...
Definition: cdr.c:1148
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
static void cdr_object_transition_state_init(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table, int do_init)
Transition a cdr_object to a new state with initiation flag.
Definition: cdr.c:804
struct cdr_object_fn_table single_state_fn_table
The virtual table for the Single state.
Definition: cdr.c:573
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821

◆ do_batch_backend_process()

static void* do_batch_backend_process ( void *  data)
static

Definition at line 3749 of file cdr.c.

References ast_cdr_free(), ast_free, cdr_batch_item::cdr, cdr_batch_item::next, NULL, and post_cdr().

Referenced by cdr_submit_batch().

3750 {
3751  struct cdr_batch_item *processeditem;
3752  struct cdr_batch_item *batchitem = data;
3753 
3754  /* Push each CDR into storage mechanism(s) and free all the memory */
3755  while (batchitem) {
3756  post_cdr(batchitem->cdr);
3757  ast_cdr_free(batchitem->cdr);
3758  processeditem = batchitem;
3759  batchitem = batchitem->next;
3760  ast_free(processeditem);
3761  }
3762 
3763  return NULL;
3764 }
static void post_cdr(struct ast_cdr *cdr)
Definition: cdr.c:3508
#define NULL
Definition: resample.c:96
struct ast_cdr * cdr
Definition: cdr.c:337
void ast_cdr_free(struct ast_cdr *cdr)
Free a CDR record.
Definition: cdr.c:3411
struct cdr_batch_item * next
Definition: cdr.c:338
Queued CDR waiting to be batched.
Definition: cdr.c:336
#define ast_free(a)
Definition: astmm.h:182

◆ do_cdr()

static void* do_cdr ( void *  data)
static

Definition at line 3903 of file cdr.c.

References ast_cond_timedwait, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_samp2tv(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), ast_tvnow(), cdr_pending_cond, cdr_pending_lock, and NULL.

Referenced by cdr_enable_batch_mode().

3904 {
3905  struct timespec timeout;
3906  int schedms;
3907  int numevents = 0;
3908 
3909  for (;;) {
3910  struct timeval now;
3911  schedms = ast_sched_wait(sched);
3912  /* this shouldn't happen, but provide a 1 second default just in case */
3913  if (schedms < 0)
3914  schedms = 1000;
3915  now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
3916  timeout.tv_sec = now.tv_sec;
3917  timeout.tv_nsec = now.tv_usec * 1000;
3918  /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
3921  numevents = ast_sched_runq(sched);
3923  ast_debug(2, "Processed %d CDR batches from the run queue\n", numevents);
3924  }
3925 
3926  return NULL;
3927 }
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
Definition: sched.c:755
static int timeout
Definition: cdr_mysql.c:86
Definition: sched.c:76
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static ast_mutex_t cdr_pending_lock
These are used to wake up the CDR thread when there&#39;s work to do.
Definition: cdr.c:361
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
static ast_cond_t cdr_pending_cond
Definition: cdr.c:362
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
Definition: sched.c:431
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ filter_bridge_messages()

static int filter_bridge_messages ( struct ast_bridge_snapshot bridge)
static

Filter bridge messages based on bridge technology.

Definition at line 2386 of file cdr.c.

References ast_bridge_snapshot::subclass, and ast_bridge_snapshot::technology.

Referenced by handle_bridge_enter_message(), and handle_bridge_leave_message().

2387 {
2388  /* Ignore holding bridge technology messages. We treat this simply as an application
2389  * that a channel enters into.
2390  */
2391  if (!strcmp(bridge->technology, "holding_bridge") && strcmp(bridge->subclass, "parking")) {
2392  return 1;
2393  }
2394  return 0;
2395 }
const ast_string_field technology
Definition: bridge.h:336
const ast_string_field subclass
Definition: bridge.h:336

◆ filter_channel_snapshot()

static int filter_channel_snapshot ( struct ast_channel_snapshot snapshot)
static

Definition at line 2064 of file cdr.c.

References AST_CHAN_TP_INTERNAL, ast_channel_snapshot::base, and ast_channel_snapshot_base::tech_properties.

Referenced by filter_channel_snapshot_message(), handle_bridge_enter_message(), handle_bridge_leave_message(), handle_dial_message(), and handle_parked_call_message().

2065 {
2066  return snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL;
2067 }
struct ast_channel_snapshot_base * base
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:972

◆ filter_channel_snapshot_message()

static int filter_channel_snapshot_message ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot 
)
static

Definition at line 2073 of file cdr.c.

References filter_channel_snapshot().

Referenced by handle_channel_snapshot_update_message().

2075 {
2076  int ret = 0;
2077 
2078  /* Drop cache updates from certain channel technologies */
2079  if (old_snapshot) {
2080  ret |= filter_channel_snapshot(old_snapshot);
2081  }
2082  if (new_snapshot) {
2083  ret |= filter_channel_snapshot(new_snapshot);
2084  }
2085 
2086  return ret;
2087 }
static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2064

◆ finalize_batch_mode()

static void finalize_batch_mode ( void  )
static

Definition at line 4277 of file cdr.c.

References ast_cdr_engine_term(), ast_cond_destroy, AST_PTHREADT_NULL, cdr_pending_cond, cdr_thread, and NULL.

Referenced by cdr_engine_shutdown(), and reload_module().

4278 {
4279  if (cdr_thread == AST_PTHREADT_NULL) {
4280  return;
4281  }
4282  /* wake up the thread so it will exit */
4283  pthread_cancel(cdr_thread);
4284  pthread_kill(cdr_thread, SIGURG);
4285  pthread_join(cdr_thread, NULL);
4289 }
#define NULL
Definition: resample.c:96
void ast_cdr_engine_term(void)
Definition: cdr.c:4577
#define AST_PTHREADT_NULL
Definition: lock.h:66
static ast_cond_t cdr_pending_cond
Definition: cdr.c:362
#define ast_cond_destroy(cond)
Definition: lock.h:200
static pthread_t cdr_thread
Definition: cdr.c:355

◆ finalized_state_init_function()

static void finalized_state_init_function ( struct cdr_object cdr)
static

Definition at line 2044 of file cdr.c.

References cdr_object_finalize().

2045 {
2046  cdr_object_finalize(cdr);
2047 }
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440

◆ finalized_state_process_party_a()

static int finalized_state_process_party_a ( struct cdr_object cdr,
struct ast_channel_snapshot snapshot 
)
static

Definition at line 2049 of file cdr.c.

References AST_SOFTHANGUP_HANGUP_EXEC, ast_test_flag, CDR_END_BEFORE_H_EXTEN, is_cdr_flag_set(), and ast_channel_snapshot::softhangup_flags.

2050 {
2053  return 0;
2054  }
2055 
2056  /* Indicate that, if possible, we should get a new CDR */
2057  return 1;
2058 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127
struct ast_flags softhangup_flags

◆ free_variables()

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 777 of file cdr.c.

References AST_LIST_REMOVE_HEAD, ast_var_delete(), and ast_var_t::entries.

Referenced by ast_cdr_fork(), and ast_cdr_free().

778 {
779  struct ast_var_t *vardata;
780 
781  while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) {
782  ast_var_delete(vardata);
783  }
784 }
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
struct ast_var_t::@249 entries

◆ handle_bridge_enter_message()

static void handle_bridge_enter_message ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 2708 of file cdr.c.

References ao2_cleanup, ao2_find, ast_assert, ast_log, AST_LOG_WARNING, ast_channel_snapshot::base, ast_bridge_blob::bridge, CDR_DEBUG, ast_bridge_blob::channel, filter_bridge_messages(), filter_channel_snapshot(), handle_parking_bridge_enter_message(), handle_standard_bridge_enter_message(), ast_channel_snapshot_base::name, OBJ_SEARCH_KEY, stasis_message_data(), stasis_message_timestamp(), ast_bridge_snapshot::subclass, ast_channel_snapshot_base::uniqueid, and update().

Referenced by load_module().

2710 {
2711  struct ast_bridge_blob *update = stasis_message_data(message);
2712  struct ast_bridge_snapshot *bridge = update->bridge;
2713  struct ast_channel_snapshot *channel = update->channel;
2714  struct cdr_object *cdr;
2715 
2716  if (filter_bridge_messages(bridge)) {
2717  return;
2718  }
2719 
2720  if (filter_channel_snapshot(channel)) {
2721  return;
2722  }
2723 
2724  CDR_DEBUG("Bridge Enter message for channel %s: %u.%08u\n",
2725  channel->base->name,
2726  (unsigned int)stasis_message_timestamp(message)->tv_sec,
2727  (unsigned int)stasis_message_timestamp(message)->tv_usec);
2728 
2730  if (!cdr) {
2731  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2732  ast_assert(0);
2733  return;
2734  }
2735 
2736  if (!strcmp(bridge->subclass, "parking")) {
2737  handle_parking_bridge_enter_message(cdr, bridge, channel, stasis_message_timestamp(message));
2738  } else {
2739  handle_standard_bridge_enter_message(cdr, bridge, channel, stasis_message_timestamp(message));
2740  }
2741  ao2_cleanup(cdr);
2742 }
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:1105
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition: codec_g726.c:367
static void handle_parking_bridge_enter_message(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel, const struct timeval *event_time)
Handle entering into a parking bridge.
Definition: cdr.c:2586
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:322
#define AST_LOG_WARNING
Definition: logger.h:279
Structure representing a snapshot of channel state.
const ast_string_field uniqueid
#define ast_assert(a)
Definition: utils.h:695
Definition: muted.c:95
static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2064
struct ast_bridge_snapshot * bridge
#define ast_log
Definition: astobj2.c:42
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
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:2386
Blob of data associated with a bridge.
An in-memory representation of an active CDR.
Definition: cdr.c:712
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:365
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static void handle_standard_bridge_enter_message(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel, const struct timeval *event_time)
Handle a bridge enter message for a &#39;normal&#39; bridge.
Definition: cdr.c:2627
const ast_string_field subclass
Definition: bridge.h:336
const ast_string_field name

◆ handle_bridge_leave_message()

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
topicThe topic this message was published for
messageThe message - hopefully a bridge one!

Definition at line 2404 of file cdr.c.

References ao2_callback_data, ao2_cleanup, ao2_find, ao2_lock, ao2_unlock, ast_assert, ast_log, AST_LOG_WARNING, ast_string_field_set, ast_channel_snapshot::base, ast_bridge_blob::bridge, bridge_leave_data::bridge, CDR_DEBUG, cdr_object_party_b_left_bridge_cb(), ast_bridge_blob::channel, bridge_leave_data::channel, filter_bridge_messages(), filter_channel_snapshot(), cdr_object::fn_table, cdr_object::lastevent, bridge_leave_data::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, ast_channel_snapshot_base::uniqueid, and update().

Referenced by load_module().

2406 {
2407  struct ast_bridge_blob *update = stasis_message_data(message);
2408  struct ast_bridge_snapshot *bridge = update->bridge;
2409  struct ast_channel_snapshot *channel = update->channel;
2410  struct cdr_object *cdr;
2411  struct cdr_object *it_cdr;
2412  struct bridge_leave_data leave_data = {
2413  .bridge = bridge,
2414  .channel = channel,
2415  .lastevent = stasis_message_timestamp(message)
2416  };
2417  int left_bridge = 0;
2418 
2419  if (filter_bridge_messages(bridge)) {
2420  return;
2421  }
2422 
2423  if (filter_channel_snapshot(channel)) {
2424  return;
2425  }
2426 
2427  CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n",
2428  channel->base->name,
2429  (unsigned int)leave_data.lastevent->tv_sec,
2430  (unsigned int)leave_data.lastevent->tv_usec);
2431 
2433  if (!cdr) {
2434  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2435  ast_assert(0);
2436  return;
2437  }
2438 
2439  /* Party A */
2440  ao2_lock(cdr);
2441  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2442  it_cdr->lastevent = *leave_data.lastevent;
2443  if (!it_cdr->fn_table->process_bridge_leave) {
2444  continue;
2445  }
2446  CDR_DEBUG("%p - Processing Bridge Leave for %s\n",
2447  it_cdr, channel->base->name);
2448  if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
2449  ast_string_field_set(it_cdr, bridge, "");
2450  left_bridge = 1;
2451  }
2452  }
2453  ao2_unlock(cdr);
2454 
2455  /* Party B */
2456  if (left_bridge
2457  && strcmp(bridge->subclass, "parking")) {
2459  cdr_object_party_b_left_bridge_cb, (char *) leave_data.channel->base->name,
2460  &leave_data);
2461  }
2462 
2463  ao2_cleanup(cdr);
2464 }
struct ast_bridge_snapshot * bridge
Definition: cdr.c:2355
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:1105
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition: codec_g726.c:367
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:322
#define AST_LOG_WARNING
Definition: logger.h:279
struct cdr_object * next
Definition: cdr.c:735
Structure representing a snapshot of channel state.
const ast_string_field uniqueid
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
Definition: muted.c:95
static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2064
struct ast_channel_snapshot * channel
Definition: cdr.c:2356
struct ast_bridge_snapshot * bridge
#define ast_log
Definition: astobj2.c:42
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
#define ao2_lock(a)
Definition: astobj2.h:718
static int filter_bridge_messages(struct ast_bridge_snapshot *bridge)
Filter bridge messages based on bridge technology.
Definition: cdr.c:2386
Blob of data associated with a bridge.
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
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:365
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
struct timeval lastevent
Definition: cdr.c:721
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, void *data, int flags)
Callback used to notify CDRs of a Party B leaving the bridge.
Definition: cdr.c:2361
const struct timeval * lastevent
Definition: cdr.c:2357
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * active_cdrs_all
A container of all active CDRs with a Party B indexed by Party B channel name.
Definition: cdr.c:368
int(*const process_bridge_leave)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process the leaving of a bridge by this CDR.
Definition: cdr.c:533
const ast_string_field subclass
Definition: bridge.h:336
const ast_string_field name
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ handle_bridge_pairings()

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 2561 of file cdr.c.

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

Referenced by handle_standard_bridge_enter_message().

2562 {
2563  struct ao2_iterator it_channels;
2564  char *channel_id;
2565 
2566  it_channels = ao2_iterator_init(bridge->channels, 0);
2567  while ((channel_id = ao2_iterator_next(&it_channels))) {
2568  struct cdr_object *cand_cdr;
2569 
2570  cand_cdr = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
2571  if (cand_cdr) {
2572  bridge_candidate_process(cdr, cand_cdr);
2573  ao2_ref(cand_cdr, -1);
2574  }
2575 
2576  ao2_ref(channel_id, -1);
2577  }
2578  ao2_iterator_destroy(&it_channels);
2579 }
struct ao2_container * channels
Definition: bridge.h:339
static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
Process a single bridge_candidate.
Definition: cdr.c:2503
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
An in-memory representation of an active CDR.
Definition: cdr.c:712
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ handle_cdr_sync_message()

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
topicThe topic this message was published for
messageA blank ao2 object

Definition at line 2820 of file cdr.c.

Referenced by load_module().

2822 {
2823  return;
2824 }

◆ handle_channel_snapshot_update_message()

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
topicThe topic this message was published for
messageThe message

Definition at line 2278 of file cdr.c.

References ao2_callback_data, ao2_cleanup, ao2_find, ao2_link, ao2_lock, ao2_unlink, ao2_unlock, ast_assert, AST_FLAG_DEAD, ast_log, AST_LOG_WARNING, ast_test_flag, ast_channel_snapshot::base, cdr_all_unlink(), CDR_DEBUG, cdr_object_alloc(), cdr_object_create_and_append(), cdr_object_dispatch(), cdr_object_finalize(), cdr_object_finalize_party_b(), cdr_object_update_party_b(), check_new_cdr_needed(), filter_channel_snapshot_message(), ast_channel_snapshot::flags, cdr_object::fn_table, 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, stasis_message_data(), stasis_message_timestamp(), ast_channel_snapshot_base::uniqueid, and update().

Referenced by load_module().

2279 {
2280  struct cdr_object *cdr;
2282  struct cdr_object *it_cdr;
2283 
2285  return;
2286  }
2287 
2288  if (update->new_snapshot && !update->old_snapshot) {
2289  cdr = cdr_object_alloc(update->new_snapshot, stasis_message_timestamp(message));
2290  if (!cdr) {
2291  return;
2292  }
2293  cdr->is_root = 1;
2295  } else {
2297  }
2298 
2299  /* Handle Party A */
2300  if (!cdr) {
2301  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->base->name);
2302  ast_assert(0);
2303  } else {
2304  int all_reject = 1;
2305 
2306  ao2_lock(cdr);
2307  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2308  it_cdr->lastevent = *stasis_message_timestamp(message);
2309  if (!it_cdr->fn_table->process_party_a) {
2310  continue;
2311  }
2312  all_reject &= it_cdr->fn_table->process_party_a(it_cdr, update->new_snapshot);
2313  }
2314  if (all_reject && check_new_cdr_needed(update->old_snapshot, update->new_snapshot)) {
2315  /* We're not hung up and we have a new snapshot - we need a new CDR */
2316  struct cdr_object *new_cdr;
2317 
2318  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
2319  if (new_cdr) {
2320  new_cdr->fn_table->process_party_a(new_cdr, update->new_snapshot);
2321  }
2322  }
2323  ao2_unlock(cdr);
2324  }
2325 
2326  if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2327  ao2_lock(cdr);
2328  CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->base->name);
2329  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2330  it_cdr->lastevent = *stasis_message_timestamp(message);
2331  cdr_object_finalize(it_cdr);
2332  }
2333  cdr_object_dispatch(cdr);
2334  ao2_unlock(cdr);
2335 
2336  cdr_all_unlink(cdr);
2338  }
2339 
2340  /* Handle Party B */
2341  if (update->new_snapshot) {
2343  cdr_object_update_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2344  }
2345 
2346  if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
2348  cdr_object_finalize_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
2349  }
2350 
2351  ao2_cleanup(cdr);
2352 }
struct ast_channel_snapshot_base * base
static void cdr_all_unlink(struct cdr_object *cdr)
Definition: cdr.c:972
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition: codec_g726.c:367
#define AST_LOG_WARNING
Definition: logger.h:279
struct cdr_object * next
Definition: cdr.c:735
int(*const process_party_a)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party A update for the cdr_object.
Definition: cdr.c:437
static struct cdr_object * cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
cdr_object constructor
Definition: cdr.c:1039
const ast_string_field uniqueid
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
Structure representing a change of snapshot of channel state.
int is_root
Definition: cdr.c:737
#define ast_log
Definition: astobj2.c:42
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
static void cdr_object_dispatch(struct cdr_object *cdr)
Dispatch a CDR.
Definition: cdr.c:1386
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
#define ao2_lock(a)
Definition: astobj2.h:718
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
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:365
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
struct timeval lastevent
Definition: cdr.c:721
static int cdr_object_update_party_b(void *obj, void *arg, void *data, int flags)
Definition: cdr.c:2220
struct ast_channel_snapshot * new_snapshot
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct ast_channel_snapshot * old_snapshot
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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:368
static struct cdr_object * cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
Create a new cdr_object and append it to an existing chain.
Definition: cdr.c:1075
static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Determine if we need to add a new CDR based on snapshots.
Definition: cdr.c:2249
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
static int cdr_object_finalize_party_b(void *obj, void *arg, void *data, int flags)
Definition: cdr.c:2196
const ast_string_field name
static int filter_channel_snapshot_message(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Definition: cdr.c:2073
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ handle_cli_debug()

static char* handle_cli_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3929 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_cli_args::argc, ast_cli_args::argv, ast_clear_flag, ast_cli(), ast_set_flag, ast_test_flag, CDR_DEBUG, cdr_set_debug_mode, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, module_config::general, NULL, ast_cdr_config::settings, and ast_cli_entry::usage.

3930 {
3931  struct module_config *mod_cfg;
3932 
3933  switch (cmd) {
3934  case CLI_INIT:
3935  e->command = "cdr set debug [on|off]";
3936  e->usage = "Enable or disable extra debugging in the CDR Engine. Note\n"
3937  "that this will dump debug information to the VERBOSE setting\n"
3938  "and should only be used when debugging information from the\n"
3939  "CDR engine is needed.\n";
3940  return NULL;
3941  case CLI_GENERATE:
3942  return NULL;
3943  }
3944 
3945  if (a->argc != 4) {
3946  return CLI_SHOWUSAGE;
3947  }
3948 
3949  mod_cfg = ao2_global_obj_ref(module_configs);
3950  if (!mod_cfg) {
3951  ast_cli(a->fd, "Could not set CDR debugging mode\n");
3952  return CLI_SUCCESS;
3953  }
3954  if (!strcasecmp(a->argv[3], "on")
3955  && !ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3956  ast_set_flag(&mod_cfg->general->settings, CDR_DEBUG);
3957  ast_cli(a->fd, "CDR debugging enabled\n");
3958  } else if (!strcasecmp(a->argv[3], "off")
3959  && ast_test_flag(&mod_cfg->general->settings, CDR_DEBUG)) {
3961  ast_cli(a->fd, "CDR debugging disabled\n");
3962  }
3963  cdr_set_debug_mode(mod_cfg);
3964  ao2_cleanup(mod_cfg);
3965 
3966  return CLI_SUCCESS;
3967 }
#define cdr_set_debug_mode(mod_cfg)
Definition: cdr.c:203
struct ast_flags settings
Definition: cdr.h:265
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
const int fd
Definition: cli.h:159
The configuration settings for this module.
Definition: cdr.c:222
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
#define ast_clear_flag(p, flag)
Definition: utils.h:77
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_cdr_config * general
Definition: cdr.c:223

◆ handle_cli_show()

static char* handle_cli_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4115 of file cdr.c.

References ast_cli_args::argc, cli_complete_show(), CLI_GENERATE, CLI_INIT, cli_show_channel(), cli_show_channels(), CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

4116 {
4117  switch (cmd) {
4118  case CLI_INIT:
4119  e->command = "cdr show active";
4120  e->usage =
4121  "Usage: cdr show active [channel]\n"
4122  " Displays a summary of all Call Detail Records when [channel]\n"
4123  " is omitted; displays all of the Call Detail Records\n"
4124  " currently in flight for a given [channel] when [channel] is\n"
4125  " specified.\n\n"
4126  " Note that this will not display Call Detail Records that\n"
4127  " have already been dispatched to a backend storage, nor for\n"
4128  " channels that are no longer active.\n";
4129  return NULL;
4130  case CLI_GENERATE:
4131  return cli_complete_show(a);
4132  }
4133 
4134  if (a->argc > 4) {
4135  return CLI_SHOWUSAGE;
4136  } else if (a->argc < 4) {
4137  cli_show_channels(a);
4138  } else {
4139  cli_show_channel(a);
4140  }
4141 
4142  return CLI_SUCCESS;
4143 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static void cli_show_channel(struct ast_cli_args *a)
Definition: cdr.c:4055
static char * cli_complete_show(struct ast_cli_args *a)
Complete user input for &#39;cdr show&#39;.
Definition: cdr.c:3970
static void cli_show_channels(struct ast_cli_args *a)
Definition: cdr.c:3991

◆ handle_cli_status()

static char* handle_cli_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4145 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_cli_args::argc, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_sched_when(), ast_test_flag, batch, BATCH_MODE_SAFE_SHUTDOWN, BATCH_MODE_SCHEDULER_ONLY, ast_cdr_config::batch_settings, CDR_BATCHMODE, CDR_CONGESTION, CDR_ENABLED, cdr_sched, CDR_UNANSWERED, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ESS, ast_cli_args::fd, module_config::general, cdr_beitem::name, NULL, ast_cdr_config::batch_settings::settings, ast_cdr_config::settings, ast_cdr_config::batch_settings::size, cdr_batch::size, ast_cdr_config::batch_settings::time, and ast_cli_entry::usage.

4146 {
4147  struct cdr_beitem *beitem = NULL;
4148  struct module_config *mod_cfg;
4149  int cnt = 0;
4150  long nextbatchtime = 0;
4151 
4152  switch (cmd) {
4153  case CLI_INIT:
4154  e->command = "cdr show status";
4155  e->usage =
4156  "Usage: cdr show status\n"
4157  " Displays the Call Detail Record engine system status.\n";
4158  return NULL;
4159  case CLI_GENERATE:
4160  return NULL;
4161  }
4162 
4163  if (a->argc > 3) {
4164  return CLI_SHOWUSAGE;
4165  }
4166 
4167  mod_cfg = ao2_global_obj_ref(module_configs);
4168  if (!mod_cfg) {
4169  return CLI_FAILURE;
4170  }
4171 
4172  ast_cli(a->fd, "\n");
4173  ast_cli(a->fd, "Call Detail Record (CDR) settings\n");
4174  ast_cli(a->fd, "----------------------------------\n");
4175  ast_cli(a->fd, " Logging: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED) ? "Enabled" : "Disabled");
4176  ast_cli(a->fd, " Mode: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE) ? "Batch" : "Simple");
4177  if (ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4178  ast_cli(a->fd, " Log unanswered calls: %s\n", ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) ? "Yes" : "No");
4179  ast_cli(a->fd, " Log congestion: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION) ? "Yes" : "No");
4180  if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4181  ast_cli(a->fd, "* Batch Mode Settings\n");
4182  ast_cli(a->fd, " -------------------\n");
4183  if (batch)
4184  cnt = batch->size;
4185  if (cdr_sched > -1)
4186  nextbatchtime = ast_sched_when(sched, cdr_sched);
4187  ast_cli(a->fd, " Safe shutdown: %s\n", ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SAFE_SHUTDOWN) ? "Enabled" : "Disabled");
4188  ast_cli(a->fd, " Threading model: %s\n", ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SCHEDULER_ONLY) ? "Scheduler only" : "Scheduler plus separate threads");
4189  ast_cli(a->fd, " Current batch size: %d record%s\n", cnt, ESS(cnt));
4190  ast_cli(a->fd, " Maximum batch size: %u record%s\n", mod_cfg->general->batch_settings.size, ESS(mod_cfg->general->batch_settings.size));
4191  ast_cli(a->fd, " Maximum batch time: %u second%s\n", mod_cfg->general->batch_settings.time, ESS(mod_cfg->general->batch_settings.time));
4192  ast_cli(a->fd, " Next batch processing time: %ld second%s\n\n", nextbatchtime, ESS(nextbatchtime));
4193  }
4194  ast_cli(a->fd, "* Registered Backends\n");
4195  ast_cli(a->fd, " -------------------\n");
4197  if (AST_RWLIST_EMPTY(&be_list)) {
4198  ast_cli(a->fd, " (none)\n");
4199  } else {
4200  AST_RWLIST_TRAVERSE(&be_list, beitem, list) {
4201  ast_cli(a->fd, " %s%s\n", beitem->name, beitem->suspended ? " (suspended) " : "");
4202  }
4203  }
4205  ast_cli(a->fd, "\n");
4206  }
4207 
4208  ao2_cleanup(mod_cfg);
4209  return CLI_SUCCESS;
4210 }
struct ast_flags settings
Definition: cdr.h:265
#define ast_test_flag(p, flag)
Definition: utils.h:63
const int argc
Definition: cli.h:160
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: sched.c:76
Definition: cli.h:152
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
Registration object for CDR backends.
Definition: cdr.c:321
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
struct ast_cdr_config::batch_settings batch_settings
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
The configuration settings for this module.
Definition: cdr.c:222
static struct cdr_batch * batch
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
#define CLI_SHOWUSAGE
Definition: cli.h:45
char name[20]
Definition: cdr.c:322
static int cdr_sched
Definition: cdr.c:353
long ast_sched_when(struct ast_sched_context *con, int id)
Returns the number of seconds before an event takes place.
Definition: sched.c:814
#define CLI_FAILURE
Definition: cli.h:46
#define ESS(x)
Definition: cli.h:59
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
struct ast_flags settings
Definition: cdr.h:269
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_cdr_config * general
Definition: cdr.c:223
int size
Definition: cdr.c:343
List of registered backends.
Definition: cdr.c:330

◆ handle_cli_submit()

static char* handle_cli_submit ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 4212 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_cli_args::argc, ast_cli(), ast_test_flag, CDR_BATCHMODE, CDR_ENABLED, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, module_config::general, NULL, ast_cdr_config::settings, start_batch_mode(), and ast_cli_entry::usage.

4213 {
4214  struct module_config *mod_cfg;
4215 
4216  switch (cmd) {
4217  case CLI_INIT:
4218  e->command = "cdr submit";
4219  e->usage =
4220  "Usage: cdr submit\n"
4221  "Posts all pending batched CDR data to the configured CDR\n"
4222  "backend engine modules.\n";
4223  return NULL;
4224  case CLI_GENERATE:
4225  return NULL;
4226  }
4227  if (a->argc > 2) {
4228  return CLI_SHOWUSAGE;
4229  }
4230 
4231  mod_cfg = ao2_global_obj_ref(module_configs);
4232  if (!mod_cfg) {
4233  return CLI_FAILURE;
4234  }
4235 
4236  if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
4237  ast_cli(a->fd, "Cannot submit CDR batch: CDR engine disabled.\n");
4238  } else if (!ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4239  ast_cli(a->fd, "Cannot submit CDR batch: batch mode not enabled.\n");
4240  } else {
4241  start_batch_mode();
4242  ast_cli(a->fd, "Submitted CDRs to backend engines for processing. This may take a while.\n");
4243  }
4244  ao2_cleanup(mod_cfg);
4245 
4246  return CLI_SUCCESS;
4247 }
struct ast_flags settings
Definition: cdr.h:265
#define ast_test_flag(p, flag)
Definition: utils.h:63
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
The configuration settings for this module.
Definition: cdr.c:222
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
static void start_batch_mode(void)
Definition: cdr.c:3825
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_cdr_config * general
Definition: cdr.c:223

◆ handle_dial_message()

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
topicThe topic this message was published for
messageThe message

Definition at line 2105 of file cdr.c.

References ao2_cleanup, ao2_find, ao2_lock, ao2_unlock, ast_assert, ast_json_object_get(), ast_json_string_get(), ast_log, AST_LOG_WARNING, ast_multi_channel_blob_get_channel(), ast_multi_channel_blob_get_json(), ast_strlen_zero, ast_channel_snapshot::base, ast_channel_snapshot::caller, CDR_DEBUG, cdr_object_create_and_append(), dial_status_end(), filter_channel_snapshot(), cdr_object::fn_table, cdr_object::lastevent, ast_channel_snapshot_base::name, cdr_object::next, NULL, 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.

Referenced by load_module().

2106 {
2107  struct cdr_object *cdr;
2108  struct ast_multi_channel_blob *payload = stasis_message_data(message);
2109  struct ast_channel_snapshot *caller;
2110  struct ast_channel_snapshot *peer;
2111  struct cdr_object *it_cdr;
2112  struct ast_json *dial_status_blob;
2113  const char *dial_status = NULL;
2114  int res = 1;
2115 
2116  caller = ast_multi_channel_blob_get_channel(payload, "caller");
2117  peer = ast_multi_channel_blob_get_channel(payload, "peer");
2118  if (!peer && !caller) {
2119  return;
2120  }
2121 
2122  if (peer && filter_channel_snapshot(peer)) {
2123  return;
2124  }
2125 
2126  if (caller && filter_channel_snapshot(caller)) {
2127  return;
2128  }
2129 
2130  dial_status_blob = ast_json_object_get(ast_multi_channel_blob_get_json(payload), "dialstatus");
2131  if (dial_status_blob) {
2132  dial_status = ast_json_string_get(dial_status_blob);
2133  }
2134 
2135  CDR_DEBUG("Dial %s message for %s, %s: %u.%08u\n",
2136  ast_strlen_zero(dial_status) ? "Begin" : "End",
2137  caller ? caller->base->name : "(none)",
2138  peer ? peer->base->name : "(none)",
2139  (unsigned int)stasis_message_timestamp(message)->tv_sec,
2140  (unsigned int)stasis_message_timestamp(message)->tv_usec);
2141 
2142  /* Figure out who is running this show */
2143  if (caller) {
2145  } else {
2147  }
2148  if (!cdr) {
2149  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->base->name : peer->base->name);
2150  ast_assert(0);
2151  return;
2152  }
2153 
2154  ao2_lock(cdr);
2155  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2156  it_cdr->lastevent = *stasis_message_timestamp(message);
2157  if (ast_strlen_zero(dial_status)) {
2158  if (!it_cdr->fn_table->process_dial_begin) {
2159  continue;
2160  }
2161  CDR_DEBUG("%p - Processing Dial Begin message for channel %s, peer %s\n",
2162  it_cdr,
2163  caller ? caller->base->name : "(none)",
2164  peer ? peer->base->name : "(none)");
2165  res &= it_cdr->fn_table->process_dial_begin(it_cdr,
2166  caller,
2167  peer);
2168  } else if (dial_status_end(dial_status)) {
2169  if (!it_cdr->fn_table->process_dial_end) {
2170  continue;
2171  }
2172  CDR_DEBUG("%p - Processing Dial End message for channel %s, peer %s\n",
2173  it_cdr,
2174  caller ? caller->base->name : "(none)",
2175  peer ? peer->base->name : "(none)");
2176  it_cdr->fn_table->process_dial_end(it_cdr,
2177  caller,
2178  peer,
2179  dial_status);
2180  }
2181  }
2182 
2183  /* If no CDR handled a dial begin message, make a new one */
2184  if (res && ast_strlen_zero(dial_status)) {
2185  struct cdr_object *new_cdr;
2186 
2187  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
2188  if (new_cdr) {
2189  new_cdr->fn_table->process_dial_begin(new_cdr, caller, peer);
2190  }
2191  }
2192  ao2_unlock(cdr);
2193  ao2_cleanup(cdr);
2194 }
struct ast_channel_snapshot_base * base
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define AST_LOG_WARNING
Definition: logger.h:279
struct cdr_object * next
Definition: cdr.c:735
Structure representing a snapshot of channel state.
const ast_string_field uniqueid
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2064
#define NULL
Definition: resample.c:96
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...
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
int(*const process_dial_begin)(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
Process the beginning of a dial. A dial message implies one of two things: The cdr_object&#39;s Party A h...
Definition: cdr.c:462
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
struct ast_channel_snapshot_caller * caller
An in-memory representation of an active CDR.
Definition: cdr.c:712
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:365
struct timeval lastevent
Definition: cdr.c:721
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int dial_status_end(const char *dialstatus)
Definition: cdr.c:2089
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
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:1075
int(*const process_dial_end)(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
Process the end of a dial. At the end of a dial, a CDR can be transitioned into one of two states - D...
Definition: cdr.c:480
const ast_string_field name

◆ handle_parked_call_message()

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
topicThe topic this message was published for
messageThe message about who got parked

Definition at line 2751 of file cdr.c.

References ao2_cleanup, ao2_find, ao2_lock, ao2_unlock, ast_assert, ast_log, AST_LOG_WARNING, ast_channel_snapshot::base, CDR_DEBUG, cdr_object_create_and_append(), ast_parked_call_payload::event_type, filter_channel_snapshot(), cdr_object::fn_table, cdr_object::lastevent, ast_channel_snapshot_base::name, cdr_object::next, OBJ_SEARCH_KEY, PARKED_CALL, ast_parked_call_payload::parkee, cdr_object_fn_table::process_parked_channel, stasis_message_data(), stasis_message_timestamp(), and ast_channel_snapshot_base::uniqueid.

Referenced by load_module().

2753 {
2754  struct ast_parked_call_payload *payload = stasis_message_data(message);
2755  struct ast_channel_snapshot *channel = payload->parkee;
2756  struct cdr_object *cdr;
2757  int unhandled = 1;
2758  struct cdr_object *it_cdr;
2759 
2760  /* Anything other than getting parked will be handled by other updates */
2761  if (payload->event_type != PARKED_CALL) {
2762  return;
2763  }
2764 
2765  /* No one got parked? */
2766  if (!channel) {
2767  return;
2768  }
2769 
2770  if (filter_channel_snapshot(channel)) {
2771  return;
2772  }
2773 
2774  CDR_DEBUG("Parked Call message for channel %s: %u.%08u\n",
2775  channel->base->name,
2776  (unsigned int)stasis_message_timestamp(message)->tv_sec,
2777  (unsigned int)stasis_message_timestamp(message)->tv_usec);
2778 
2780  if (!cdr) {
2781  ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
2782  ast_assert(0);
2783  return;
2784  }
2785 
2786  ao2_lock(cdr);
2787 
2788  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2789  it_cdr->lastevent = *stasis_message_timestamp(message);
2790  if (it_cdr->fn_table->process_parked_channel) {
2791  unhandled &= it_cdr->fn_table->process_parked_channel(it_cdr, payload);
2792  }
2793  }
2794 
2795  if (unhandled) {
2796  /* Nothing handled the messgae - we need a new one! */
2797  struct cdr_object *new_cdr;
2798 
2799  new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
2800  if (new_cdr) {
2801  /* As the new CDR is created in the single state, it is guaranteed
2802  * to have a function for the parked call message and will handle
2803  * the message */
2804  new_cdr->fn_table->process_parked_channel(new_cdr, payload);
2805  }
2806  }
2807 
2808  ao2_unlock(cdr);
2809 
2810  ao2_cleanup(cdr);
2811 }
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:546
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define AST_LOG_WARNING
Definition: logger.h:279
struct cdr_object * next
Definition: cdr.c:735
Structure representing a snapshot of channel state.
const ast_string_field uniqueid
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
Definition: muted.c:95
A parked call message payload.
Definition: parking.h:59
static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
Definition: cdr.c:2064
enum ast_parked_call_event_type event_type
Definition: parking.h:62
#define ast_log
Definition: astobj2.c:42
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
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.
#define ao2_lock(a)
Definition: astobj2.h:718
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
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:365
struct timeval lastevent
Definition: cdr.c:721
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct cdr_object * cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
Create a new cdr_object and append it to an existing chain.
Definition: cdr.c:1075
const ast_string_field name

◆ handle_parking_bridge_enter_message()

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

Definition at line 2586 of file cdr.c.

References ao2_lock, ao2_unlock, 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.

Referenced by handle_bridge_enter_message().

2590 {
2591  int res = 1;
2592  struct cdr_object *it_cdr;
2593  struct cdr_object *new_cdr;
2594 
2595  ao2_lock(cdr);
2596 
2597  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2598  it_cdr->lastevent = *event_time;
2599 
2600  if (it_cdr->fn_table->process_parking_bridge_enter) {
2601  res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
2602  }
2603  if (it_cdr->fn_table->process_party_a) {
2604  CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2605  channel->base->name);
2606  it_cdr->fn_table->process_party_a(it_cdr, channel);
2607  }
2608  }
2609 
2610  if (res) {
2611  /* No one handled it - we need a new one! */
2612  new_cdr = cdr_object_create_and_append(cdr, event_time);
2613  if (new_cdr) {
2614  /* Let the single state transition us to Parked */
2616  new_cdr->fn_table->process_parking_bridge_enter(new_cdr, bridge, channel);
2617  }
2618  }
2619  ao2_unlock(cdr);
2620 }
struct ast_channel_snapshot_base * base
struct cdr_object * next
Definition: cdr.c:735
int(*const process_party_a)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party A update for the cdr_object.
Definition: cdr.c:437
#define ao2_unlock(a)
Definition: astobj2.h:730
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
#define ao2_lock(a)
Definition: astobj2.h:718
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct cdr_object_fn_table single_state_fn_table
The virtual table for the Single state.
Definition: cdr.c:573
struct timeval lastevent
Definition: cdr.c:721
int(*const process_parking_bridge_enter)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process entering into a parking bridge.
Definition: cdr.c:519
static struct cdr_object * cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
Create a new cdr_object and append it to an existing chain.
Definition: cdr.c:1075
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:821

◆ handle_standard_bridge_enter_message()

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

Definition at line 2627 of file cdr.c.

References ao2_lock, ao2_unlock, 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, NULL, cdr_object_fn_table::process_bridge_enter, cdr_object_fn_table::process_party_a, and result.

Referenced by handle_bridge_enter_message().

2631 {
2633  struct cdr_object *it_cdr;
2634  struct cdr_object *new_cdr;
2635  struct cdr_object *handled_cdr = NULL;
2636 
2637  ao2_lock(cdr);
2638 
2639 try_again:
2640  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
2641  it_cdr->lastevent = *event_time;
2642 
2643  if (it_cdr->fn_table->process_party_a) {
2644  CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
2645  channel->base->name);
2646  it_cdr->fn_table->process_party_a(it_cdr, channel);
2647  }
2648 
2649  /* Notify all states that they have entered a bridge */
2650  if (it_cdr->fn_table->process_bridge_enter) {
2651  CDR_DEBUG("%p - Processing bridge enter for %s\n", it_cdr,
2652  channel->base->name);
2653  result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
2654  switch (result) {
2656  /* Fall through */
2658  if (!handled_cdr) {
2659  handled_cdr = it_cdr;
2660  }
2661  break;
2662  case BRIDGE_ENTER_NEED_CDR:
2663  /* Pass */
2664  break;
2666  /* We didn't win on any - end this CDR. If someone else comes in later
2667  * that is Party B to this CDR, it can re-activate this CDR.
2668  */
2669  if (!handled_cdr) {
2670  handled_cdr = it_cdr;
2671  }
2672  cdr_object_finalize(cdr);
2673  break;
2674  }
2675  }
2676  }
2677 
2678  /* Create the new matchings, but only for either:
2679  * * The first CDR in the chain that handled it. This avoids issues with
2680  * forked CDRs.
2681  * * If no one handled it, the last CDR in the chain. This would occur if
2682  * a CDR joined a bridge and it wasn't Party A for anyone. We still need
2683  * to make pairings with everyone in the bridge.
2684  */
2685  if (handled_cdr) {
2686  handle_bridge_pairings(handled_cdr, bridge);
2687  } else {
2688  /* Nothing handled it - we need a new one! */
2689  new_cdr = cdr_object_create_and_append(cdr, event_time);
2690  if (new_cdr) {
2691  /* This is guaranteed to succeed: the new CDR is created in the single state
2692  * and will be able to handle the bridge enter message
2693  */
2694  goto try_again;
2695  }
2696  }
2697  ao2_unlock(cdr);
2698 }
struct ast_channel_snapshot_base * base
struct cdr_object * next
Definition: cdr.c:735
int(*const process_party_a)(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Process a Party A update for the cdr_object.
Definition: cdr.c:437
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
enum process_bridge_enter_results(*const process_bridge_enter)(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
Process the entering of a bridge by this CDR. The purpose of this callback is to have the CDR prepare...
Definition: cdr.c:503
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
process_bridge_enter_results
Return types for process_bridge_enter functions.
Definition: cdr.c:391
#define ao2_lock(a)
Definition: astobj2.h:718
static void handle_bridge_pairings(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge)
Handle creating bridge pairings for the cdr_object that just entered a bridge.
Definition: cdr.c:2561
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
struct timeval lastevent
Definition: cdr.c:721
static PGresult * result
Definition: cel_pgsql.c:88
static struct cdr_object * cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
Create a new cdr_object and append it to an existing chain.
Definition: cdr.c:1075
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
const ast_string_field name

◆ init_batch()

static int init_batch ( void  )
static
Note
Don't call without cdr_batch_lock

Definition at line 3738 of file cdr.c.

References ast_malloc, batch, and reset_batch().

Referenced by cdr_detach().

3739 {
3740  /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
3741  if (!(batch = ast_malloc(sizeof(*batch))))
3742  return -1;
3743 
3744  reset_batch();
3745 
3746  return 0;
3747 }
static void reset_batch(void)
Definition: cdr.c:3730
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
static struct cdr_batch * batch

◆ is_cdr_flag_set()

static int is_cdr_flag_set ( unsigned int  cdr_flag)
static

Definition at line 1127 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_test_flag, module_config::general, and ast_cdr_config::settings.

Referenced by ast_cdr_is_enabled(), ast_cdr_serialize_variables(), base_process_party_a(), cdr_object_check_party_a_hangup(), cdr_object_get_billsec(), cdr_object_set_disposition(), check_new_cdr_needed(), dial_status_to_disposition(), finalized_state_process_party_a(), and snapshot_cep_changed().

1128 {
1129  struct module_config *mod_cfg;
1130  int flag_set;
1131 
1132  mod_cfg = ao2_global_obj_ref(module_configs);
1133  flag_set = mod_cfg && ast_test_flag(&mod_cfg->general->settings, cdr_flag);
1134  ao2_cleanup(mod_cfg);
1135  return flag_set;
1136 }
struct ast_flags settings
Definition: cdr.h:265
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
The configuration settings for this module.
Definition: cdr.c:222
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_cdr_config * general
Definition: cdr.c:223

◆ load_module()

static int load_module ( void  )
static

Definition at line 4522 of file cdr.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_container_register(), ARRAY_LEN, ast_channel_dial_type(), ast_channel_entered_bridge_type(), ast_channel_left_bridge_type(), ast_channel_snapshot_type(), ast_cli_register_multiple, ast_log, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, AST_NUM_CHANNEL_BUCKETS, ast_parked_call_type(), ast_register_atexit(), ast_sched_context_create(), AST_TASKPROCESSOR_HIGH_WATER_LEVEL, cdr_all_cmp_fn(), cdr_all_hash_fn(), cdr_all_print_fn(), cdr_engine_shutdown(), cdr_master_cmp_fn(), cdr_master_hash_fn(), cdr_master_print_fn(), cdr_toggle_runtime_options(), handle_bridge_enter_message(), handle_bridge_leave_message(), handle_cdr_sync_message(), handle_channel_snapshot_update_message(), handle_dial_message(), handle_parked_call_message(), LOG_ERROR, NULL, process_config(), stasis_message_router_add(), stasis_message_router_create, stasis_message_router_set_congestion_limits(), STASIS_MESSAGE_TYPE_INIT, and stasis_topic_create().

Referenced by reload_module().

4523 {
4524  if (process_config(0)) {
4525  return AST_MODULE_LOAD_FAILURE;
4526  }
4527 
4528  cdr_topic = stasis_topic_create("cdr:aggregator");
4529  if (!cdr_topic) {
4530  return AST_MODULE_LOAD_FAILURE;
4531  }
4532 
4534  if (!stasis_router) {
4535  return AST_MODULE_LOAD_FAILURE;
4536  }
4539 
4540  if (STASIS_MESSAGE_TYPE_INIT(cdr_sync_message_type)) {
4541  return AST_MODULE_LOAD_FAILURE;
4542  }
4543 
4550 
4553  if (!active_cdrs_master) {
4554  return AST_MODULE_LOAD_FAILURE;
4555  }
4557 
4560  if (!active_cdrs_all) {
4561  return AST_MODULE_LOAD_FAILURE;
4562  }
4564 
4566  if (!sched) {
4567  ast_log(LOG_ERROR, "Unable to create schedule context.\n");
4568  return AST_MODULE_LOAD_FAILURE;
4569  }
4570 
4573 
4575 }
static struct stasis_message_router * stasis_router
Message router for stasis messages regarding channel state.
Definition: cdr.c:371
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int cdr_master_cmp_fn(void *obj, void *arg, int flags)
Definition: cdr.c:854
struct stasis_message_type * ast_channel_entered_bridge_type(void)
Message type for channel enter bridge blob messages.
static void handle_bridge_leave_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for when a channel leaves a bridge.
Definition: cdr.c:2404
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
struct stasis_message_type * ast_channel_left_bridge_type(void)
Message type for channel leave bridge blob messages.
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
Definition: taskprocessor.h:63
static int cdr_master_hash_fn(const void *obj, const int flags)
Definition: cdr.c:830
static void cdr_engine_shutdown(void)
Definition: cdr.c:4385
Definition: sched.c:76
static struct stasis_topic * cdr_topic
The parent topic for all topics we want to aggregate for CDRs.
Definition: cdr.c:383
#define AST_NUM_CHANNEL_BUCKETS
Definition: channel.h:156
static void handle_bridge_enter_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: cdr.c:2708
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static void handle_dial_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for Stasis-Core dial messages.
Definition: cdr.c:2105
#define NULL
Definition: resample.c:96
static void handle_channel_snapshot_update_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for channel snapshot update messages.
Definition: cdr.c:2278
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
#define ast_log
Definition: astobj2.c:42
static int cdr_all_hash_fn(const void *obj, const int flags)
Definition: cdr.c:888
static int process_config(int reload)
Definition: cdr.c:4340
static struct ast_cli_entry cli_commands[]
Definition: cdr.c:4249
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition: stasis.c:618
#define stasis_message_router_create(topic)
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:236
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
Module could not be loaded properly.
Definition: module.h:102
static int cdr_all_cmp_fn(void *obj, void *arg, int flags)
Definition: cdr.c:912
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
static void handle_parked_call_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for when a channel is parked.
Definition: cdr.c:2751
static void cdr_all_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: cdr.c:4472
static struct ao2_container * active_cdrs_all
A container of all active CDRs with a Party B indexed by Party B channel name.
Definition: cdr.c:368
struct stasis_message_type * ast_channel_dial_type(void)
Message type for when a channel dials another channel.
int stasis_message_router_set_congestion_limits(struct stasis_message_router *router, long low_water, long high_water)
Set the high and low alert water marks of the stasis message router.
static void cdr_master_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: cdr.c:4445
static void handle_cdr_sync_message(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Handler for a synchronization message.
Definition: cdr.c:2820
static int cdr_toggle_runtime_options(void)
Checks if CDRs are enabled and enables/disables the necessary options.
Definition: cdr.c:4488

◆ module_config_alloc()

static void * module_config_alloc ( void  )
static

Create a new module config object.

Definition at line 300 of file cdr.c.

References ao2_alloc, ao2_ref, cdr_config, module_config::general, module_config_destructor(), and NULL.

Referenced by process_config().

301 {
302  struct module_config *mod_cfg;
303  struct ast_cdr_config *cdr_config;
304 
305  mod_cfg = ao2_alloc(sizeof(*mod_cfg), module_config_destructor);
306  if (!mod_cfg) {
307  return NULL;
308  }
309 
310  cdr_config = ao2_alloc(sizeof(*cdr_config), NULL);
311  if (!cdr_config) {
312  ao2_ref(cdr_config, -1);
313  return NULL;
314  }
315  mod_cfg->general = cdr_config;
316 
317  return mod_cfg;
318 }
#define NULL
Definition: resample.c:96
static const char cdr_config[]
Definition: cdr_radius.c:86
static void module_config_destructor(void *obj)
Dispose of a module config object.
Definition: cdr.c:289
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The configuration settings for this module.
Definition: cdr.c:222
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
The global options available for CDRs.
Definition: cdr.h:264
struct ast_cdr_config * general
Definition: cdr.c:223

◆ module_config_destructor()

static void module_config_destructor ( void *  obj)
static

Dispose of a module config object.

Definition at line 289 of file cdr.c.

References ao2_ref, and module_config::general.

Referenced by module_config_alloc().

290 {
291  struct module_config *cfg = obj;
292 
293  if (!cfg) {
294  return;
295  }
296  ao2_ref(cfg->general, -1);
297 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The configuration settings for this module.
Definition: cdr.c:222
struct ast_cdr_config * general
Definition: cdr.c:223

◆ module_config_post_apply()

static void module_config_post_apply ( void  )
static

Definition at line 276 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, and cdr_set_debug_mode.

277 {
278  struct module_config *mod_cfg;
279 
280  mod_cfg = ao2_global_obj_ref(module_configs);
281  if (!mod_cfg) {
282  return;
283  }
284  cdr_set_debug_mode(mod_cfg);
285  ao2_cleanup(mod_cfg);
286 }
#define cdr_set_debug_mode(mod_cfg)
Definition: cdr.c:203
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
The configuration settings for this module.
Definition: cdr.c:222
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ parked_state_process_bridge_leave()

static int parked_state_process_bridge_leave ( struct cdr_object cdr,
struct ast_bridge_snapshot bridge,
struct ast_channel_snapshot channel 
)
static

Definition at line 2032 of file cdr.c.

References ast_channel_snapshot::base, cdr_object_transition_state(), ast_channel_snapshot_base::name, cdr_object::party_a, and cdr_object_snapshot::snapshot.

2033 {
2034  if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)) {
2035  return 1;
2036  }
2038 
2039  return 0;
2040 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_a
Definition: cdr.c:713
struct cdr_object_fn_table finalized_state_fn_table
The virtual table for the finalized state.
Definition: cdr.c:694
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:821

◆ post_cdr()

static void post_cdr ( struct ast_cdr cdr)
static

Definition at line 3508 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, AST_CDR_ANSWERED, AST_CDR_FLAG_DISABLE, ast_debug, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero, ast_test_flag, cdr_beitem::be, CDR_UNANSWERED, ast_cdr::channel, ast_cdr::disposition, ast_cdr::dstchannel, module_config::general, ast_cdr::next, and ast_cdr_config::settings.

Referenced by cdr_detach(), and do_batch_backend_process().

3509 {
3510  struct module_config *mod_cfg;
3511  struct cdr_beitem *i;
3512 
3513  mod_cfg = ao2_global_obj_ref(module_configs);
3514  if (!mod_cfg) {
3515  return;
3516  }
3517 
3518  for (; cdr ; cdr = cdr->next) {
3519  /* For people, who don't want to see unanswered single-channel events */
3520  if (!ast_test_flag(&mod_cfg->general->settings, CDR_UNANSWERED) &&
3521  cdr->disposition < AST_CDR_ANSWERED &&
3523  ast_debug(1, "Skipping CDR for %s since we weren't answered\n", cdr->channel);
3524  continue;
3525  }
3526 
3527  /* Modify CDR's */
3529  AST_RWLIST_TRAVERSE(&mo_list, i, list) {
3530  i->be(cdr);
3531  }
3533 
3534  if (ast_test_flag(cdr, AST_CDR_FLAG_DISABLE)) {
3535  continue;
3536  }
3538  AST_RWLIST_TRAVERSE(&be_list, i, list) {
3539  if (!i->suspended) {
3540  i->be(cdr);
3541  }
3542  }
3544  }
3545  ao2_cleanup(mod_cfg);
3546 }
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:288
struct ast_flags settings
Definition: cdr.h:265
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_cdr * next
Definition: cdr.h:325
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
Registration object for CDR backends.
Definition: cdr.c:321
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
The configuration settings for this module.
Definition: cdr.c:222
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:286
List of registered modifiers.
Definition: cdr.c:333
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
ast_cdrbe be
Definition: cdr.c:324
long int disposition
Definition: cdr.h:304
struct ast_cdr_config * general
Definition: cdr.c:223
List of registered backends.
Definition: cdr.c:330

◆ process_config()

static int process_config ( int  reload)
static

Definition at line 4340 of file cdr.c.

References ACO_EXACT, aco_info_init(), aco_option_register, aco_process_config(), ACO_PROCESS_ERROR, aco_set_defaults(), ao2_cleanup, ao2_global_obj_replace_unref, ast_log, BATCH_MODE_SAFE_SHUTDOWN, BATCH_MODE_SCHEDULER_ONLY, CDR_BATCHMODE, CDR_CONGESTION, CDR_DEBUG, CDR_ENABLED, CDR_END_BEFORE_H_EXTEN, CDR_INITIATED_SECONDS, cdr_set_debug_mode, CDR_UNANSWERED, DEFAULT_BATCH_SAFE_SHUTDOWN, DEFAULT_BATCH_SCHEDULER_ONLY, DEFAULT_BATCH_SIZE, DEFAULT_BATCH_TIME, DEFAULT_BATCHMODE, DEFAULT_ENABLED, DEFAULT_END_BEFORE_H_EXTEN, DEFAULT_INITIATED_SECONDS, DEFAULT_UNANSWERED, FLDSET, module_config::general, LOG_NOTICE, MAX_BATCH_SIZE, MAX_BATCH_TIME, module_config_alloc(), OPT_BOOLFLAG_T, OPT_UINT_T, PARSE_IN_RANGE, settings, and ast_cdr_config::settings.

Referenced by load_module(), and reload_module().

4341 {
4342  if (!reload) {
4343  if (aco_info_init(&cfg_info)) {
4344  return 1;
4345  }
4346 
4358  }
4359 
4360  if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) {
4361  struct module_config *mod_cfg;
4362 
4363  if (reload) {
4364  return 1;
4365  }
4366 
4367  /* If we couldn't process the configuration and this wasn't a reload,
4368  * create a default config
4369  */
4370  mod_cfg = module_config_alloc();
4371  if (!mod_cfg
4372  || aco_set_defaults(&general_option, "general", mod_cfg->general)) {
4373  ao2_cleanup(mod_cfg);
4374  return 1;
4375  }
4376  ast_log(LOG_NOTICE, "Failed to process CDR configuration; using defaults\n");
4377  ao2_global_obj_replace_unref(module_configs, mod_cfg);
4378  cdr_set_debug_mode(mod_cfg);
4379  ao2_cleanup(mod_cfg);
4380  }
4381 
4382  return 0;
4383 }
#define MAX_BATCH_SIZE
Definition: cdr.c:197
static void * module_config_alloc(void)
Create a new module config object.
Definition: cdr.c:300
#define cdr_set_debug_mode(mod_cfg)
Definition: cdr.c:203
struct ast_flags settings
Definition: cdr.h:265
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
#define DEFAULT_BATCH_SIZE
Definition: cdr.c:196
#define DEFAULT_BATCH_TIME
Definition: cdr.c:198
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define DEFAULT_ENABLED
Definition: cdr.c:189
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
#define DEFAULT_BATCH_SAFE_SHUTDOWN
Definition: cdr.c:201
#define ast_log
Definition: astobj2.c:42
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define DEFAULT_UNANSWERED
Definition: cdr.c:191
Type for default option handler for unsigned integers.
#define DEFAULT_END_BEFORE_H_EXTEN
Definition: cdr.c:193
The configuration settings for this module.
Definition: cdr.c:222
Their was an error and no changes were applied.
static struct aco_type * general_options[]
Definition: cdr.c:274
#define LOG_NOTICE
Definition: logger.h:263
static int reload(void)
Definition: cdr_mysql.c:741
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
#define ao2_global_obj_replace_unref(holder, obj)
Definition: astobj2.h:908
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct aco_type general_option
The type definition for general options.
Definition: cdr.c:230
#define DEFAULT_BATCHMODE
Definition: cdr.c:190
The global options available for CDRs.
Definition: cdr.h:264
struct ast_cdr_config * general
Definition: cdr.c:223
static struct cdr_tds_config * settings
Definition: cdr_tds.c:98
#define DEFAULT_BATCH_SCHEDULER_ONLY
Definition: cdr.c:200
#define DEFAULT_INITIATED_SECONDS
Definition: cdr.c:194
#define MAX_BATCH_TIME
Definition: cdr.c:199

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 4617 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CORE, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_test_flag, ASTERISK_GPL_KEY, CDR_BATCHMODE, CDR_ENABLED, cdr_toggle_runtime_options(), finalize_batch_mode(), module_config::general, load_module(), process_config(), reload(), ast_cdr_config::settings, and unload_module().

4618 {
4619  struct module_config *old_mod_cfg;
4620  struct module_config *mod_cfg;
4621 
4622  old_mod_cfg = ao2_global_obj_ref(module_configs);
4623 
4624  if (!old_mod_cfg || process_config(1)) {
4625  ao2_cleanup(old_mod_cfg);
4626  return -1;
4627  }
4628 
4629  mod_cfg = ao2_global_obj_ref(module_configs);
4630  if (!mod_cfg
4631  || !ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)
4632  || !ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
4633  /* If batch mode used to be enabled, finalize the batch */
4634  if (ast_test_flag(&old_mod_cfg->general->settings, CDR_BATCHMODE)) {
4636  }
4637  }
4638  ao2_cleanup(mod_cfg);
4639 
4640  ao2_cleanup(old_mod_cfg);
4641  return cdr_toggle_runtime_options();
4642 }
struct ast_flags settings
Definition: cdr.h:265
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
static int process_config(int reload)
Definition: cdr.c:4340
The configuration settings for this module.
Definition: cdr.c:222
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_cdr_config * general
Definition: cdr.c:223
static int cdr_toggle_runtime_options(void)
Checks if CDRs are enabled and enables/disables the necessary options.
Definition: cdr.c:4488
static void finalize_batch_mode(void)
Definition: cdr.c:4277

◆ reset_batch()

static void reset_batch ( void  )
static
Note
Don't call without cdr_batch_lock

Definition at line 3730 of file cdr.c.

References batch, cdr_batch::head, NULL, cdr_batch::size, and cdr_batch::tail.

Referenced by cdr_submit_batch(), and init_batch().

3731 {
3732  batch->size = 0;
3733  batch->head = NULL;
3734  batch->tail = NULL;
3735 }
struct cdr_batch_item * tail
Definition: cdr.c:345
#define NULL
Definition: resample.c:96
static struct cdr_batch * batch
struct cdr_batch_item * head
Definition: cdr.c:344
int size
Definition: cdr.c:343

◆ set_variable()

static void set_variable ( struct varshead headp,
const char *  name,
const char *  value 
)
static

Definition at line 1262 of file cdr.c.

References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_var_assign, ast_var_delete(), ast_var_name(), and ast_var_t::entries.

Referenced by ast_cdr_setvar(), and cdr_object_update_cid().

1263 {
1264  struct ast_var_t *newvariable;
1265 
1266  AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1267  if (!strcasecmp(ast_var_name(newvariable), name)) {
1269  ast_var_delete(newvariable);
1270  break;
1271  }
1272  }
1274 
1275  if (value && (newvariable = ast_var_assign(name, value))) {
1276  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1277  }
1278 }
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
int value
Definition: syslog.c:37
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
static const char name[]
Definition: cdr_mysql.c:74
struct ast_var_t::@249 entries
#define ast_var_assign(name, value)
Definition: chanvars.h:40
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528

◆ single_state_bridge_enter_comparison()

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 1692 of file cdr.c.

References ast_channel_snapshot::base, cdr_all_relink(), 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.

Referenced by single_state_process_bridge_enter().

1694 {
1695  struct cdr_object_snapshot *party_a;
1696 
1697  /* Don't match on ourselves */
1698  if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
1699  return 1;
1700  }
1701 
1702  /* Try the candidate CDR's Party A first */
1703  party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
1704  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1705  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1706  cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name);
1707  cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
1708  cdr_all_relink(cdr);
1709  if (!cand_cdr->party_b.snapshot) {
1710  /* We just stole them - finalize their CDR. Note that this won't
1711  * transition their state, it just sets the end time and the
1712  * disposition - if we need to re-activate them later, we can.
1713  */
1714  cdr_object_finalize(cand_cdr);
1715  }
1716  return 0;
1717  }
1718 
1719  /* Try their Party B, unless it's us */
1720  if (!cand_cdr->party_b.snapshot
1721  || !strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name)) {
1722  return 1;
1723  }
1724  party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
1725  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
1726  CDR_DEBUG("%p - Party A %s has new Party B %s\n",
1727  cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name);
1728  cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
1729  cdr_all_relink(cdr);
1730  return 0;
1731  }
1732 
1733  return 1;
1734 }
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
A wrapper object around a snapshot. Fields that are mutable by the CDR engine are replicated here...
Definition: cdr.c:704
struct cdr_object_snapshot party_a
Definition: cdr.c:713
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
static struct cdr_object_snapshot * cdr_object_pick_party_a(struct cdr_object_snapshot *left, struct cdr_object_snapshot *right)
Given two CDR snapshots, figure out who should be Party A for the resulting CDR.
Definition: cdr.c:1192
static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr_object_snapshot *src)
Copy a snapshot and its details.
Definition: cdr.c:791
static void cdr_object_finalize(struct cdr_object *cdr)
Finalize a CDR.
Definition: cdr.c:1440
const ast_string_field name
static void cdr_all_relink(struct cdr_object *cdr)
Definition: cdr.c:949

◆ single_state_init_function()

static void single_state_init_function ( struct cdr_object cdr)
static

Definition at line 1639 of file cdr.c.

References cdr_object_check_party_a_answer(), cdr_object::lastevent, and cdr_object::start.

1640 {
1641  cdr->start = cdr->lastevent;
1643 }
struct timeval start
Definition: cdr.c:718
struct timeval lastevent
Definition: cdr.c:721
static void cdr_object_check_party_a_answer(struct cdr_object *cdr)
Check to see if a CDR needs to be answered based on its Party A. Note that this is safe to call as mu...
Definition: cdr.c:1494

◆ single_state_process_bridge_enter()

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

Definition at line 1736 of file cdr.c.

References ao2_cleanup, ao2_container_count(), ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_string_field_set, cdr_object::bridge, BRIDGE_ENTER_NO_PARTY_B, BRIDGE_ENTER_OBTAINED_PARTY_B, BRIDGE_ENTER_ONLY_PARTY, cdr_object_transition_state(), ast_bridge_snapshot::channels, cdr_object::fn_table, cdr_object::next, OBJ_SEARCH_KEY, single_state_bridge_enter_comparison(), and ast_bridge_snapshot::uniqueid.

1737 {
1738  struct ao2_iterator it_cdrs;
1739  char *channel_id;
1740  int success = 0;
1741 
1742  ast_string_field_set(cdr, bridge, bridge->uniqueid);
1743 
1744  if (ao2_container_count(bridge->channels) == 1) {
1745  /* No one in the bridge yet but us! */
1747  return BRIDGE_ENTER_ONLY_PARTY;
1748  }
1749 
1750  for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
1751  !success && (channel_id = ao2_iterator_next(&it_cdrs));
1752  ao2_ref(channel_id, -1)) {
1753  struct cdr_object *cand_cdr_master;
1754  struct cdr_object *cand_cdr;
1755 
1756  cand_cdr_master = ao2_find(active_cdrs_master, channel_id, OBJ_SEARCH_KEY);
1757  if (!cand_cdr_master) {
1758  continue;
1759  }
1760 
1761  ao2_lock(cand_cdr_master);
1762  for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
1763  /* Skip any records that are not in a bridge or in this bridge.
1764  * I'm not sure how that would happen, but it pays to be careful. */
1765  if (cand_cdr->fn_table != &bridge_state_fn_table ||
1766  strcmp(cdr->bridge, cand_cdr->bridge)) {
1767  continue;
1768  }
1769 
1770  if (single_state_bridge_enter_comparison(cdr, cand_cdr)) {
1771  continue;
1772  }
1773  /* We successfully got a party B - break out */
1774  success = 1;
1775  break;
1776  }
1777  ao2_unlock(cand_cdr_master);
1778  ao2_cleanup(cand_cdr_master);
1779  }
1780  ao2_iterator_destroy(&it_cdrs);
1781 
1782  /* We always transition state, even if we didn't get a peer */
1784 
1785  /* Success implies that we have a Party B */
1786  if (success) {
1788  }
1789 
1790  return BRIDGE_ENTER_NO_PARTY_B;
1791 }
struct ao2_container * channels
Definition: bridge.h:339
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct cdr_object * next
Definition: cdr.c:735
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct cdr_object_fn_table * fn_table
Definition: cdr.c:715
An in-memory representation of an active CDR.
Definition: cdr.c:712
static struct ao2_container * active_cdrs_master
A container of the active master CDRs indexed by Party A channel uniqueid.
Definition: cdr.c:365
static int single_state_bridge_enter_comparison(struct cdr_object *cdr, struct cdr_object *cand_cdr)
Handle a comparison between our cdr_object and a cdr_object already in the bridge while in the Single...
Definition: cdr.c:1692
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const ast_string_field uniqueid
Definition: bridge.h:336
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct cdr_object_fn_table bridge_state_fn_table
The virtual table for the Bridged state.
Definition: cdr.c:659
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
const ast_string_field bridge
Definition: cdr.c:734
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ single_state_process_dial_begin()

static int single_state_process_dial_begin ( struct cdr_object cdr,
struct ast_channel_snapshot caller,
struct ast_channel_snapshot peer 
)
static

Definition at line 1653 of file cdr.c.

References AST_CDR_LOCK_APP, ast_set_flag, ast_channel_snapshot::base, base_process_party_a(), cdr_all_relink(), CDR_DEBUG, cdr_object_swap_snapshot(), cdr_object_transition_state(), cdr_object::flags, ast_channel_snapshot_base::name, cdr_object::party_a, cdr_object::party_b, and cdr_object_snapshot::snapshot.

1654 {
1655  if (caller && !strcasecmp(cdr->party_a.snapshot->base->name, caller->base->name)) {
1656  base_process_party_a(cdr, caller);
1657  CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
1658  cdr->party_a.snapshot->base->name);
1659  cdr_object_swap_snapshot(&cdr->party_b, peer);
1660  cdr_all_relink(cdr);
1661  CDR_DEBUG("%p - Updated Party B %s snapshot\n", cdr,
1662  cdr->party_b.snapshot->base->name);
1663 
1664  /* If we have two parties, lock the application that caused the
1665  * two parties to be associated. This prevents mid-call event
1666  * macros/gosubs from perturbing the CDR application/data
1667  */
1669  } else if (!strcasecmp(cdr->party_a.snapshot->base->name, peer->base->name)) {
1670  /* We're the entity being dialed, i.e., outbound origination */
1671  base_process_party_a(cdr, peer);
1672  CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
1673  cdr->party_a.snapshot->base->name);
1674  }
1675 
1677  return 0;
1678 }
static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
Definition: cdr.c:1540
struct ast_channel_snapshot_base * base
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct cdr_object_snapshot party_b
Definition: cdr.c:714
struct cdr_object_snapshot party_a
Definition: cdr.c:713
struct ast_flags flags
Definition: cdr.c:723
#define CDR_DEBUG(fmt,...)
Definition: cdr.c:210
static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
Swap an old cdr_object_snapshot&#39;s ast_channel_snapshot for a new ast_channel_snapshot.
Definition: cdr.c:1531
struct cdr_object_fn_table dial_state_fn_table
The virtual table for the Dial state.
Definition: cdr.c:604
const ast_string_field name
static void cdr_all_relink(struct cdr_object *cdr)
Definition: cdr.c:949
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821

◆ single_state_process_parking_bridge_enter()

static int single_state_process_parking_bridge_enter ( struct cdr_object cdr,
struct ast_bridge_snapshot bridge,
struct ast_channel_snapshot channel 
)
static

Definition at line 1793 of file cdr.c.

References cdr_object_transition_state().

1794 {
1796  return 0;
1797 }
struct cdr_object_fn_table parked_state_fn_table
The virtual table for the Parked state.
Definition: cdr.c:678
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
Transition a cdr_object to a new state.
Definition: cdr.c:821

◆ single_state_process_party_b()

static void single_state_process_party_b ( struct cdr_object cdr,
struct ast_channel_snapshot snapshot 
)
static

Definition at line 1645 of file cdr.c.

References ast_assert, NULL, cdr_object::party_b, and cdr_object_snapshot::snapshot.

1646 {
1647  /* This should never happen! */
1648  ast_assert(cdr->party_b.snapshot == NULL);
1649  ast_assert(0);
1650  return;
1651 }
struct ast_channel_snapshot * snapshot
Definition: cdr.c:705
struct cdr_object_snapshot party_b
Definition: cdr.c:714
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96

◆ snapshot_cep_changed()

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 1148 of file cdr.c.

References ast_channel_snapshot_dialplan::appl, AST_SOFTHANGUP_HANGUP_EXEC, ast_test_flag, CDR_END_BEFORE_H_EXTEN, ast_channel_snapshot_dialplan::context, ast_channel_snapshot::dialplan, ast_channel_snapshot_dialplan::exten, is_cdr_flag_set(), ast_channel_snapshot_dialplan::priority, and ast_channel_snapshot::softhangup_flags.

Referenced by check_new_cdr_needed(), and dialed_pending_state_process_party_a().

1150 {
1151  /* If we ignore hangup logic, don't indicate that we're executing anything new */
1154  return 0;
1155  }
1156 
1157  /* When Party A is originated to an application and the application exits, the stack
1158  * will attempt to clear the application and restore the dummy originate application
1159  * of "AppDialX". Ignore application changes to AppDialX as a result.
1160  */
1161  if (strcmp(new_snapshot->dialplan->appl, old_snapshot->dialplan->appl)
1162  && strncasecmp(new_snapshot->dialplan->appl, "appdial", 7)
1163  && (strcmp(new_snapshot->dialplan->context, old_snapshot->dialplan->context)
1164  || strcmp(new_snapshot->dialplan->exten, old_snapshot->dialplan->exten)
1165  || new_snapshot->dialplan->priority != old_snapshot->dialplan->priority)) {
1166  return 1;
1167  }
1168 
1169  return 0;
1170 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int is_cdr_flag_set(unsigned int cdr_flag)
Definition: cdr.c:1127
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

◆ snapshot_is_dialed()

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 1179 of file cdr.c.

References AST_FLAG_ORIGINATED, AST_FLAG_OUTGOING, ast_test_flag, and ast_channel_snapshot::flags.

Referenced by cdr_object_create_public_records(), cdr_object_pick_party_a(), cli_show_channel(), and cli_show_channels().

1180 {
1181  return (ast_test_flag(&snapshot->flags, AST_FLAG_OUTGOING)
1182  && !(ast_test_flag(&snapshot->flags, AST_FLAG_ORIGINATED)));
1183 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_flags flags

◆ start_batch_mode()

static void start_batch_mode ( void  )
static

Do not hold the batch lock while calling this function

Definition at line 3825 of file cdr.c.

References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ast_sched_add_variable(), AST_SCHED_DEL, cdr_pending_cond, cdr_pending_lock, cdr_sched, cdr_sched_lock, NULL, and submit_scheduled_batch().

Referenced by cdr_detach(), cdr_enable_batch_mode(), and handle_cli_submit().

3826 {
3827  /* Prevent two deletes from happening at the same time */
3829  /* this is okay since we are not being called from within the scheduler */
3831  /* schedule the submission to occur ASAP (1 ms) */
3834 
3835  /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
3839 }
static ast_mutex_t cdr_sched_lock
Definition: cdr.c:354
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:524
static int submit_scheduled_batch(const void *data)
Definition: cdr.c:3804
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
#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&#39;s work to do.
Definition: cdr.c:361
static ast_cond_t cdr_pending_cond
Definition: cdr.c:362
static int cdr_sched
Definition: cdr.c:353
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL()

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( cdr_sync_message_type  )

A message type used to synchronize with the CDR topic.

◆ submit_scheduled_batch()

static int submit_scheduled_batch ( const void *  data)
static

Definition at line 3804 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_cdr_config::batch_settings, cdr_submit_batch(), module_config::general, and ast_cdr_config::batch_settings::time.

Referenced by start_batch_mode().

3805 {
3806  struct module_config *mod_cfg;
3807  int nextms;
3808 
3809  cdr_submit_batch(0);
3810 
3811  mod_cfg = ao2_global_obj_ref(module_configs);
3812  if (!mod_cfg) {
3813  return 0;
3814  }
3815 
3816  /* Calculate the next scheduled interval */
3817  nextms = mod_cfg->general->batch_settings.time * 1000;
3818 
3819  ao2_cleanup(mod_cfg);
3820 
3821  return nextms;
3822 }
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
static void cdr_submit_batch(int shutdown)
Definition: cdr.c:3766
struct ast_cdr_config::batch_settings batch_settings
The configuration settings for this module.
Definition: cdr.c:222
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_cdr_config * general
Definition: cdr.c:223

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 4515 of file cdr.c.

References destroy_subscriptions().

Referenced by reload_module().

4516 {
4518 
4519  return 0;
4520 }
static void destroy_subscriptions(void)
Destroy the active Stasis subscriptions.
Definition: cdr.c:4304

Variable Documentation

◆ __mod_info

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig", }
static

Definition at line 4651 of file cdr.c.

◆ active_cdrs_all

struct ao2_container* active_cdrs_all
static

A container of all active CDRs with a Party B indexed by Party B channel name.

Definition at line 368 of file cdr.c.

◆ active_cdrs_master

struct ao2_container* active_cdrs_master
static

A container of the active master CDRs indexed by Party A channel uniqueid.

Definition at line 365 of file cdr.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4651 of file cdr.c.

◆ batch

struct cdr_batch * batch = NULL
static

◆ be_list

struct be_list be_list = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ bridge_state_fn_table

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 659 of file cdr.c.

◆ bridge_subscription

struct stasis_forward* bridge_subscription
static

Our subscription for bridges.

Definition at line 374 of file cdr.c.

◆ cdr_batch_lock

ast_mutex_t cdr_batch_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Lock protecting modifications to the batch queue.

Definition at line 358 of file cdr.c.

Referenced by cdr_detach(), and cdr_submit_batch().

◆ cdr_debug_enabled

int cdr_debug_enabled
static

Definition at line 208 of file cdr.c.

◆ cdr_pending_cond

ast_cond_t cdr_pending_cond
static

Definition at line 362 of file cdr.c.

Referenced by cdr_enable_batch_mode(), do_cdr(), finalize_batch_mode(), and start_batch_mode().

◆ cdr_pending_lock

ast_mutex_t cdr_pending_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

These are used to wake up the CDR thread when there's work to do.

Definition at line 361 of file cdr.c.

Referenced by do_cdr(), and start_batch_mode().

◆ cdr_readonly_vars

const char* const cdr_readonly_vars[]
static

Definition at line 3154 of file cdr.c.

◆ cdr_sched

int cdr_sched = -1
static

Definition at line 353 of file cdr.c.

Referenced by handle_cli_status(), and start_batch_mode().

◆ cdr_sched_lock

ast_mutex_t cdr_sched_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 354 of file cdr.c.

Referenced by start_batch_mode().

◆ cdr_thread

pthread_t cdr_thread = AST_PTHREADT_NULL
static

Definition at line 355 of file cdr.c.

Referenced by cdr_enable_batch_mode(), and finalize_batch_mode().

◆ cdr_topic

struct stasis_topic* cdr_topic
static

The parent topic for all topics we want to aggregate for CDRs.

Definition at line 383 of file cdr.c.

◆ channel_subscription

struct stasis_forward* channel_subscription
static

Our subscription for channels.

Definition at line 377 of file cdr.c.

◆ cli_commands

struct ast_cli_entry cli_commands[]
static

Definition at line 4249 of file cdr.c.

◆ dial_state_fn_table

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 604 of file cdr.c.

◆ dialed_pending_state_fn_table

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 637 of file cdr.c.

◆ finalized_state_fn_table

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 694 of file cdr.c.

◆ general_option

struct aco_type general_option
static

The type definition for general options.

Definition at line 230 of file cdr.c.

◆ general_options

struct aco_type* general_options[] = ACO_TYPES(&general_option)
static

Definition at line 274 of file cdr.c.

◆ global_cdr_sequence

int global_cdr_sequence = 0
static

The global sequence counter used for CDRs.

Definition at line 349 of file cdr.c.

Referenced by cdr_object_alloc().

◆ ignore_categories

const char* ignore_categories[]
static

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

Definition at line 239 of file cdr.c.

◆ ignore_option

struct aco_type ignore_option
static

Definition at line 252 of file cdr.c.

◆ mo_list

struct mo_list mo_list = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ module_file_conf

struct aco_file module_file_conf
static
Initial value:
= {
.filename = "cdr.conf",
}
#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:230
static struct aco_type ignore_option
Definition: cdr.c:252

The file definition.

Definition at line 264 of file cdr.c.

◆ parked_state_fn_table

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 678 of file cdr.c.

◆ parking_subscription

struct stasis_forward* parking_subscription
static

Our subscription for parking.

Definition at line 380 of file cdr.c.

Referenced by park_and_announce_app_exec().

◆ sched

struct ast_sched_context* sched
static

Scheduler items.

Definition at line 352 of file cdr.c.

◆ single_state_fn_table

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 573 of file cdr.c.

◆ stasis_router

struct stasis_message_router* stasis_router
static

Message router for stasis messages regarding channel state.

Definition at line 371 of file cdr.c.

Referenced by ast_cdr_message_router().