Call Detail Record API. More...
#include <sys/time.h>
#include "asterisk/channel.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Data Structures | |
struct | ast_cdr |
Responsible for call detail data. More... | |
Defines | |
#define | AST_MAX_ACCOUNT_CODE 20 |
#define | AST_MAX_USER_FIELD 256 |
CDR Flags | |
#define | AST_CDR_FLAG_KEEP_VARS (1 << 0) |
#define | AST_CDR_FLAG_POSTED (1 << 1) |
#define | AST_CDR_FLAG_LOCKED (1 << 2) |
#define | AST_CDR_FLAG_CHILD (1 << 3) |
#define | AST_CDR_FLAG_POST_DISABLED (1 << 4) |
#define | AST_CDR_FLAG_BRIDGED (1 << 5) |
#define | AST_CDR_FLAG_MAIN (1 << 6) |
#define | AST_CDR_FLAG_ENABLE (1 << 7) |
#define | AST_CDR_FLAG_ANSLOCKED (1 << 8) |
#define | AST_CDR_FLAG_DONT_TOUCH (1 << 9) |
#define | AST_CDR_FLAG_POST_ENABLE (1 << 10) |
#define | AST_CDR_FLAG_DIALED (1 << 11) |
#define | AST_CDR_FLAG_ORIGINATED (1 << 12) |
CDR Flags - Disposition | |
#define | AST_CDR_NOANSWER 0 |
#define | AST_CDR_NULL (1 << 0) |
#define | AST_CDR_FAILED (1 << 1) |
#define | AST_CDR_BUSY (1 << 2) |
#define | AST_CDR_ANSWERED (1 << 3) |
CDR AMA Flags | |
#define | AST_CDR_OMIT (1) |
#define | AST_CDR_BILLING (2) |
#define | AST_CDR_DOCUMENTATION (3) |
Typedefs | |
typedef int(* | ast_cdrbe )(struct ast_cdr *cdr) |
CDR backend callback. | |
Functions | |
struct ast_cdr * | ast_cdr_alloc (void) |
Allocate a CDR record. | |
int | ast_cdr_amaflags2int (const char *flag) |
Convert a string to a detail record AMA flag. | |
void | ast_cdr_answer (struct ast_cdr *cdr) |
Answer a call. | |
struct ast_cdr * | ast_cdr_append (struct ast_cdr *cdr, struct ast_cdr *newcdr) |
int | ast_cdr_appenduserfield (struct ast_channel *chan, const char *userfield) |
Append to CDR user field for channel (stored in CDR) | |
void | ast_cdr_busy (struct ast_cdr *cdr) |
Busy a call. | |
int | ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr) |
void | ast_cdr_detach (struct ast_cdr *cdr) |
Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other records during batch mode operation. | |
void | ast_cdr_discard (struct ast_cdr *cdr) |
Discard and free a CDR record. | |
char * | ast_cdr_disp2str (int disposition) |
Disposition to a string. | |
int | ast_cdr_disposition (struct ast_cdr *cdr, int cause) |
Save the result of the call based on the AST_CAUSE_*. | |
struct ast_cdr * | ast_cdr_dup (struct ast_cdr *cdr) |
Duplicate a record. | |
void | ast_cdr_end (struct ast_cdr *cdr) |
End a call. | |
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) |
void | ast_cdr_failed (struct ast_cdr *cdr) |
Fail a call. | |
char * | ast_cdr_flags2str (int flags) |
void | ast_cdr_free (struct ast_cdr *cdr) |
Free a CDR record. | |
void | ast_cdr_free_vars (struct ast_cdr *cdr, int recur) |
void | ast_cdr_getvar (struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw) |
int | ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *chan) |
Initialize based on a channel. | |
int | ast_cdr_isset_unanswered (void) |
void | ast_cdr_merge (struct ast_cdr *to, struct ast_cdr *from) |
Move the non-null data from the "from" cdr to the "to" cdr. | |
void | ast_cdr_noanswer (struct ast_cdr *cdr) |
A call wasn't answered. | |
int | ast_cdr_register (const char *name, const char *desc, ast_cdrbe be) |
Register a CDR handling engine. | |
void | ast_cdr_reset (struct ast_cdr *cdr, struct ast_flags *flags) |
Reset the detail record, optionally posting it first. | |
int | ast_cdr_serialize_variables (struct ast_cdr *cdr, struct ast_str **buf, char delim, char sep, int recur) |
int | ast_cdr_setaccount (struct ast_channel *chan, const char *account) |
Set account code, will generate AMI event. | |
int | ast_cdr_setamaflags (struct ast_channel *chan, const char *amaflags) |
Set AMA flags for channel. | |
void | ast_cdr_setanswer (struct ast_cdr *cdr, struct timeval t) |
Set the answer time for a call. | |
void | ast_cdr_setapp (struct ast_cdr *cdr, const char *app, const char *data) |
Set the last executed application. | |
int | ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *chan) |
Initialize based on a channel. | |
void | ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chan) |
Set the destination channel, if there was one. | |
void | ast_cdr_setdisposition (struct ast_cdr *cdr, long int disposition) |
Set the disposition for a call. | |
int | ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield) |
Set CDR user field for channel (stored in CDR) | |
int | ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur) |
void | ast_cdr_specialized_reset (struct ast_cdr *cdr, struct ast_flags *flags) |
void | ast_cdr_start (struct ast_cdr *cdr) |
Start a call. | |
void | ast_cdr_submit_batch (int shutdown) |
Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines. | |
void | ast_cdr_unregister (const char *name) |
Unregister a CDR handling engine. | |
int | ast_cdr_update (struct ast_channel *chan) |
int | check_cdr_enabled (void) |
Return TRUE if CDR subsystem is enabled. | |
Variables | |
char | ast_default_accountcode [AST_MAX_ACCOUNT_CODE] |
int | ast_default_amaflags |
Call Detail Record API.
Definition in file cdr.h.
#define AST_CDR_ANSWERED (1 << 3) |
Definition at line 51 of file cdr.h.
Referenced by ast_bridge_call(), ast_cdr_answer(), ast_cdr_disp2str(), ast_cdr_end(), ast_cdr_init(), post_cdr(), and wait_for_answer().
#define AST_CDR_BILLING (2) |
Definition at line 57 of file cdr.h.
Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str().
#define AST_CDR_BUSY (1 << 2) |
Definition at line 50 of file cdr.h.
Referenced by ast_cdr_busy(), and ast_cdr_disp2str().
#define AST_CDR_DOCUMENTATION (3) |
Definition at line 58 of file cdr.h.
Referenced by ast_cdr_amaflags2int(), ast_cdr_flags2str(), and ast_cdr_merge().
#define AST_CDR_FAILED (1 << 1) |
Definition at line 49 of file cdr.h.
Referenced by ast_cdr_disp2str(), ast_cdr_end(), and ast_cdr_failed().
#define AST_CDR_FLAG_ANSLOCKED (1 << 8) |
Definition at line 38 of file cdr.h.
Referenced by ast_cdr_answer(), ast_cdr_fork(), and ast_cdr_setanswer().
#define AST_CDR_FLAG_BRIDGED (1 << 5) |
Definition at line 35 of file cdr.h.
Referenced by ast_bridge_call(), and ast_hangup().
#define AST_CDR_FLAG_CHILD (1 << 3) |
Definition at line 33 of file cdr.h.
Referenced by ast_cdr_fork(), and ast_cdr_merge().
#define AST_CDR_FLAG_DIALED (1 << 11) |
Definition at line 41 of file cdr.h.
Referenced by ast_bridge_call(), ast_call(), ast_hangup(), dial_exec_full(), and post_cdr().
#define AST_CDR_FLAG_DONT_TOUCH (1 << 9) |
Definition at line 39 of file cdr.h.
Referenced by ast_cdr_answer(), ast_cdr_end(), ast_cdr_fork(), ast_cdr_setanswer(), and ast_cdr_setvar().
#define AST_CDR_FLAG_KEEP_VARS (1 << 0) |
Definition at line 30 of file cdr.h.
Referenced by ast_cdr_fork(), ast_cdr_merge(), ast_cdr_reset(), and forkcdr_exec().
#define AST_CDR_FLAG_LOCKED (1 << 2) |
Definition at line 32 of file cdr.h.
Referenced by ast_cdr_answer(), ast_cdr_appenduserfield(), ast_cdr_busy(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_fork(), ast_cdr_init(), ast_cdr_merge(), ast_cdr_noanswer(), ast_cdr_reset(), ast_cdr_setaccount(), ast_cdr_setamaflags(), ast_cdr_setanswer(), ast_cdr_setapp(), ast_cdr_setcid(), ast_cdr_setdestchan(), ast_cdr_setdisposition(), ast_cdr_setuserfield(), ast_cdr_setvar(), ast_cdr_start(), ast_cdr_update(), cdr_read(), pick_unlocked_cdr(), and try_calling().
#define AST_CDR_FLAG_MAIN (1 << 6) |
Definition at line 36 of file cdr.h.
Referenced by ast_bridge_call().
#define AST_CDR_FLAG_ORIGINATED (1 << 12) |
Definition at line 42 of file cdr.h.
Referenced by __ast_request_and_dial(), ast_call_forward(), and post_cdr().
#define AST_CDR_FLAG_POST_DISABLED (1 << 4) |
Definition at line 34 of file cdr.h.
Referenced by ast_bridge_call(), ast_cdr_detach(), ast_cdr_merge(), ast_cdr_reset(), ast_cdr_specialized_reset(), ast_hangup(), connect_link(), nocdr_exec(), post_cdr(), rpt(), rpt_call(), rpt_exec(), rpt_tele_thread(), and try_calling().
#define AST_CDR_FLAG_POST_ENABLE (1 << 10) |
Definition at line 40 of file cdr.h.
Referenced by ast_cdr_reset().
#define AST_CDR_FLAG_POSTED (1 << 1) |
Definition at line 31 of file cdr.h.
Referenced by ast_cdr_merge(), ast_cdr_reset(), check_post(), disa_exec(), and post_cdr().
#define AST_CDR_NOANSWER 0 |
Definition at line 47 of file cdr.h.
Referenced by ast_cdr_disp2str(), ast_cdr_init(), ast_cdr_merge(), ast_cdr_noanswer(), and ast_cdr_reset().
#define AST_CDR_NULL (1 << 0) |
Definition at line 48 of file cdr.h.
Referenced by ast_bridge_call(), ast_cdr_disp2str(), ast_cdr_specialized_reset(), and ast_hangup().
#define AST_CDR_OMIT (1) |
Definition at line 56 of file cdr.h.
Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str().
struct ast_cdr* ast_cdr_alloc | ( | void | ) | [read] |
Allocate a CDR record.
a | malloc'd ast_cdr structure |
NULL | on error (malloc failure) |
Definition at line 460 of file cdr.c.
References ast_calloc, ast_log(), and LOG_ERROR.
Referenced by __agent_start_monitoring(), __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_dup(), builtin_blindtransfer(), clear_caller(), findmeexec(), and start_monitor_exec().
{ struct ast_cdr *x; x = ast_calloc(1, sizeof(*x)); if (!x) ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n"); return x; }
int ast_cdr_amaflags2int | ( | const char * | flag | ) |
Convert a string to a detail record AMA flag.
flag | string form of flag Converts the string form of the flag to the binary form. |
Definition at line 1021 of file cdr.c.
References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
Referenced by ast_cdr_setamaflags(), build_device(), build_gateway(), build_peer(), build_user(), config_parse_variables(), process_dahdi(), and set_config().
{ if (!strcasecmp(flag, "default")) return 0; if (!strcasecmp(flag, "omit")) return AST_CDR_OMIT; if (!strcasecmp(flag, "billing")) return AST_CDR_BILLING; if (!strcasecmp(flag, "documentation")) return AST_CDR_DOCUMENTATION; return -1; }
void ast_cdr_answer | ( | struct ast_cdr * | cdr | ) |
Answer a call.
cdr | the cdr you wish to associate with the call Starts all CDR stuff necessary for doing CDR when answering a call |
Definition at line 695 of file cdr.c.
References ast_cdr::answer, AST_CDR_ANSWERED, AST_CDR_FLAG_ANSLOCKED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_test_flag, ast_tvnow(), ast_tvzero(), check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_bridge_call(), and ast_raw_answer().
{ for (; cdr; cdr = cdr->next) { if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) continue; if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) continue; check_post(cdr); if (cdr->disposition < AST_CDR_ANSWERED) cdr->disposition = AST_CDR_ANSWERED; if (ast_tvzero(cdr->answer)) cdr->answer = ast_tvnow(); } }
Definition at line 1134 of file cdr.c.
References ast_cdr::next.
Referenced by ast_cdr_fork(), ast_cdr_merge(), and attempt_transfer().
int ast_cdr_appenduserfield | ( | struct ast_channel * | chan, |
const char * | userfield | ||
) |
Append to CDR user field for channel (stored in CDR)
Definition at line 987 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, ast_channel::cdr, len(), ast_cdr::next, and ast_cdr::userfield.
{ struct ast_cdr *cdr = chan->cdr; for ( ; cdr ; cdr = cdr->next) { int len = strlen(cdr->userfield); if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len); } return 0; }
void ast_cdr_busy | ( | struct ast_cdr * | cdr | ) |
Busy a call.
cdr | the cdr you wish to associate with the call Marks the channel disposition as "BUSY" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. Returns nothing |
Definition at line 711 of file cdr.c.
References AST_CDR_BUSY, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_cdr_disposition(), handle_cause(), pbx_builtin_busy(), ring_entry(), and wait_for_answer().
{ for (; cdr; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { check_post(cdr); cdr->disposition = AST_CDR_BUSY; } } }
Definition at line 344 of file cdr.c.
References AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_assign(), ast_var_name(), ast_var_value(), val, var, and ast_cdr::varshead.
Referenced by ast_cdr_dup().
{ struct ast_var_t *variables, *newvariable = NULL; struct varshead *headpa, *headpb; const char *var, *val; int x = 0; if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */ return 0; headpa = &from_cdr->varshead; headpb = &to_cdr->varshead; AST_LIST_TRAVERSE(headpa,variables,entries) { if (variables && (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && !ast_strlen_zero(var) && !ast_strlen_zero(val)) { newvariable = ast_var_assign(var, val); AST_LIST_INSERT_HEAD(headpb, newvariable, entries); x++; } } return x; }
void ast_cdr_detach | ( | struct ast_cdr * | cdr | ) |
Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other records during batch mode operation.
cdr | Which CDR to detach from the channel thread Prevents the channel thread from blocking on the CDR handling Returns nothing |
Definition at line 1239 of file cdr.c.
References ast_calloc, AST_CDR_FLAG_POST_DISABLED, ast_cdr_free(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, batch, batchmode, batchsize, ast_cdr_batch_item::cdr, cdr_batch_lock, enabled, ast_cdr_batch::head, init_batch(), ast_cdr_batch_item::next, post_cdr(), ast_cdr_batch::size, submit_unscheduled_batch(), and ast_cdr_batch::tail.
Referenced by ast_bridge_call(), ast_cdr_reset(), ast_hangup(), and ast_pbx_outgoing_cdr_failed().
{ struct ast_cdr_batch_item *newtail; int curr; if (!cdr) return; /* maybe they disabled CDR stuff completely, so just drop it */ if (!enabled) { ast_debug(1, "Dropping CDR !\n"); ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); ast_cdr_free(cdr); return; } /* post stuff immediately if we are not in batch mode, this is legacy behaviour */ if (!batchmode) { post_cdr(cdr); ast_cdr_free(cdr); return; } /* otherwise, each CDR gets put into a batch list (at the end) */ ast_debug(1, "CDR detaching from this thread\n"); /* we'll need a new tail for every CDR */ if (!(newtail = ast_calloc(1, sizeof(*newtail)))) { post_cdr(cdr); ast_cdr_free(cdr); return; } /* don't traverse a whole list (just keep track of the tail) */ ast_mutex_lock(&cdr_batch_lock); if (!batch) init_batch(); if (!batch->head) { /* new batch is empty, so point the head at the new tail */ batch->head = newtail; } else { /* already got a batch with something in it, so just append a new tail */ batch->tail->next = newtail; } newtail->cdr = cdr; batch->tail = newtail; curr = batch->size++; ast_mutex_unlock(&cdr_batch_lock); /* if we have enough stuff to post, then do it */ if (curr >= (batchsize - 1)) submit_unscheduled_batch(); }
void ast_cdr_discard | ( | struct ast_cdr * | cdr | ) |
Discard and free a CDR record.
cdr | ast_cdr structure to free Returns nothing -- same as free, but no checks or complaints |
Definition at line 449 of file cdr.c.
References ast_cdr_free_vars(), ast_free, and ast_cdr::next.
Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_merge(), and ast_channel_free().
char* ast_cdr_disp2str | ( | int | disposition | ) |
Disposition to a string.
disposition | input binary form Converts the binary form of a disposition to string form. |
Definition at line 910 of file cdr.c.
References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, AST_CDR_NOANSWER, and AST_CDR_NULL.
Referenced by ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), execute_cb(), manager_log(), and tds_log().
{ switch (disposition) { case AST_CDR_NULL: return "NO ANSWER"; /* by default, for backward compatibility */ case AST_CDR_NOANSWER: return "NO ANSWER"; case AST_CDR_FAILED: return "FAILED"; case AST_CDR_BUSY: return "BUSY"; case AST_CDR_ANSWERED: return "ANSWERED"; } return "UNKNOWN"; }
int ast_cdr_disposition | ( | struct ast_cdr * | cdr, |
int | cause | ||
) |
Save the result of the call based on the AST_CAUSE_*.
cdr | the cdr you wish to associate with the call |
cause | the AST_CAUSE_* Returns nothing |
Definition at line 751 of file cdr.c.
References AST_CAUSE_BUSY, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL, ast_cdr_busy(), ast_cdr_noanswer(), and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), clear_caller(), and findmeexec().
{ int res = 0; for (; cdr; cdr = cdr->next) { switch (cause) { /* handle all the non failure, busy cases, return 0 not to set disposition, return -1 to set disposition to FAILED */ case AST_CAUSE_BUSY: ast_cdr_busy(cdr); break; case AST_CAUSE_NO_ANSWER: ast_cdr_noanswer(cdr); break; case AST_CAUSE_NORMAL: break; default: res = -1; } } return res; }
Duplicate a record.
a | malloc'd ast_cdr structure, |
NULL | on error (malloc failure) |
Duplicate a CDR record
Definition at line 176 of file cdr.c.
References ast_cdr_alloc(), ast_cdr_copy_vars(), ast_cdr::next, and ast_cdr::varshead.
Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_merge(), and ast_cdr_reset().
{ struct ast_cdr *newcdr; if (!cdr) /* don't die if we get a null cdr pointer */ return NULL; newcdr = ast_cdr_alloc(); if (!newcdr) return NULL; memcpy(newcdr, cdr, sizeof(*newcdr)); /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */ memset(&newcdr->varshead, 0, sizeof(newcdr->varshead)); ast_cdr_copy_vars(newcdr, cdr); newcdr->next = NULL; return newcdr; }
void ast_cdr_end | ( | struct ast_cdr * | cdr | ) |
End a call.
cdr | the cdr you have associated the call with Registers the end of call time in the cdr structure. Returns nothing |
Definition at line 884 of file cdr.c.
References ast_cdr::answer, AST_CDR_ANSWERED, AST_CDR_FAILED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_log(), AST_OPT_FLAG_INITIATED_SECONDS, ast_options, ast_test_flag, ast_tvnow(), ast_tvzero(), ast_cdr::billsec, ast_cdr::channel, check_post(), ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, LOG_WARNING, ast_cdr::next, S_OR, and ast_cdr::start.
Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_reset(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), clear_caller(), and findmeexec().
{ for ( ; cdr ; cdr = cdr->next) { if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) continue; check_post(cdr); if (ast_tvzero(cdr->end)) cdr->end = ast_tvnow(); if (ast_tvzero(cdr->start)) { ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>")); cdr->disposition = AST_CDR_FAILED; } else cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec; if (ast_tvzero(cdr->answer)) { if (cdr->disposition == AST_CDR_ANSWERED) { ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>")); cdr->disposition = AST_CDR_FAILED; } } else { cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec; if (ast_test_flag(&ast_options, AST_OPT_FLAG_INITIATED_SECONDS)) cdr->billsec += cdr->end.tv_usec > cdr->answer.tv_usec ? 1 : 0; } } }
int ast_cdr_engine_init | ( | void | ) |
Load the configuration file cdr.conf and possibly start the CDR scheduling thread.
Definition at line 1532 of file cdr.c.
References ast_cli_register(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cdr_batch_lock, cli_status, do_reload(), init_batch(), LOG_ERROR, and sched_context_create().
Referenced by main().
{ int res; sched = sched_context_create(); if (!sched) { ast_log(LOG_ERROR, "Unable to create schedule context.\n"); return -1; } ast_cli_register(&cli_status); res = do_reload(0); if (res) { ast_mutex_lock(&cdr_batch_lock); res = init_batch(); ast_mutex_unlock(&cdr_batch_lock); } return res; }
int ast_cdr_engine_reload | ( | void | ) |
Reload the configuration file cdr.conf and start/stop CDR scheduling thread.
Definition at line 1561 of file cdr.c.
References do_reload().
{ return do_reload(1); }
void ast_cdr_engine_term | ( | void | ) |
Submit any remaining CDRs and prepare for shutdown
Definition at line 1556 of file cdr.c.
References ast_cdr_submit_batch(), and batchsafeshutdown.
Referenced by do_reload(), and quit_handler().
void ast_cdr_failed | ( | struct ast_cdr * | cdr | ) |
Fail a call.
cdr | the cdr you wish to associate with the call Marks the channel disposition as "FAILED" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. Returns nothing |
Definition at line 722 of file cdr.c.
References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), clear_caller(), findmeexec(), handle_cause(), try_calling(), and wait_for_answer().
{ for (; cdr; cdr = cdr->next) { check_post(cdr); if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { check_post(cdr); if (cdr->disposition < AST_CDR_FAILED) cdr->disposition = AST_CDR_FAILED; } } }
char* ast_cdr_flags2str | ( | int | flag | ) |
Flags to a string
flags | binary flag Converts binary flags to string flags Returns string with flag name |
Converts AMA flag to printable string
Definition at line 928 of file cdr.c.
References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
Referenced by _sip_show_peer(), _skinny_show_line(), ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), manager_log(), sip_show_user(), and tds_log().
{ switch (flag) { case AST_CDR_OMIT: return "OMIT"; case AST_CDR_BILLING: return "BILLING"; case AST_CDR_DOCUMENTATION: return "DOCUMENTATION"; } return "Unknown"; }
void ast_cdr_free | ( | struct ast_cdr * | cdr | ) |
Free a CDR record.
cdr | ast_cdr structure to free Returns nothing |
Definition at line 436 of file cdr.c.
References ast_cdr_free_vars(), ast_free, and ast_cdr::next.
Referenced by ast_cdr_detach(), and do_batch_backend_process().
void ast_cdr_free_vars | ( | struct ast_cdr * | cdr, |
int | recur | ||
) |
Definition at line 415 of file cdr.c.
References AST_LIST_REMOVE_HEAD, ast_var_delete(), ast_cdr::next, and ast_cdr::varshead.
Referenced by ast_cdr_discard(), ast_cdr_fork(), ast_cdr_free(), and ast_cdr_reset().
{ /* clear variables */ for (; cdr; cdr = recur ? cdr->next : NULL) { struct ast_var_t *vardata; struct varshead *headp = &cdr->varshead; while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) ast_var_delete(vardata); } }
void ast_cdr_getvar | ( | struct ast_cdr * | cdr, |
const char * | name, | ||
char ** | ret, | ||
char * | workspace, | ||
int | workspacelen, | ||
int | recur, | ||
int | raw | ||
) |
CDR channel variable retrieval
Definition at line 227 of file cdr.c.
References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_disp2str(), ast_cdr_flags2str(), ast_cdr_getvar_internal(), ast_copy_string(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_cdr::billsec, 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::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.
Referenced by ast_cdr_serialize_variables(), cdr_handler(), cdr_read(), odbc_log(), and pgsql_log().
{ const char *fmt = "%Y-%m-%d %T"; const char *varbuf; if (!cdr) /* don't die if the cdr is null */ return; *ret = NULL; /* special vars (the ones from the struct ast_cdr when requested by name) I'd almost say we should convert all the stringed vals to vars */ if (!strcasecmp(name, "clid")) ast_copy_string(workspace, cdr->clid, workspacelen); else if (!strcasecmp(name, "src")) ast_copy_string(workspace, cdr->src, workspacelen); else if (!strcasecmp(name, "dst")) ast_copy_string(workspace, cdr->dst, workspacelen); else if (!strcasecmp(name, "dcontext")) ast_copy_string(workspace, cdr->dcontext, workspacelen); else if (!strcasecmp(name, "channel")) ast_copy_string(workspace, cdr->channel, workspacelen); else if (!strcasecmp(name, "dstchannel")) ast_copy_string(workspace, cdr->dstchannel, workspacelen); else if (!strcasecmp(name, "lastapp")) ast_copy_string(workspace, cdr->lastapp, workspacelen); else if (!strcasecmp(name, "lastdata")) ast_copy_string(workspace, cdr->lastdata, workspacelen); else if (!strcasecmp(name, "start")) cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen); else if (!strcasecmp(name, "answer")) cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen); else if (!strcasecmp(name, "end")) cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen); else if (!strcasecmp(name, "duration")) snprintf(workspace, workspacelen, "%ld", cdr->duration ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000); else if (!strcasecmp(name, "billsec")) snprintf(workspace, workspacelen, "%ld", cdr->billsec || cdr->answer.tv_sec == 0 ? cdr->billsec : (long)ast_tvdiff_ms(ast_tvnow(), cdr->answer) / 1000); else if (!strcasecmp(name, "disposition")) { if (raw) { snprintf(workspace, workspacelen, "%ld", cdr->disposition); } else { ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); } } else if (!strcasecmp(name, "amaflags")) { if (raw) { snprintf(workspace, workspacelen, "%ld", cdr->amaflags); } else { ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); } } else if (!strcasecmp(name, "accountcode")) ast_copy_string(workspace, cdr->accountcode, workspacelen); else if (!strcasecmp(name, "uniqueid")) ast_copy_string(workspace, cdr->uniqueid, workspacelen); else if (!strcasecmp(name, "userfield")) ast_copy_string(workspace, cdr->userfield, workspacelen); else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) ast_copy_string(workspace, varbuf, workspacelen); else workspace[0] = '\0'; if (!ast_strlen_zero(workspace)) *ret = workspace; }
int ast_cdr_init | ( | struct ast_cdr * | cdr, |
struct ast_channel * | chan | ||
) |
Initialize based on a channel.
cdr | Call Detail Record to use for channel |
chan | Channel to bind CDR with Initializes a CDR and associates it with a particular channel |
Definition at line 849 of file cdr.c.
References ast_channel::_state, ast_channel::accountcode, ast_cdr::accountcode, ast_channel::amaflags, ast_cdr::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_copy_string(), ast_default_amaflags, AST_STATE_UP, ast_test_flag, chan, ast_cdr::channel, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::name, ast_cdr::next, S_OR, set_one_cid(), ast_channel::uniqueid, and ast_cdr::uniqueid.
Referenced by __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().
{ char *chan; for ( ; cdr ; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { chan = S_OR(cdr->channel, "<unknown>"); ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); set_one_cid(cdr, c); cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); /* Destination information */ ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst)); ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext)); /* Unique call identifier */ ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid)); } } return 0; }
int ast_cdr_isset_unanswered | ( | void | ) |
Definition at line 168 of file cdr.c.
References unanswered.
Referenced by ring_entry(), and try_calling().
{ return unanswered; }
Move the non-null data from the "from" cdr to the "to" cdr.
to | the cdr to get the goodies |
from | the cdr to give the goodies |
Definition at line 504 of file cdr.c.
References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_append(), ast_cdr_discard(), AST_CDR_DOCUMENTATION, ast_cdr_dup(), AST_CDR_FLAG_CHILD, AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, AST_CDR_NOANSWER, ast_copy_string(), ast_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_tv(), ast_tvcmp(), ast_tvzero(), ast_cdr::billsec, cdr_merge_vars(), 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, LOG_WARNING, ast_cdr::next, ast_cdr::src, ast_cdr::start, and ast_cdr::userfield.
{ struct ast_cdr *zcdr; struct ast_cdr *lto = NULL; struct ast_cdr *lfrom = NULL; int discard_from = 0; if (!to || !from) return; /* don't merge into locked CDR's -- it's bad business */ if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { zcdr = to; /* safety valve? */ while (to->next) { lto = to; to = to->next; } if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { ast_log(LOG_WARNING, "Merging into locked CDR... no choice."); to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */ lto = NULL; } } if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) { struct ast_cdr *llfrom = NULL; discard_from = 1; if (lto) { /* insert the from stuff after lto */ lto->next = from; lfrom = from; while (lfrom && lfrom->next) { if (!lfrom->next->next) llfrom = lfrom; lfrom = lfrom->next; } /* rip off the last entry and put a copy of the to at the end */ llfrom->next = to; from = lfrom; } else { /* save copy of the current *to cdr */ struct ast_cdr tcdr; memcpy(&tcdr, to, sizeof(tcdr)); /* copy in the locked from cdr */ memcpy(to, from, sizeof(*to)); lfrom = from; while (lfrom && lfrom->next) { if (!lfrom->next->next) llfrom = lfrom; lfrom = lfrom->next; } from->next = NULL; /* rip off the last entry and put a copy of the to at the end */ if (llfrom == from) to = to->next = ast_cdr_dup(&tcdr); else to = llfrom->next = ast_cdr_dup(&tcdr); from = lfrom; } } if (!ast_tvzero(from->start)) { if (!ast_tvzero(to->start)) { if (ast_tvcmp(to->start, from->start) > 0 ) { to->start = from->start; /* use the earliest time */ from->start = ast_tv(0,0); /* we actively "steal" these values */ } /* else nothing to do */ } else { to->start = from->start; from->start = ast_tv(0,0); /* we actively "steal" these values */ } } if (!ast_tvzero(from->answer)) { if (!ast_tvzero(to->answer)) { if (ast_tvcmp(to->answer, from->answer) > 0 ) { to->answer = from->answer; /* use the earliest time */ from->answer = ast_tv(0,0); /* we actively "steal" these values */ } /* we got the earliest answer time, so we'll settle for that? */ } else { to->answer = from->answer; from->answer = ast_tv(0,0); /* we actively "steal" these values */ } } if (!ast_tvzero(from->end)) { if (!ast_tvzero(to->end)) { if (ast_tvcmp(to->end, from->end) < 0 ) { to->end = from->end; /* use the latest time */ from->end = ast_tv(0,0); /* we actively "steal" these values */ to->duration = to->end.tv_sec - to->start.tv_sec; /* don't forget to update the duration, billsec, when we set end */ to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; } /* else, nothing to do */ } else { to->end = from->end; from->end = ast_tv(0,0); /* we actively "steal" these values */ to->duration = to->end.tv_sec - to->start.tv_sec; to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; } } if (to->disposition < from->disposition) { to->disposition = from->disposition; from->disposition = AST_CDR_NOANSWER; } if (ast_strlen_zero(to->lastapp) && !ast_strlen_zero(from->lastapp)) { ast_copy_string(to->lastapp, from->lastapp, sizeof(to->lastapp)); from->lastapp[0] = 0; /* theft */ } if (ast_strlen_zero(to->lastdata) && !ast_strlen_zero(from->lastdata)) { ast_copy_string(to->lastdata, from->lastdata, sizeof(to->lastdata)); from->lastdata[0] = 0; /* theft */ } if (ast_strlen_zero(to->dcontext) && !ast_strlen_zero(from->dcontext)) { ast_copy_string(to->dcontext, from->dcontext, sizeof(to->dcontext)); from->dcontext[0] = 0; /* theft */ } if (ast_strlen_zero(to->dstchannel) && !ast_strlen_zero(from->dstchannel)) { ast_copy_string(to->dstchannel, from->dstchannel, sizeof(to->dstchannel)); from->dstchannel[0] = 0; /* theft */ } if (!ast_strlen_zero(from->channel) && (ast_strlen_zero(to->channel) || !strncasecmp(from->channel, "Agent/", 6))) { ast_copy_string(to->channel, from->channel, sizeof(to->channel)); from->channel[0] = 0; /* theft */ } if (ast_strlen_zero(to->src) && !ast_strlen_zero(from->src)) { ast_copy_string(to->src, from->src, sizeof(to->src)); from->src[0] = 0; /* theft */ } if (ast_strlen_zero(to->clid) && !ast_strlen_zero(from->clid)) { ast_copy_string(to->clid, from->clid, sizeof(to->clid)); from->clid[0] = 0; /* theft */ } if (ast_strlen_zero(to->dst) && !ast_strlen_zero(from->dst)) { ast_copy_string(to->dst, from->dst, sizeof(to->dst)); from->dst[0] = 0; /* theft */ } if (!to->amaflags) to->amaflags = AST_CDR_DOCUMENTATION; if (!from->amaflags) from->amaflags = AST_CDR_DOCUMENTATION; /* make sure both amaflags are set to something (DOC is default) */ if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) { to->amaflags = from->amaflags; } if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) { ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode)); } if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) { ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield)); } /* flags, varsead, ? */ cdr_merge_vars(from, to); if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS)) ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS); if (ast_test_flag(from, AST_CDR_FLAG_POSTED)) ast_set_flag(to, AST_CDR_FLAG_POSTED); if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) ast_set_flag(to, AST_CDR_FLAG_LOCKED); if (ast_test_flag(from, AST_CDR_FLAG_CHILD)) ast_set_flag(to, AST_CDR_FLAG_CHILD); if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED)) ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED); /* last, but not least, we need to merge any forked CDRs to the 'to' cdr */ while (from->next) { /* just rip 'em off the 'from' and insert them on the 'to' */ zcdr = from->next; from->next = zcdr->next; zcdr->next = NULL; /* zcdr is now ripped from the current list; */ ast_cdr_append(to, zcdr); } if (discard_from) ast_cdr_discard(from); }
void ast_cdr_noanswer | ( | struct ast_cdr * | cdr | ) |
A call wasn't answered.
cdr | the cdr you wish to associate with the call Marks the channel disposition as "NO ANSWER" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. |
Definition at line 734 of file cdr.c.
References AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_strlen_zero(), ast_test_flag, chan, ast_cdr::channel, check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by ast_cdr_disposition(), handle_cause(), and wait_for_answer().
{ char *chan; while (cdr) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; check_post(cdr); cdr->disposition = AST_CDR_NOANSWER; } cdr = cdr->next; } }
int ast_cdr_register | ( | const char * | name, |
const char * | desc, | ||
ast_cdrbe | be | ||
) |
Register a CDR handling engine.
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. |
0 | on success. |
-1 | on error |
Register a CDR driver. Each registered CDR driver generates a CDR
Definition at line 116 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, ast_cdr_beitem::be, ast_cdr_beitem::desc, LOG_WARNING, and ast_cdr_beitem::name.
Referenced by config_module(), load_config(), load_module(), odbc_load_module(), and unload_module().
{ struct ast_cdr_beitem *i = NULL; if (!name) return -1; if (!be) { ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name); return -1; } AST_RWLIST_WRLOCK(&be_list); AST_RWLIST_TRAVERSE(&be_list, i, list) { if (!strcasecmp(name, i->name)) { ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name); AST_RWLIST_UNLOCK(&be_list); return -1; } } if (!(i = ast_calloc(1, sizeof(*i)))) return -1; i->be = be; ast_copy_string(i->name, name, sizeof(i->name)); ast_copy_string(i->desc, desc, sizeof(i->desc)); AST_RWLIST_INSERT_HEAD(&be_list, i, list); AST_RWLIST_UNLOCK(&be_list); return 0; }
Reset the detail record, optionally posting it first.
cdr | which cdr to act upon |
flags | |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's |
Definition at line 1067 of file cdr.c.
References ast_cdr::answer, ast_cdr_detach(), ast_cdr_dup(), ast_cdr_end(), AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POST_ENABLE, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), AST_CDR_NOANSWER, ast_cdr_start(), ast_clear_flag, ast_copy_flags, AST_FLAGS_ALL, ast_set_flag, ast_test_flag, ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, ast_cdr::next, and ast_cdr::start.
Referenced by ast_cdr_fork(), dial_exec_full(), disa_exec(), and pbx_builtin_resetcdr().
{ struct ast_cdr *duplicate; struct ast_flags flags = { 0 }; if (_flags) ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); for ( ; cdr ; cdr = cdr->next) { /* Detach if post is requested */ if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) { ast_cdr_end(cdr); if ((duplicate = ast_cdr_dup(cdr))) { ast_cdr_detach(duplicate); } ast_set_flag(cdr, AST_CDR_FLAG_POSTED); } /* enable CDR only */ if (ast_test_flag(&flags, AST_CDR_FLAG_POST_ENABLE)) { ast_clear_flag(cdr, AST_CDR_FLAG_POST_DISABLED); continue; } /* clear variables */ if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) { ast_cdr_free_vars(cdr, 0); } /* Reset to initial state */ ast_clear_flag(cdr, AST_FLAGS_ALL); memset(&cdr->start, 0, sizeof(cdr->start)); memset(&cdr->end, 0, sizeof(cdr->end)); memset(&cdr->answer, 0, sizeof(cdr->answer)); cdr->billsec = 0; cdr->duration = 0; ast_cdr_start(cdr); cdr->disposition = AST_CDR_NOANSWER; } } }
int ast_cdr_serialize_variables | ( | struct ast_cdr * | cdr, |
struct ast_str ** | buf, | ||
char | delim, | ||
char | sep, | ||
int | recur | ||
) |
Definition at line 370 of file cdr.c.
References ast_cdr_getvar(), AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), cdr_readonly_vars, ast_var_t::entries, LOG_ERROR, ast_cdr::next, S_OR, total, var, and ast_cdr::varshead.
Referenced by handle_showchan().
{ struct ast_var_t *variables; const char *var; char *tmp; char workspace[256]; int total = 0, x = 0, i; ast_str_reset(*buf); for (; cdr; cdr = recur ? cdr->next : NULL) { if (++x > 1) ast_str_append(buf, 0, "\n"); AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) { if (!(var = ast_var_name(variables))) { continue; } if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variables), ""), sep) < 0) { ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); break; } total++; } for (i = 0; cdr_readonly_vars[i]; i++) { workspace[0] = 0; /* null out the workspace, because the cdr_get_tv() won't write anything if time is NULL, so you get old vals */ ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0); if (!tmp) continue; if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep) < 0) { ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); break; } else total++; } } return total; }
int ast_cdr_setaccount | ( | struct ast_channel * | chan, |
const char * | account | ||
) |
Set account code, will generate AMI event.
Definition at line 941 of file cdr.c.
References ast_cdr::accountcode, accountcode, ast_channel::accountcode, AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, buf, ast_channel::cdr, EVENT_FLAG_CALL, manager_event, ast_channel::name, ast_cdr::next, and ast_channel::uniqueid.
Referenced by __ast_request_and_dial(), ast_bridge_call(), ast_call_forward(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), auth_exec(), cdr_write(), and rpt_call().
{ struct ast_cdr *cdr = chan->cdr; char buf[BUFSIZ/2] = ""; if (!ast_strlen_zero(chan->accountcode)) ast_copy_string(buf, chan->accountcode, sizeof(buf)); ast_string_field_set(chan, accountcode, account); for ( ; cdr ; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode)); } } /* Signal change of account code to manager */ manager_event(EVENT_FLAG_CALL, "NewAccountCode", "Channel: %s\r\nUniqueid: %s\r\nAccountCode: %s\r\nOldAccountCode: %s\r\n", chan->name, chan->uniqueid, chan->accountcode, buf); return 0; }
int ast_cdr_setamaflags | ( | struct ast_channel * | chan, |
const char * | amaflags | ||
) |
Set AMA flags for channel.
Definition at line 960 of file cdr.c.
References ast_cdr::amaflags, ast_cdr_amaflags2int(), AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, and ast_cdr::next.
Referenced by cdr_write(), and pbx_builtin_setamaflags().
{ struct ast_cdr *cdr; int newflag = ast_cdr_amaflags2int(flag); if (newflag) { for (cdr = chan->cdr; cdr; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { cdr->amaflags = newflag; } } } return 0; }
void ast_cdr_setanswer | ( | struct ast_cdr * | cdr, |
struct timeval | t | ||
) |
Set the answer time for a call.
cdr | the cdr you wish to associate with the call |
t | the answer time Starts all CDR stuff necessary for doing CDR when answering a call NULL argument is just fine. |
Definition at line 795 of file cdr.c.
References ast_cdr::answer, AST_CDR_FLAG_ANSLOCKED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), and ast_cdr::next.
Referenced by ast_bridge_call().
{ for (; cdr; cdr = cdr->next) { if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) continue; if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) continue; check_post(cdr); cdr->answer = t; } }
void ast_cdr_setapp | ( | struct ast_cdr * | cdr, |
const char * | app, | ||
const char * | data | ||
) |
Set the last executed application.
cdr | which cdr to act upon |
app | the name of the app you wish to change it to |
data | the data you want in the data field of app you set it to Changes the value of the last executed app Returns nothing |
Definition at line 783 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, check_post(), ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::next, and S_OR.
Referenced by __ast_request_and_dial(), agi_handle_command(), clear_caller(), findmeexec(), and pbx_exec().
{ for (; cdr; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { check_post(cdr); ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp)); ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata)); } } }
int ast_cdr_setcid | ( | struct ast_cdr * | cdr, |
struct ast_channel * | chan | ||
) |
Initialize based on a channel.
cdr | Call Detail Record to use for channel |
chan | Channel to bind CDR with Initializes a CDR and associates it with a particular channel |
Definition at line 840 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_cdr::next, and set_one_cid().
Referenced by ast_bridge_call(), ast_set_callerid(), and callerid_write().
{ for (; cdr; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) set_one_cid(cdr, c); } return 0; }
void ast_cdr_setdestchan | ( | struct ast_cdr * | cdr, |
const char * | chan | ||
) |
Set the destination channel, if there was one.
cdr | Which cdr it's applied to |
chan | Channel to which dest will be Sets the destination channel the CDR is applied to Returns nothing |
Definition at line 773 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, check_post(), ast_cdr::dstchannel, and ast_cdr::next.
Referenced by dial_exec_full(), park_exec_full(), ring_entry(), and try_calling().
{ for (; cdr; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { check_post(cdr); ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel)); } } }
void ast_cdr_setdisposition | ( | struct ast_cdr * | cdr, |
long int | disposition | ||
) |
Set the disposition for a call.
cdr | the cdr you wish to associate with the call |
disposition | the new disposition Set the disposition on a call. NULL argument is just fine. |
Definition at line 808 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by ast_bridge_call().
{ for (; cdr; cdr = cdr->next) { if (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) continue; check_post(cdr); cdr->disposition = disposition; } }
int ast_cdr_setuserfield | ( | struct ast_channel * | chan, |
const char * | userfield | ||
) |
Set CDR user field for channel (stored in CDR)
Definition at line 975 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, ast_channel::cdr, ast_cdr::next, and ast_cdr::userfield.
Referenced by __agent_start_monitoring(), cdr_write(), handle_request_info(), and start_monitor_exec().
{ struct ast_cdr *cdr = chan->cdr; for ( ; cdr ; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield)); } return 0; }
int ast_cdr_setvar | ( | struct ast_cdr * | cdr, |
const char * | name, | ||
const char * | value, | ||
int | recur | ||
) |
Set a CDR channel variable
Definition at line 300 of file cdr.c.
References AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_test_flag, ast_var_assign(), ast_var_delete(), ast_var_name(), cdr_readonly_vars, LOG_ERROR, ast_cdr::next, and ast_cdr::varshead.
Referenced by ast_cdr_fork(), cdr_write(), and set_one_cid().
{ struct ast_var_t *newvariable; struct varshead *headp; int x; if (!cdr) /* don't die if the cdr is null */ return -1; for (x = 0; cdr_readonly_vars[x]; x++) { if (!strcasecmp(name, cdr_readonly_vars[x])) { ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name); return -1; } } if (!cdr) { ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n"); return -1; } for (; cdr; cdr = recur ? cdr->next : NULL) { if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) continue; headp = &cdr->varshead; AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { if (!strcasecmp(ast_var_name(newvariable), name)) { /* there is already such a variable, delete it */ AST_LIST_REMOVE_CURRENT(entries); ast_var_delete(newvariable); break; } } AST_LIST_TRAVERSE_SAFE_END; if (value) { newvariable = ast_var_assign(name, value); AST_LIST_INSERT_HEAD(headp, newvariable, entries); } } return 0; }
Reset the detail record times, flags
cdr | which cdr to act upon |
flags | |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's |
Definition at line 1110 of file cdr.c.
References ast_cdr::answer, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NULL, ast_cdr_start(), ast_clear_flag, ast_copy_flags, AST_FLAGS_ALL, ast_set_flag, ast_test_flag, ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, and ast_cdr::start.
Referenced by ast_bridge_call().
{ struct ast_flags flags = { 0 }; if (_flags) ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); /* Reset to initial state */ if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) { /* But do NOT lose the NoCDR() setting */ ast_clear_flag(cdr, AST_FLAGS_ALL); ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); } else { ast_clear_flag(cdr, AST_FLAGS_ALL); } memset(&cdr->start, 0, sizeof(cdr->start)); memset(&cdr->end, 0, sizeof(cdr->end)); memset(&cdr->answer, 0, sizeof(cdr->answer)); cdr->billsec = 0; cdr->duration = 0; ast_cdr_start(cdr); cdr->disposition = AST_CDR_NULL; }
void ast_cdr_start | ( | struct ast_cdr * | cdr | ) |
Start a call.
cdr | the cdr you wish to associate with the call Starts all CDR stuff necessary for monitoring a call Returns nothing |
Definition at line 682 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_tvnow(), chan, ast_cdr::channel, check_post(), ast_cdr::next, S_OR, and ast_cdr::start.
Referenced by __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_reset(), ast_cdr_specialized_reset(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().
{ char *chan; for (; cdr; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { chan = S_OR(cdr->channel, "<unknown>"); check_post(cdr); cdr->start = ast_tvnow(); } } }
void ast_cdr_submit_batch | ( | int | shutdown | ) |
Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines.
shutdown | Whether or not we are shutting down Blocks the asterisk shutdown procedures until the CDR data is submitted. Returns nothing |
Definition at line 1188 of file cdr.c.
References ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_detached_background, AST_PTHREADT_NULL, batch, batchscheduleronly, cdr_batch_lock, do_batch_backend_process(), ast_cdr_batch::head, LOG_WARNING, and reset_batch().
Referenced by ast_cdr_engine_term(), and submit_scheduled_batch().
{ struct ast_cdr_batch_item *oldbatchitems = NULL; pthread_t batch_post_thread = AST_PTHREADT_NULL; /* if there's no batch, or no CDRs in the batch, then there's nothing to do */ if (!batch || !batch->head) return; /* move the old CDRs aside, and prepare a new CDR batch */ ast_mutex_lock(&cdr_batch_lock); oldbatchitems = batch->head; reset_batch(); ast_mutex_unlock(&cdr_batch_lock); /* if configured, spawn a new thread to post these CDRs, also try to save as much as possible if we are shutting down safely */ if (batchscheduleronly || do_shutdown) { ast_debug(1, "CDR single-threaded batch processing begins now\n"); do_batch_backend_process(oldbatchitems); } else { if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) { ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n"); do_batch_backend_process(oldbatchitems); } else { ast_debug(1, "CDR multi-threaded batch processing begins now\n"); } } }
void ast_cdr_unregister | ( | const char * | name | ) |
Unregister a CDR handling engine.
name | name of CDR handler to unregister Unregisters a CDR by it's name |
unregister a CDR driver
Definition at line 151 of file cdr.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and ast_cdr_beitem::name.
Referenced by load_config(), reload(), tds_unload_module(), and unload_module().
{ struct ast_cdr_beitem *i = NULL; AST_RWLIST_WRLOCK(&be_list); AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { if (!strcasecmp(name, i->name)) { AST_RWLIST_REMOVE_CURRENT(list); ast_verb(2, "Unregistered '%s' CDR backend\n", name); ast_free(i); break; } } AST_RWLIST_TRAVERSE_SAFE_END; AST_RWLIST_UNLOCK(&be_list); }
int ast_cdr_update | ( | struct ast_channel * | chan | ) |
Update CDR on a channel
Definition at line 1001 of file cdr.c.
References ast_channel::accountcode, ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, ast_channel::cdr, ast_channel::context, ast_cdr::dcontext, ast_cdr::dst, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, S_OR, and set_one_cid().
Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_bridge_call(), cb_events(), clear_caller(), findmeexec(), and local_call().
{ struct ast_cdr *cdr = c->cdr; for ( ; cdr ; cdr = cdr->next) { if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { set_one_cid(cdr, c); /* Copy account code et-al */ ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); /* Destination information */ /* XXX privilege macro* ? */ ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst)); ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext)); } } return 0; }
int check_cdr_enabled | ( | void | ) |
Return TRUE if CDR subsystem is enabled.
Definition at line 108 of file cdr.c.
References enabled.
Referenced by action_coresettings(), and handle_show_settings().
{ return enabled; }
char ast_default_accountcode[AST_MAX_ACCOUNT_CODE] |
Definition at line 55 of file cdr.c.
Referenced by __ast_channel_alloc_ap().
Default AMA flag for billing records (CDR's)
Definition at line 54 of file cdr.c.
Referenced by __ast_channel_alloc_ap(), ast_bridge_call(), and ast_cdr_init().