cdr.h File Reference

Call Detail Record API. More...

#include "asterisk/channel.h"

Include dependency graph for cdr.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_cdr
 Responsible for call detail data. More...
struct  ast_cdr_config
 The global options available for CDRs. More...
struct  ast_cdr_config::batch_settings

Typedefs

typedef int(* ast_cdrbe )(struct ast_cdr *cdr)
 CDR backend callback.

Enumerations

enum  ast_cdr_batch_mode_settings { BATCH_MODE_SCHEDULER_ONLY = 1 << 0, BATCH_MODE_SAFE_SHUTDOWN = 1 << 1 }
 CDR Batch Mode settings. More...
enum  ast_cdr_disposition {
  AST_CDR_NOANSWER = 0, AST_CDR_NULL = (1 << 0), AST_CDR_FAILED = (1 << 1), AST_CDR_BUSY = (1 << 2),
  AST_CDR_ANSWERED = (1 << 3), AST_CDR_CONGESTION = (1 << 4)
}
 CDR Flags - Disposition. More...
enum  ast_cdr_options {
  AST_CDR_FLAG_KEEP_VARS = (1 << 0), AST_CDR_FLAG_DISABLE = (1 << 1), AST_CDR_FLAG_DISABLE_ALL = (3 << 1), AST_CDR_FLAG_PARTY_A = (1 << 3),
  AST_CDR_FLAG_FINALIZE = (1 << 4), AST_CDR_FLAG_SET_ANSWER = (1 << 5), AST_CDR_FLAG_RESET = (1 << 6), AST_CDR_LOCK_APP = (1 << 7)
}
 CDR manipulation options. Certain function calls will manipulate the state of a CDR object based on these flags. More...
enum  ast_cdr_settings {
  CDR_ENABLED = 1 << 0, CDR_BATCHMODE = 1 << 1, CDR_UNANSWERED = 1 << 2, CDR_CONGESTION = 1 << 3,
  CDR_END_BEFORE_H_EXTEN = 1 << 4, CDR_INITIATED_SECONDS = 1 << 5, CDR_DEBUG = 1 << 6
}
 CDR engine settings. More...

Functions

struct ast_cdrast_cdr_alloc (void)
 Allocate a CDR record.
int ast_cdr_backend_suspend (const char *name)
 Suspend a CDR backend temporarily.
int ast_cdr_backend_unsuspend (const char *name)
 Unsuspend a CDR backend.
int ast_cdr_clear_property (const char *channel_name, enum ast_cdr_options option)
 Clear a property on a CDR for a channel.
const char * ast_cdr_disp2str (int disposition)
 Disposition to a string.
struct ast_cdrast_cdr_dup (struct ast_cdr *cdr)
 Duplicate a public CDR.
int ast_cdr_engine_init (void)
 Load the configuration file cdr.conf and possibly start the CDR scheduling thread.
int ast_cdr_engine_reload (void)
 Reload the configuration file cdr.conf and start/stop CDR scheduling thread.
void ast_cdr_engine_term (void)
int ast_cdr_fork (const char *channel_name, struct ast_flags *options)
 Fork a CDR.
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.
void ast_cdr_free (struct ast_cdr *cdr)
 Free a CDR record.
struct ast_cdr_configast_cdr_get_config (void)
 Obtain the current CDR configuration.
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.
int ast_cdr_is_enabled (void)
 Return TRUE if CDR subsystem is enabled.
struct stasis_message_routerast_cdr_message_router (void)
 Return the message router for the CDR engine.
int ast_cdr_register (const char *name, const char *desc, ast_cdrbe be)
 Register a CDR handling engine.
int ast_cdr_reset (const char *channel_name, int keep_variables)
 Reset the detail record.
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.
void ast_cdr_set_config (struct ast_cdr_config *config)
 Set the current CDR configuration.
int ast_cdr_set_property (const char *channel_name, enum ast_cdr_options option)
 Set a property on a CDR for a channel.
void ast_cdr_setuserfield (const char *channel_name, const char *userfield)
 Set CDR user field for channel (stored in CDR).
int ast_cdr_setvar (const char *channel_name, const char *name, const char *value)
 Set a variable on a CDR.
int ast_cdr_unregister (const char *name)
 Unregister a CDR handling engine.


Detailed Description

Call Detail Record API.

Call Detail Record Engine.

Author:
Mark Spencer <markster@digium.com>
Since:
12

Definition in file cdr.h.


Typedef Documentation

typedef int(* ast_cdrbe)(struct ast_cdr *cdr)

CDR backend callback.

Warning:
CDR backends should NOT attempt to access the channel associated with a CDR record. This channel is not guaranteed to exist when the CDR backend is invoked.

Definition at line 458 of file cdr.h.


Enumeration Type Documentation

CDR Batch Mode settings.

Enumerator:
BATCH_MODE_SCHEDULER_ONLY 
BATCH_MODE_SAFE_SHUTDOWN 

Definition at line 230 of file cdr.h.

00230                                  {
00231    BATCH_MODE_SCHEDULER_ONLY = 1 << 0, /*< Don't spawn a thread to handle the batches - do it on the scheduler */
00232    BATCH_MODE_SAFE_SHUTDOWN = 1 << 1,  /*< During safe shutdown, submit the batched CDRs */
00233 };

CDR Flags - Disposition.

Enumerator:
AST_CDR_NOANSWER 
AST_CDR_NULL 
AST_CDR_FAILED 
AST_CDR_BUSY 
AST_CDR_ANSWERED 
AST_CDR_CONGESTION 

Definition at line 253 of file cdr.h.

00253                          {
00254    AST_CDR_NOANSWER   = 0,
00255    AST_CDR_NULL       = (1 << 0),
00256    AST_CDR_FAILED     = (1 << 1),
00257    AST_CDR_BUSY       = (1 << 2),
00258    AST_CDR_ANSWERED   = (1 << 3),
00259    AST_CDR_CONGESTION = (1 << 4),
00260 };

CDR manipulation options. Certain function calls will manipulate the state of a CDR object based on these flags.

Enumerator:
AST_CDR_FLAG_KEEP_VARS 
AST_CDR_FLAG_DISABLE 
AST_CDR_FLAG_DISABLE_ALL 
AST_CDR_FLAG_PARTY_A 
AST_CDR_FLAG_FINALIZE 
AST_CDR_FLAG_SET_ANSWER 
AST_CDR_FLAG_RESET 
AST_CDR_LOCK_APP 

Definition at line 239 of file cdr.h.

00239                      {
00240    AST_CDR_FLAG_KEEP_VARS = (1 << 0),   /*< Copy variables during the operation */
00241    AST_CDR_FLAG_DISABLE = (1 << 1),     /*< Disable the current CDR */
00242    AST_CDR_FLAG_DISABLE_ALL = (3 << 1), /*< Disable the CDR and all future CDRs */
00243    AST_CDR_FLAG_PARTY_A = (1 << 3),     /*< Set the channel as party A */
00244    AST_CDR_FLAG_FINALIZE = (1 << 4),    /*< Finalize the current CDRs */
00245    AST_CDR_FLAG_SET_ANSWER = (1 << 5),  /*< If the channel is answered, set the answer time to now */
00246    AST_CDR_FLAG_RESET = (1 << 6),       /*< If set, set the start and answer time to now */
00247    AST_CDR_LOCK_APP = (1 << 7),         /*< Prevent any further changes to the application field/data field for this CDR */
00248 };

CDR engine settings.

Enumerator:
CDR_ENABLED 
CDR_BATCHMODE 
CDR_UNANSWERED 
CDR_CONGESTION 
CDR_END_BEFORE_H_EXTEN 
CDR_INITIATED_SECONDS 
CDR_DEBUG 

Definition at line 219 of file cdr.h.

00219                       {
00220    CDR_ENABLED = 1 << 0,               /*< Enable CDRs */
00221    CDR_BATCHMODE = 1 << 1,             /*< Whether or not we should dispatch CDRs in batches */
00222    CDR_UNANSWERED = 1 << 2,            /*< Log unanswered CDRs */
00223    CDR_CONGESTION = 1 << 3,            /*< Treat congestion as if it were a failed call */
00224    CDR_END_BEFORE_H_EXTEN = 1 << 4,    /*< End the CDR before the 'h' extension runs */
00225    CDR_INITIATED_SECONDS = 1 << 5,     /*< Include microseconds into the billing time */
00226    CDR_DEBUG = 1 << 6,                 /*< Enables extra debug statements */
00227 };


Function Documentation

struct ast_cdr* ast_cdr_alloc ( void   )  [read]

Allocate a CDR record.

Return values:
a malloc'd ast_cdr structure
NULL on error (malloc failure)

Definition at line 3167 of file cdr.c.

References ast_calloc.

Referenced by ast_cdr_dup().

03168 {
03169    struct ast_cdr *x;
03170 
03171    x = ast_calloc(1, sizeof(*x));
03172    return x;
03173 }

int ast_cdr_backend_suspend ( const char *  name  ) 

Suspend a CDR backend temporarily.

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

Definition at line 2635 of file cdr.c.

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

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

02636 {
02637    int success = -1;
02638    struct cdr_beitem *i = NULL;
02639 
02640    AST_RWLIST_WRLOCK(&be_list);
02641    AST_RWLIST_TRAVERSE(&be_list, i, list) {
02642       if (!strcasecmp(name, i->name)) {
02643          ast_debug(3, "Suspending CDR backend %s\n", i->name);
02644          i->suspended = 1;
02645          success = 0;
02646       }
02647    }
02648    AST_RWLIST_UNLOCK(&be_list);
02649 
02650    return success;
02651 }

int ast_cdr_backend_unsuspend ( const char *  name  ) 

Unsuspend a CDR backend.

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

Definition at line 2653 of file cdr.c.

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

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

02654 {
02655    int success = -1;
02656    struct cdr_beitem *i = NULL;
02657 
02658    AST_RWLIST_WRLOCK(&be_list);
02659    AST_RWLIST_TRAVERSE(&be_list, i, list) {
02660       if (!strcasecmp(name, i->name)) {
02661          ast_debug(3, "Unsuspending CDR backend %s\n", i->name);
02662          i->suspended = 0;
02663          success = 0;
02664       }
02665    }
02666    AST_RWLIST_UNLOCK(&be_list);
02667 
02668    return success;
02669 }

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_name The CDR's channel
option Option to clear from the CDR
Return values:
0 on success
1 on error

Definition at line 3297 of file cdr.c.

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

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

03298 {
03299    RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
03300    struct cdr_object *it_cdr;
03301 
03302    if (!cdr) {
03303       return -1;
03304    }
03305 
03306    ao2_lock(cdr);
03307    for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
03308       if (it_cdr->fn_table == &finalized_state_fn_table) {
03309          continue;
03310       }
03311       ast_clear_flag(&it_cdr->flags, option);
03312    }
03313    ao2_unlock(cdr);
03314 
03315    return 0;
03316 }

const char* ast_cdr_disp2str ( int  disposition  ) 

Disposition to a string.

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

Definition at line 3175 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(), build_csv_record(), build_radius_record(), cdr_object_finalize(), cdr_read_callback(), execute_cb(), manager_log(), and tds_log().

03176 {
03177    switch (disposition) {
03178    case AST_CDR_NULL:
03179       return "NO ANSWER"; /* by default, for backward compatibility */
03180    case AST_CDR_NOANSWER:
03181       return "NO ANSWER";
03182    case AST_CDR_FAILED:
03183       return "FAILED";
03184    case AST_CDR_BUSY:
03185       return "BUSY";
03186    case AST_CDR_ANSWERED:
03187       return "ANSWERED";
03188    case AST_CDR_CONGESTION:
03189       return "CONGESTION";
03190    }
03191    return "UNKNOWN";
03192 }

struct ast_cdr* ast_cdr_dup ( struct ast_cdr cdr  )  [read]

Duplicate a public CDR.

Parameters:
cdr the record to duplicate
Return values:
a malloc'd ast_cdr structure,
NULL on error (malloc failure)

Definition at line 2740 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(), manager_log(), syslog_log(), and write_cdr().

02741 {
02742    struct ast_cdr *newcdr;
02743 
02744    if (!cdr) {
02745       return NULL;
02746    }
02747    newcdr = ast_cdr_alloc();
02748    if (!newcdr) {
02749       return NULL;
02750    }
02751 
02752    *newcdr = *cdr;
02753    AST_LIST_HEAD_INIT_NOLOCK(&newcdr->varshead);
02754    copy_variables(&newcdr->varshead, &cdr->varshead);
02755    newcdr->next = NULL;
02756 
02757    return newcdr;
02758 }

int ast_cdr_engine_init ( void   ) 

Load the configuration file cdr.conf and possibly start the CDR scheduling thread.

Definition at line 4166 of file cdr.c.

References active_cdrs_by_channel, ao2_container_alloc, 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_parked_call_type(), ast_register_atexit(), ast_register_cleanup(), ast_sched_context_create(), cdr_container_print_fn(), cdr_engine_cleanup(), cdr_engine_shutdown(), cdr_object_channel_cmp_fn(), cdr_object_channel_hash_fn(), cdr_toggle_runtime_options(), cdr_topic, cli_commands, handle_bridge_enter_message(), handle_bridge_leave_message(), handle_cdr_sync_message(), handle_channel_cache_message(), handle_dial_message(), handle_parked_call_message(), LOG_ERROR, NULL, NUM_CDR_BUCKETS, process_config(), stasis_message_router_add(), stasis_message_router_add_cache_update(), stasis_message_router_create(), STASIS_MESSAGE_TYPE_INIT, stasis_router, and stasis_topic_create().

Referenced by main().

04167 {
04168    if (process_config(0)) {
04169       return -1;
04170    }
04171 
04172    cdr_topic = stasis_topic_create("cdr_engine");
04173    if (!cdr_topic) {
04174       return -1;
04175    }
04176 
04177    stasis_router = stasis_message_router_create(cdr_topic);
04178    if (!stasis_router) {
04179       return -1;
04180    }
04181 
04182    if (STASIS_MESSAGE_TYPE_INIT(cdr_sync_message_type)) {
04183       return -1;
04184    }
04185 
04186    stasis_message_router_add_cache_update(stasis_router, ast_channel_snapshot_type(), handle_channel_cache_message, NULL);
04187    stasis_message_router_add(stasis_router, ast_channel_dial_type(), handle_dial_message, NULL);
04188    stasis_message_router_add(stasis_router, ast_channel_entered_bridge_type(), handle_bridge_enter_message, NULL);
04189    stasis_message_router_add(stasis_router, ast_channel_left_bridge_type(), handle_bridge_leave_message, NULL);
04190    stasis_message_router_add(stasis_router, ast_parked_call_type(), handle_parked_call_message, NULL);
04191    stasis_message_router_add(stasis_router, cdr_sync_message_type(), handle_cdr_sync_message, NULL);
04192 
04193    active_cdrs_by_channel = ao2_container_alloc(NUM_CDR_BUCKETS,
04194       cdr_object_channel_hash_fn, cdr_object_channel_cmp_fn);
04195    if (!active_cdrs_by_channel) {
04196       return -1;
04197    }
04198    ao2_container_register("cdrs_by_channel", active_cdrs_by_channel, cdr_container_print_fn);
04199 
04200    sched = ast_sched_context_create();
04201    if (!sched) {
04202       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
04203       return -1;
04204    }
04205 
04206    ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
04207    ast_register_cleanup(cdr_engine_cleanup);
04208    ast_register_atexit(cdr_engine_shutdown);
04209 
04210    return cdr_toggle_runtime_options();
04211 }

int ast_cdr_engine_reload ( void   ) 

Reload the configuration file cdr.conf and start/stop CDR scheduling thread.

Definition at line 4246 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_test_flag, CDR_BATCHMODE, CDR_ENABLED, cdr_toggle_runtime_options(), finalize_batch_mode(), NULL, process_config(), and RAII_VAR.

04247 {
04248    RAII_VAR(struct module_config *, old_mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
04249    RAII_VAR(struct module_config *, mod_cfg, NULL, ao2_cleanup);
04250 
04251    if (process_config(1)) {
04252       return -1;
04253    }
04254 
04255    mod_cfg = ao2_global_obj_ref(module_configs);
04256 
04257    if (!ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED) ||
04258          !(ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE))) {
04259       /* If batch mode used to be enabled, finalize the batch */
04260       if (ast_test_flag(&old_mod_cfg->general->settings, CDR_BATCHMODE)) {
04261          finalize_batch_mode();
04262       }
04263    }
04264 
04265    return cdr_toggle_runtime_options();
04266 }

void ast_cdr_engine_term ( void   ) 

Submit any remaining CDRs and prepare for shutdown

Definition at line 4213 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(), stasis_message_router_publish_sync(), and stasis_router.

Referenced by can_safely_quit(), and finalize_batch_mode().

04214 {
04215    RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
04216    RAII_VAR(void *, payload, NULL, ao2_cleanup);
04217    RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
04218 
04219    /* Since this is called explicitly during process shutdown, we might not have ever
04220     * been initialized. If so, the config object will be NULL.
04221     */
04222    if (!mod_cfg) {
04223       return;
04224    }
04225 
04226    if (cdr_sync_message_type()) {
04227       /* Make sure we have the needed items */
04228       payload = ao2_alloc(sizeof(*payload), NULL);
04229       if (!stasis_router || !payload) {
04230          return;
04231       }
04232 
04233       ast_debug(1, "CDR Engine termination request received; waiting on messages...\n");
04234 
04235       message = stasis_message_create(cdr_sync_message_type(), payload);
04236       if (message) {
04237          stasis_message_router_publish_sync(stasis_router, message);
04238       }
04239    }
04240 
04241    if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
04242       cdr_submit_batch(ast_test_flag(&mod_cfg->general->batch_settings.settings, BATCH_MODE_SAFE_SHUTDOWN));
04243    }
04244 }

int ast_cdr_fork ( const char *  channel_name,
struct ast_flags options 
)

Fork a CDR.

Since:
12
Parameters:
channel_name The name of the channel whose CDR should be forked
options Options to control how the fork occurs.
Return values:
0 on success
-1 on failure

Definition at line 3354 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(), cdr_object::bridge, cdr_object_create_and_append(), cdr_object_finalize(), cdr_object_get_by_name(), cdr_object_transition_state(), context, copy_variables(), cdr_object::data, exten, finalized_state_fn_table, cdr_object_snapshot::flags, ast_flags::flags, cdr_object::flags, cdr_object::fn_table, free_variables(), cdr_object::last, lock, cdr_object::next, cdr_object::party_a, cdr_object::party_b, RAII_VAR, SCOPED_AO2LOCK, cdr_object_snapshot::snapshot, cdr_object::start, ast_channel_snapshot::state, cdr_object_snapshot::userfield, and cdr_object_snapshot::variables.

Referenced by AST_TEST_DEFINE(), and forkcdr_callback().

03355 {
03356    RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
03357    struct cdr_object *new_cdr;
03358    struct cdr_object *it_cdr;
03359    struct cdr_object *cdr_obj;
03360 
03361    if (!cdr) {
03362       return -1;
03363    }
03364 
03365    {
03366       SCOPED_AO2LOCK(lock, cdr);
03367 
03368       cdr_obj = cdr->last;
03369       if (cdr_obj->fn_table == &finalized_state_fn_table) {
03370          /* If the last CDR in the chain is finalized, don't allow a fork -
03371           * things are already dying at this point
03372           */
03373          return -1;
03374       }
03375 
03376       /* Copy over the basic CDR information. The Party A information is
03377        * copied over automatically as part of the append
03378        */
03379       ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->name);
03380       new_cdr = cdr_object_create_and_append(cdr);
03381       if (!new_cdr) {
03382          return -1;
03383       }
03384       new_cdr->fn_table = cdr_obj->fn_table;
03385       ast_string_field_set(new_cdr, bridge, cdr->bridge);
03386       ast_string_field_set(new_cdr, appl, cdr->appl);
03387       ast_string_field_set(new_cdr, data, cdr->data);
03388       ast_string_field_set(new_cdr, context, cdr->context);
03389       ast_string_field_set(new_cdr, exten, cdr->exten);
03390       new_cdr->flags = cdr->flags;
03391       /* Explicitly clear the AST_CDR_LOCK_APP flag - we want
03392        * the application to be changed on the new CDR if the
03393        * dialplan demands it
03394        */
03395       ast_clear_flag(&new_cdr->flags, AST_CDR_LOCK_APP);
03396 
03397       /* If there's a Party B, copy it over as well */
03398       if (cdr_obj->party_b.snapshot) {
03399          new_cdr->party_b.snapshot = cdr_obj->party_b.snapshot;
03400          ao2_ref(new_cdr->party_b.snapshot, +1);
03401          strcpy(new_cdr->party_b.userfield, cdr_obj->party_b.userfield);
03402          new_cdr->party_b.flags = cdr_obj->party_b.flags;
03403          if (ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
03404             copy_variables(&new_cdr->party_b.variables, &cdr_obj->party_b.variables);
03405          }
03406       }
03407       new_cdr->start = cdr_obj->start;
03408       new_cdr->answer = cdr_obj->answer;
03409 
03410       /* Modify the times based on the flags passed in */
03411       if (ast_test_flag(options, AST_CDR_FLAG_SET_ANSWER)
03412             && new_cdr->party_a.snapshot->state == AST_STATE_UP) {
03413          new_cdr->answer = ast_tvnow();
03414       }
03415       if (ast_test_flag(options, AST_CDR_FLAG_RESET)) {
03416          new_cdr->answer = ast_tvnow();
03417          new_cdr->start = ast_tvnow();
03418       }
03419 
03420       /* Create and append, by default, copies over the variables */
03421       if (!ast_test_flag(options, AST_CDR_FLAG_KEEP_VARS)) {
03422          free_variables(&new_cdr->party_a.variables);
03423       }
03424 
03425       /* Finalize any current CDRs */
03426       if (ast_test_flag(options, AST_CDR_FLAG_FINALIZE)) {
03427          for (it_cdr = cdr; it_cdr != new_cdr; it_cdr = it_cdr->next) {
03428             if (it_cdr->fn_table == &finalized_state_fn_table) {
03429                continue;
03430             }
03431             /* Force finalization on the CDR. This will bypass any checks for
03432              * end before 'h' extension.
03433              */
03434             cdr_object_finalize(it_cdr);
03435             cdr_object_transition_state(it_cdr, &finalized_state_fn_table);
03436          }
03437       }
03438    }
03439 
03440    return 0;
03441 }

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:
cdr The dispatched CDR to process
name The name of the variable
ret Pointer to the formatted buffer
workspace A pointer to the buffer to use to format the variable
workspacelen The size of workspace
raw If non-zero and a date/time is extraced, provide epoch seconds. Otherwise format as a date/time stamp

Definition at line 2792 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(), mysql_log(), odbc_log(), and pgsql_log().

02793 {
02794    const char *fmt = "%Y-%m-%d %T";
02795    const char *varbuf;
02796 
02797    if (!cdr) {
02798       return;
02799    }
02800 
02801    *ret = NULL;
02802 
02803    if (!strcasecmp(name, "clid")) {
02804       ast_copy_string(workspace, cdr->clid, workspacelen);
02805    } else if (!strcasecmp(name, "src")) {
02806       ast_copy_string(workspace, cdr->src, workspacelen);
02807    } else if (!strcasecmp(name, "dst")) {
02808       ast_copy_string(workspace, cdr->dst, workspacelen);
02809    } else if (!strcasecmp(name, "dcontext")) {
02810       ast_copy_string(workspace, cdr->dcontext, workspacelen);
02811    } else if (!strcasecmp(name, "channel")) {
02812       ast_copy_string(workspace, cdr->channel, workspacelen);
02813    } else if (!strcasecmp(name, "dstchannel")) {
02814       ast_copy_string(workspace, cdr->dstchannel, workspacelen);
02815    } else if (!strcasecmp(name, "lastapp")) {
02816       ast_copy_string(workspace, cdr->lastapp, workspacelen);
02817    } else if (!strcasecmp(name, "lastdata")) {
02818       ast_copy_string(workspace, cdr->lastdata, workspacelen);
02819    } else if (!strcasecmp(name, "start")) {
02820       cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
02821    } else if (!strcasecmp(name, "answer")) {
02822       cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
02823    } else if (!strcasecmp(name, "end")) {
02824       cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
02825    } else if (!strcasecmp(name, "duration")) {
02826       snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
02827    } else if (!strcasecmp(name, "billsec")) {
02828       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);
02829    } else if (!strcasecmp(name, "disposition")) {
02830       if (raw) {
02831          snprintf(workspace, workspacelen, "%ld", cdr->disposition);
02832       } else {
02833          ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
02834       }
02835    } else if (!strcasecmp(name, "amaflags")) {
02836       if (raw) {
02837          snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
02838       } else {
02839          ast_copy_string(workspace, ast_channel_amaflags2string(cdr->amaflags), workspacelen);
02840       }
02841    } else if (!strcasecmp(name, "accountcode")) {
02842       ast_copy_string(workspace, cdr->accountcode, workspacelen);
02843    } else if (!strcasecmp(name, "peeraccount")) {
02844       ast_copy_string(workspace, cdr->peeraccount, workspacelen);
02845    } else if (!strcasecmp(name, "uniqueid")) {
02846       ast_copy_string(workspace, cdr->uniqueid, workspacelen);
02847    } else if (!strcasecmp(name, "linkedid")) {
02848       ast_copy_string(workspace, cdr->linkedid, workspacelen);
02849    } else if (!strcasecmp(name, "userfield")) {
02850       ast_copy_string(workspace, cdr->userfield, workspacelen);
02851    } else if (!strcasecmp(name, "sequence")) {
02852       snprintf(workspace, workspacelen, "%d", cdr->sequence);
02853    } else if ((varbuf = cdr_format_var_internal(cdr, name))) {
02854       ast_copy_string(workspace, varbuf, workspacelen);
02855    } else {
02856       workspace[0] = '\0';
02857    }
02858 
02859    if (!ast_strlen_zero(workspace)) {
02860       *ret = workspace;
02861    }
02862 }

void ast_cdr_free ( struct ast_cdr cdr  ) 

Free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing

Definition at line 3156 of file cdr.c.

References ast_free, free_variables(), ast_cdr::next, cdr_beitem::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().

03157 {
03158    while (cdr) {
03159       struct ast_cdr *next = cdr->next;
03160 
03161       free_variables(&cdr->varshead);
03162       ast_free(cdr);
03163       cdr = next;
03164    }
03165 }

struct ast_cdr_config* ast_cdr_get_config ( void   )  [read]

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:
NULL on error
The current CDR configuration

Definition at line 2611 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ao2_ref, and RAII_VAR.

Referenced by test_cdr_init_cb().

02612 {
02613    RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
02614    ao2_ref(mod_cfg->general, +1);
02615    return mod_cfg->general;
02616 }

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_name The name of the party A channel that the CDR is associated with
name The name of the variable to retrieve
value Buffer to hold the value
length The size of the buffer
Return values:
0 on success
non-zero on failure

Definition at line 3066 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(), cdr_object::last, and RAII_VAR.

Referenced by AST_TEST_DEFINE(), and cdr_read_callback().

03067 {
03068    RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
03069    struct cdr_object *cdr_obj;
03070 
03071    if (!cdr) {
03072       ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
03073       return 1;
03074    }
03075 
03076    if (ast_strlen_zero(name)) {
03077       return 1;
03078    }
03079 
03080    ao2_lock(cdr);
03081 
03082    cdr_obj = cdr->last;
03083    if (cdr_object_format_property(cdr_obj, name, value, length)) {
03084       /* Property failed; attempt variable */
03085       cdr_object_format_var_internal(cdr_obj, name, value, length);
03086    }
03087 
03088    ao2_unlock(cdr);
03089 
03090    return 0;
03091 }

int ast_cdr_is_enabled ( void   ) 

Return TRUE if CDR subsystem is enabled.

Definition at line 2629 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ast_test_flag, CDR_ENABLED, and RAII_VAR.

Referenced by action_coresettings(), and handle_show_settings().

02630 {
02631    RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
02632    return ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED);
02633 }

struct stasis_message_router* ast_cdr_message_router ( void   )  [read]

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:
NULL if the CDR engine is disabled or unavailable
the stasis_message_router otherwise

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

03975 {
03976    if (!stasis_router) {
03977       return NULL;
03978    }
03979 
03980    ao2_bump(stasis_router);
03981    return stasis_router;
03982 }

int ast_cdr_register ( const char *  name,
const char *  desc,
ast_cdrbe  be 
)

Register a CDR handling engine.

Parameters:
name name associated with the particular CDR handler
desc description of the CDR handler
be function pointer to a CDR handler Used to register a Call Detail Record handler.
Return values:
0 on success.
-1 on error

Definition at line 2671 of file cdr.c.

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

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

02672 {
02673    struct cdr_beitem *i = NULL;
02674 
02675    if (!name)
02676       return -1;
02677 
02678    if (!be) {
02679       ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
02680       return -1;
02681    }
02682 
02683    AST_RWLIST_WRLOCK(&be_list);
02684    AST_RWLIST_TRAVERSE(&be_list, i, list) {
02685       if (!strcasecmp(name, i->name)) {
02686          ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
02687          AST_RWLIST_UNLOCK(&be_list);
02688          return -1;
02689       }
02690    }
02691 
02692    if (!(i = ast_calloc(1, sizeof(*i))))
02693       return -1;
02694 
02695    i->be = be;
02696    ast_copy_string(i->name, name, sizeof(i->name));
02697    ast_copy_string(i->desc, desc, sizeof(i->desc));
02698 
02699    AST_RWLIST_INSERT_HEAD(&be_list, i, list);
02700    AST_RWLIST_UNLOCK(&be_list);
02701 
02702    return 0;
02703 }

int ast_cdr_reset ( const char *  channel_name,
int  keep_variables 
)

Reset the detail record.

Parameters:
channel_name The channel that the CDR is associated with
keep_variables Keep the variables during the reset. If zero, variables are discarded during the reset.
Return values:
0 on success
-1 on failure

Definition at line 3318 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::next, cdr_object::party_a, cdr_object::party_b, RAII_VAR, cdr_object::start, and cdr_object_snapshot::variables.

Referenced by appcdr_callback(), and dial_exec_full().

03319 {
03320    RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
03321    struct ast_var_t *vardata;
03322    struct cdr_object *it_cdr;
03323 
03324    if (!cdr) {
03325       return -1;
03326    }
03327 
03328    ao2_lock(cdr);
03329    for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
03330       /* clear variables */
03331       if (!keep_variables) {
03332          while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_a.variables, entries))) {
03333             ast_var_delete(vardata);
03334          }
03335          if (cdr->party_b.snapshot) {
03336             while ((vardata = AST_LIST_REMOVE_HEAD(&it_cdr->party_b.variables, entries))) {
03337                ast_var_delete(vardata);
03338             }
03339          }
03340       }
03341 
03342       /* Reset to initial state */
03343       memset(&it_cdr->start, 0, sizeof(it_cdr->start));
03344       memset(&it_cdr->end, 0, sizeof(it_cdr->end));
03345       memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
03346       it_cdr->start = ast_tvnow();
03347       cdr_object_check_party_a_answer(it_cdr);
03348    }
03349    ao2_unlock(cdr);
03350 
03351    return 0;
03352 }

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_name The channel to get the CDR for
buf A buffer to use for formatting the data
delim A delimeter to use to separate variable keys/values
sep A separator to use between nestings
Return values:
the total number of serialized variables

Definition at line 3093 of file cdr.c.

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

Referenced by handle_showchan().

03094 {
03095    RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
03096    struct cdr_object *it_cdr;
03097    struct ast_var_t *variable;
03098    const char *var;
03099    RAII_VAR(char *, workspace, ast_malloc(256), ast_free);
03100    int total = 0, x = 0, i;
03101 
03102    if (!workspace) {
03103       return 0;
03104    }
03105 
03106    if (!cdr) {
03107       RAII_VAR(struct module_config *, mod_cfg,
03108           ao2_global_obj_ref(module_configs), ao2_cleanup);
03109 
03110       if (ast_test_flag(&mod_cfg->general->settings, CDR_ENABLED)) {
03111          ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
03112       }
03113 
03114       return 0;
03115    }
03116 
03117    ast_str_reset(*buf);
03118 
03119    ao2_lock(cdr);
03120    for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
03121       if (++x > 1)
03122          ast_str_append(buf, 0, "\n");
03123 
03124       AST_LIST_TRAVERSE(&it_cdr->party_a.variables, variable, entries) {
03125          if (!(var = ast_var_name(variable))) {
03126             continue;
03127          }
03128 
03129          if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variable), ""), sep) < 0) {
03130             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
03131             break;
03132          }
03133 
03134          total++;
03135       }
03136 
03137       for (i = 0; cdr_readonly_vars[i]; i++) {
03138          if (cdr_object_format_property(it_cdr, cdr_readonly_vars[i], workspace, sizeof(workspace))) {
03139             /* Unhandled read-only CDR variable. */
03140             ast_assert(0);
03141             continue;
03142          }
03143 
03144          if (!ast_strlen_zero(workspace)
03145             && ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, workspace, sep) < 0) {
03146             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
03147             break;
03148          }
03149          total++;
03150       }
03151    }
03152    ao2_unlock(cdr);
03153    return total;
03154 }

void ast_cdr_set_config ( struct ast_cdr_config config  ) 

Set the current CDR configuration.

Since:
12
Parameters:
config The new CDR configuration

Definition at line 2618 of file cdr.c.

References ao2_cleanup, ao2_global_obj_ref, ao2_ref, cdr_toggle_runtime_options(), and RAII_VAR.

Referenced by test_cdr_cleanup_cb().

02619 {
02620    RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
02621 
02622    ao2_cleanup(mod_cfg->general);
02623    mod_cfg->general = config;
02624    ao2_ref(mod_cfg->general, +1);
02625 
02626    cdr_toggle_runtime_options();
02627 }

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_name The CDR's channel
option Option to apply to the CDR
Return values:
0 on success
1 on error

Definition at line 3272 of file cdr.c.

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

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

03273 {
03274    RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
03275    struct cdr_object *it_cdr;
03276 
03277    if (!cdr) {
03278       return -1;
03279    }
03280 
03281    ao2_lock(cdr);
03282    for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
03283       if (it_cdr->fn_table == &finalized_state_fn_table) {
03284          continue;
03285       }
03286       /* Note: in general, set the flags on both the CDR record as well as the
03287        * Party A. Sometimes all we have is the Party A to look at.
03288        */
03289       ast_set_flag(&it_cdr->flags, option);
03290       ast_set_flag(&it_cdr->party_a, option);
03291    }
03292    ao2_unlock(cdr);
03293 
03294    return 0;
03295 }

void ast_cdr_setuserfield ( const char *  channel_name,
const char *  userfield 
)

Set CDR user field for channel (stored in CDR).

Parameters:
channel_name The name of the channel that owns the CDR
userfield The user field to set

Definition at line 3217 of file cdr.c.

References active_cdrs_by_channel, ao2_callback, ao2_cleanup, ao2_lock, ao2_unlock, cdr_object_get_by_name(), cdr_object_update_party_b_userfield_cb(), party_b_userfield_update::channel_name, finalized_state_fn_table, cdr_object::fn_table, cdr_object::next, OBJ_NODATA, cdr_object::party_a, RAII_VAR, and cdr_object_snapshot::userfield.

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

03218 {
03219    RAII_VAR(struct cdr_object *, cdr, cdr_object_get_by_name(channel_name), ao2_cleanup);
03220    struct party_b_userfield_update party_b_info = {
03221          .channel_name = channel_name,
03222          .userfield = userfield,
03223    };
03224    struct cdr_object *it_cdr;
03225 
03226    /* Handle Party A */
03227    if (cdr) {
03228       ao2_lock(cdr);
03229       for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
03230          if (it_cdr->fn_table == &finalized_state_fn_table) {
03231             continue;
03232          }
03233          strcpy(it_cdr->party_a.userfield, userfield);
03234       }
03235       ao2_unlock(cdr);
03236    }
03237 
03238    /* Handle Party B */
03239    ao2_callback(active_cdrs_by_channel, OBJ_NODATA,
03240          cdr_object_update_party_b_userfield_cb,
03241          &party_b_info);
03242 
03243 }

int ast_cdr_setvar ( const char *  channel_name,
const char *  name,
const char *  value 
)

Set a variable on a CDR.

Since:
12
Parameters:
channel_name The channel to set the variable on
name The name of the variable to set
value The value of the variable to set
Return values:
0 on success
non-zero on failure

Definition at line 2920 of file cdr.c.

References active_cdrs_by_channel, ao2_callback, ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_log, AST_LOG_ERROR, ast_strdupa, cdr_object_select_all_by_name_cb(), cdr_readonly_vars, finalized_state_fn_table, cdr_object::fn_table, LOG_ERROR, ast_channel_snapshot::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().

02921 {
02922    struct cdr_object *cdr;
02923    struct cdr_object *it_cdr;
02924    struct ao2_iterator *it_cdrs;
02925    char *arg = ast_strdupa(channel_name);
02926    int x;
02927 
02928    for (x = 0; cdr_readonly_vars[x]; x++) {
02929       if (!strcasecmp(name, cdr_readonly_vars[x])) {
02930          ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!\n", name);
02931          return -1;
02932       }
02933    }
02934 
02935    it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE, cdr_object_select_all_by_name_cb, arg);
02936    if (!it_cdrs) {
02937       ast_log(AST_LOG_ERROR, "Unable to find CDR for channel %s\n", channel_name);
02938       return -1;
02939    }
02940 
02941    for (; (cdr = ao2_iterator_next(it_cdrs)); ao2_unlock(cdr), ao2_cleanup(cdr)) {
02942       ao2_lock(cdr);
02943       for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
02944          struct varshead *headp = NULL;
02945 
02946          if (it_cdr->fn_table == &finalized_state_fn_table) {
02947             continue;
02948          }
02949          if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->name)) {
02950             headp = &it_cdr->party_a.variables;
02951          } else if (it_cdr->party_b.snapshot
02952             && !strcasecmp(channel_name, it_cdr->party_b.snapshot->name)) {
02953             headp = &it_cdr->party_b.variables;
02954          }
02955          if (headp) {
02956             set_variable(headp, name, value);
02957          }
02958       }
02959    }
02960    ao2_iterator_destroy(it_cdrs);
02961 
02962    return 0;
02963 }

int ast_cdr_unregister ( const char *  name  ) 

Unregister a CDR handling engine.

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

Definition at line 2705 of file cdr.c.

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

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

02706 {
02707    struct cdr_beitem *match = NULL;
02708    int active_count;
02709 
02710    AST_RWLIST_WRLOCK(&be_list);
02711    AST_RWLIST_TRAVERSE(&be_list, match, list) {
02712       if (!strcasecmp(name, match->name)) {
02713          break;
02714       }
02715    }
02716 
02717    if (!match) {
02718       AST_RWLIST_UNLOCK(&be_list);
02719       return 0;
02720    }
02721 
02722    active_count = ao2_container_count(active_cdrs_by_channel);
02723 
02724    if (!match->suspended && active_count != 0) {
02725       AST_RWLIST_UNLOCK(&be_list);
02726       ast_log(AST_LOG_WARNING, "Unable to unregister CDR backend %s; %d CDRs are still active\n",
02727          name, active_count);
02728       return -1;
02729    }
02730 
02731    AST_RWLIST_REMOVE(&be_list, match, list);
02732    AST_RWLIST_UNLOCK(&be_list);
02733 
02734    ast_verb(2, "Unregistered '%s' CDR backend\n", name);
02735    ast_free(match);
02736 
02737    return 0;
02738 }


Generated on Thu Apr 16 06:29:23 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6