Call Detail Record API. More...
#include <sys/time.h>#include "asterisk/data.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 |
Typedefs | |
| typedef int(* | ast_cdrbe )(struct ast_cdr *cdr) |
| CDR backend callback. | |
Enumerations | |
| enum | { AST_CDR_FLAG_KEEP_VARS = (1 << 0), AST_CDR_FLAG_POSTED = (1 << 1), AST_CDR_FLAG_LOCKED = (1 << 2), AST_CDR_FLAG_CHILD = (1 << 3), AST_CDR_FLAG_POST_DISABLED = (1 << 4), AST_CDR_FLAG_BRIDGED = (1 << 5), AST_CDR_FLAG_MAIN = (1 << 6), AST_CDR_FLAG_ENABLE = (1 << 7), AST_CDR_FLAG_ANSLOCKED = (1 << 8), AST_CDR_FLAG_DONT_TOUCH = (1 << 9), AST_CDR_FLAG_POST_ENABLE = (1 << 10), AST_CDR_FLAG_DIALED = (1 << 11), AST_CDR_FLAG_ORIGINATED = (1 << 12) } |
| CDR Flags. More... | |
| enum | { 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_OMIT = 1, AST_CDR_BILLING = 2, AST_CDR_DOCUMENTATION = 3 } |
| CDR AMA Flags. More... | |
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. | |
| void | ast_cdr_congestion (struct ast_cdr *cdr) |
| A call was set to congestion. | |
| int | ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr) |
| int | ast_cdr_data_add_structure (struct ast_data *tree, struct ast_cdr *cdr, int recur) |
| 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. | |
| struct ast_cdr * | ast_cdr_dup_unique (struct ast_cdr *cdr) |
| Duplicate a record and increment the sequence number. | |
| struct ast_cdr * | ast_cdr_dup_unique_swap (struct ast_cdr *cdr) |
| Duplicate a record and increment the sequence number of the old 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_congestion (void) |
| 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_setpeeraccount (struct ast_channel *chan, const char *account) |
| Set the peer account. | |
| 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) |
| Update CDR on a channel. | |
| 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_MAX_ACCOUNT_CODE 20 |
| #define AST_MAX_USER_FIELD 256 |
Definition at line 73 of file cdr.h.
Referenced by ast_rtp_instance_set_stats_vars(), handle_request_bye(), sip_acf_channel_read(), sip_hangup(), and tds_log().
| anonymous enum |
CDR Flags.
Definition at line 36 of file cdr.h.
{
AST_CDR_FLAG_KEEP_VARS = (1 << 0),
AST_CDR_FLAG_POSTED = (1 << 1),
AST_CDR_FLAG_LOCKED = (1 << 2),
AST_CDR_FLAG_CHILD = (1 << 3),
AST_CDR_FLAG_POST_DISABLED = (1 << 4),
AST_CDR_FLAG_BRIDGED = (1 << 5),
AST_CDR_FLAG_MAIN = (1 << 6),
AST_CDR_FLAG_ENABLE = (1 << 7),
AST_CDR_FLAG_ANSLOCKED = (1 << 8),
AST_CDR_FLAG_DONT_TOUCH = (1 << 9),
AST_CDR_FLAG_POST_ENABLE = (1 << 10),
AST_CDR_FLAG_DIALED = (1 << 11),
AST_CDR_FLAG_ORIGINATED = (1 << 12),
};
| anonymous enum |
CDR Flags - Disposition.
| AST_CDR_NOANSWER | |
| AST_CDR_NULL | |
| AST_CDR_FAILED | |
| AST_CDR_BUSY | |
| AST_CDR_ANSWERED | |
| AST_CDR_CONGESTION |
Definition at line 55 of file cdr.h.
{
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),
};
| anonymous enum |
CDR AMA Flags.
Definition at line 67 of file cdr.h.
{
AST_CDR_OMIT = 1,
AST_CDR_BILLING = 2,
AST_CDR_DOCUMENTATION = 3,
};
| 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 510 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(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), 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 1154 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 748 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();
}
}
| struct ast_cdr* ast_cdr_append | ( | struct ast_cdr * | cdr, |
| struct ast_cdr * | newcdr | ||
| ) | [read] |
Definition at line 1265 of file cdr.c.
References ast_cdr::next.
Referenced by ast_cdr_fork(), ast_cdr_merge(), and try_calling().
| int ast_cdr_appenduserfield | ( | struct ast_channel * | chan, |
| const char * | userfield | ||
| ) |
Append to CDR user field for channel (stored in CDR)
Definition at line 1118 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_channel_cdr(), ast_copy_string(), ast_test_flag, len(), ast_cdr::next, and ast_cdr::userfield.
Referenced by ast_bridge_call().
{
struct ast_cdr *cdr = ast_channel_cdr(chan);
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 764 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;
}
}
}
| void ast_cdr_congestion | ( | struct ast_cdr * | cdr | ) |
A call was set to congestion.
| cdr | the cdr you wish to associate with the call Markst he channel disposition as "CONGESTION" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application |
Definition at line 798 of file cdr.c.
References AST_CDR_CONGESTION, ast_cdr_failed(), AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, congestion, ast_cdr::disposition, LOG_WARNING, and ast_cdr::next.
Referenced by ast_cdr_disposition(), and pbx_builtin_congestion().
{
char *chan;
/* if congestion log is disabled, pass the buck to ast_cdr_failed */
if (!congestion) {
ast_cdr_failed(cdr);
}
while (cdr && congestion) {
if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) {
ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
}
if (cdr->disposition < AST_CDR_CONGESTION) {
cdr->disposition = AST_CDR_CONGESTION;
}
}
cdr = cdr->next;
}
}
| int ast_cdr_copy_vars | ( | struct ast_cdr * | to_cdr, |
| struct ast_cdr * | from_cdr | ||
| ) |
Definition at line 394 of file cdr.c.
References AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_assign(), ast_var_name(), ast_var_value(), var, and ast_cdr::varshead.
Referenced by ast_bridge_call(), and 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;
}
| int ast_cdr_data_add_structure | ( | struct ast_data * | tree, |
| struct ast_cdr * | cdr, | ||
| int | recur | ||
| ) |
| [in] | tree | Where to insert the cdr. |
| [in] | cdr | The cdr structure to insert in 'tree'. |
| [in] | recur | Go throw all the cdr levels. |
| <0 | on error. |
| 0 | on success. |
Definition at line 1715 of file cdr.c.
References ast_cdr_getvar(), ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_name(), ast_var_value(), cdr_readonly_vars, ast_var_t::entries, ast_cdr::next, var, and ast_cdr::varshead.
Referenced by ast_channel_data_add_structure().
{
struct ast_cdr *tmpcdr;
struct ast_data *level;
struct ast_var_t *variables;
const char *var, *val;
int x = 1, i;
char workspace[256];
char *tmp;
if (!cdr) {
return -1;
}
for (tmpcdr = cdr; tmpcdr; tmpcdr = (recur ? tmpcdr->next : NULL)) {
level = ast_data_add_node(tree, "level");
if (!level) {
continue;
}
ast_data_add_int(level, "level_number", x);
AST_LIST_TRAVERSE(&tmpcdr->varshead, variables, entries) {
if (variables && (var = ast_var_name(variables)) &&
(val = ast_var_value(variables)) && !ast_strlen_zero(var)
&& !ast_strlen_zero(val)) {
ast_data_add_str(level, var, val);
} else {
break;
}
}
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(tmpcdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0);
if (!tmp) {
continue;
}
ast_data_add_str(level, cdr_readonly_vars[i], tmp);
}
x++;
}
return 0;
}
| 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 1377 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;
int submit_batch = 0;
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++;
/* if we have enough stuff to post, then do it */
if (curr >= (batchsize - 1)) {
submit_batch = 1;
}
ast_mutex_unlock(&cdr_batch_lock);
/* Don't call submit_unscheduled_batch with the cdr_batch_lock held */
if (submit_batch) {
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 499 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(), ast_channel_destructor(), and ast_dummy_channel_destructor().
| 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 998 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_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";
case AST_CDR_CONGESTION:
return "CONGESTION";
}
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 826 of file cdr.c.
References AST_CAUSE_BUSY, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, ast_cdr_busy(), ast_cdr_congestion(), ast_cdr_noanswer(), and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), and clear_caller().
{
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_CIRCUIT_CONGESTION:
ast_cdr_congestion(cdr);
break;
case AST_CAUSE_NORMAL:
break;
default:
res = -1;
}
}
return res;
}
| struct ast_cdr* ast_cdr_dup | ( | struct ast_cdr * | cdr | ) | [read] |
Duplicate a record.
| cdr | the record to duplicate |
| a | malloc'd ast_cdr structure, |
| NULL | on error (malloc failure) |
Duplicate a CDR record
Definition at line 224 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_cdr_dup_unique(), ast_cdr_dup_unique_swap(), ast_cdr_merge(), custom_log(), manager_log(), syslog_log(), try_calling(), and write_cdr().
{
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;
}
| struct ast_cdr* ast_cdr_dup_unique | ( | struct ast_cdr * | cdr | ) | [read] |
Duplicate a record and increment the sequence number.
| cdr | the record to duplicate |
| a | malloc'd ast_cdr structure, |
| NULL | on error (malloc failure) |
Definition at line 201 of file cdr.c.
References ast_cdr_dup(), and cdr_seq_inc().
Referenced by ast_cdr_fork().
{
struct ast_cdr *newcdr = ast_cdr_dup(cdr);
if (!newcdr)
return NULL;
cdr_seq_inc(newcdr);
return newcdr;
}
| struct ast_cdr* ast_cdr_dup_unique_swap | ( | struct ast_cdr * | cdr | ) | [read] |
Duplicate a record and increment the sequence number of the old record.
| cdr | the record to duplicate |
| a | malloc'd ast_cdr structure, |
| NULL | on error (malloc failure) |
Definition at line 211 of file cdr.c.
References ast_cdr_dup(), and cdr_seq_inc().
Referenced by ast_bridge_call(), and ast_cdr_reset().
{
struct ast_cdr *newcdr = ast_cdr_dup(cdr);
if (!newcdr)
return NULL;
cdr_seq_inc(cdr);
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 972 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_request_and_dial(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_reset(), ast_hangup(), ast_pbx_h_exten_run(), ast_pbx_hangup_handler_run(), ast_pbx_outgoing_cdr_failed(), and clear_caller().
{
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 1687 of file cdr.c.
References ast_cli_register(), ast_log(), ast_register_atexit(), ast_sched_context_create(), cdr_engine_shutdown(), cli_status, do_reload(), and LOG_ERROR.
Referenced by main().
{
sched = ast_sched_context_create();
if (!sched) {
ast_log(LOG_ERROR, "Unable to create schedule context.\n");
return -1;
}
ast_cli_register(&cli_status);
do_reload(0);
ast_register_atexit(cdr_engine_shutdown);
return 0;
}
| int ast_cdr_engine_reload | ( | void | ) |
Reload the configuration file cdr.conf and start/stop CDR scheduling thread.
Definition at line 1709 of file cdr.c.
References do_reload().
{
do_reload(1);
return 0;
}
| void ast_cdr_engine_term | ( | void | ) |
Submit any remaining CDRs and prepare for shutdown
Definition at line 1704 of file cdr.c.
References ast_cdr_submit_batch(), and batchsafeshutdown.
Referenced by can_safely_quit(), and do_reload().
| 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 775 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_cdr_congestion(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), clear_caller(), 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 1018 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(), ast_channel_data_add_structure(), build_csv_record(), build_radius_record(), csv_log(), manager_log(), peers_data_provider_get(), sip_show_user(), tds_log(), and users_data_provider_get().
{
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 486 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 465 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 275 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_tvzero(), 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::linkedid, ast_cdr::peeraccount, ast_cdr::sequence, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.
Referenced by ast_cdr_data_add_structure(), 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->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
} else if (!strcasecmp(name, "billsec")) {
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);
} 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, "peeraccount"))
ast_copy_string(workspace, cdr->peeraccount, workspacelen);
else if (!strcasecmp(name, "uniqueid"))
ast_copy_string(workspace, cdr->uniqueid, workspacelen);
else if (!strcasecmp(name, "linkedid"))
ast_copy_string(workspace, cdr->linkedid, workspacelen);
else if (!strcasecmp(name, "userfield"))
ast_copy_string(workspace, cdr->userfield, workspacelen);
else if (!strcasecmp(name, "sequence"))
snprintf(workspace, workspacelen, "%d", cdr->sequence);
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 936 of file cdr.c.
References ast_cdr::accountcode, ast_cdr::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_channel_accountcode(), ast_channel_amaflags(), ast_channel_context(), ast_channel_exten(), ast_channel_linkedid(), ast_channel_macrocontext(), ast_channel_macroexten(), ast_channel_name(), ast_channel_peeraccount(), ast_channel_uniqueid(), ast_copy_string(), ast_default_amaflags, AST_STATE_UP, ast_test_flag, cdr_seq_inc(), ast_cdr::channel, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::linkedid, ast_cdr::next, ast_cdr::peeraccount, S_OR, set_one_cid(), and ast_cdr::uniqueid.
Referenced by __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), findmeexec(), and try_calling().
{
for ( ; cdr ; cdr = cdr->next) {
if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
ast_copy_string(cdr->channel, ast_channel_name(c), sizeof(cdr->channel));
set_one_cid(cdr, c);
cdr_seq_inc(cdr);
cdr->disposition = (ast_channel_state(c) == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER;
cdr->amaflags = ast_channel_amaflags(c) ? ast_channel_amaflags(c) : ast_default_amaflags;
ast_copy_string(cdr->accountcode, ast_channel_accountcode(c), sizeof(cdr->accountcode));
ast_copy_string(cdr->peeraccount, ast_channel_peeraccount(c), sizeof(cdr->peeraccount));
/* Destination information */
ast_copy_string(cdr->dst, S_OR(ast_channel_macroexten(c),ast_channel_exten(c)), sizeof(cdr->dst));
ast_copy_string(cdr->dcontext, S_OR(ast_channel_macrocontext(c),ast_channel_context(c)), sizeof(cdr->dcontext));
/* Unique call identifier */
ast_copy_string(cdr->uniqueid, ast_channel_uniqueid(c), sizeof(cdr->uniqueid));
/* Linked call identifier */
ast_copy_string(cdr->linkedid, ast_channel_linkedid(c), sizeof(cdr->linkedid));
}
}
return 0;
}
| int ast_cdr_isset_congestion | ( | void | ) |
| int ast_cdr_isset_unanswered | ( | void | ) |
Definition at line 191 of file cdr.c.
References unanswered.
Referenced by ring_entry(), and try_calling().
{
return unanswered;
}
| 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.
| to | the cdr to get the goodies |
| from | the cdr to give the goodies |
Definition at line 554 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::peeraccount, 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.\n");
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 */
if (llfrom) {
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 if (llfrom) {
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->peeraccount) && !ast_strlen_zero(from->peeraccount))) {
ast_copy_string(to->peeraccount, from->peeraccount, sizeof(to->peeraccount));
}
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 787 of file cdr.c.
References AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by ast_cdr_disposition(), handle_cause(), and wait_for_answer().
{
while (cdr) {
if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
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 handling engine.
| 0 | on success. |
| -1 | on error |
Definition at line 136 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 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;
}
| void ast_cdr_reset | ( | struct ast_cdr * | cdr, |
| struct ast_flags * | flags | ||
| ) |
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 1198 of file cdr.c.
References ast_cdr::answer, ast_cdr_detach(), ast_cdr_dup_unique_swap(), 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(), pbx_builtin_resetcdr(), and try_calling().
{
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_unique_swap(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 420 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 1031 of file cdr.c.
References ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_channel_accountcode(), ast_channel_cdr(), ast_channel_name(), ast_channel_uniqueid(), ast_copy_string(), ast_manager_event, ast_strlen_zero(), ast_test_flag, EVENT_FLAG_CALL, and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_bridge_call(), ast_call_forward(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), auth_exec(), and cdr_write().
{
struct ast_cdr *cdr = ast_channel_cdr(chan);
const char *old_acct = "";
if (!ast_strlen_zero(ast_channel_accountcode(chan))) {
old_acct = ast_strdupa(ast_channel_accountcode(chan));
}
ast_channel_accountcode_set(chan, account);
for ( ; cdr ; cdr = cdr->next) {
if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
ast_copy_string(cdr->accountcode, ast_channel_accountcode(chan), sizeof(cdr->accountcode));
}
}
/*** DOCUMENTATION
<managerEventInstance>
<synopsis>Raised when a CDR's AccountCode is changed.</synopsis>
</managerEventInstance>
***/
ast_manager_event(chan, EVENT_FLAG_CALL, "NewAccountCode",
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
"AccountCode: %s\r\n"
"OldAccountCode: %s\r\n",
ast_channel_name(chan), ast_channel_uniqueid(chan), ast_channel_accountcode(chan), old_acct);
return 0;
}
| int ast_cdr_setamaflags | ( | struct ast_channel * | chan, |
| const char * | amaflags | ||
| ) |
Set AMA flags for channel.
Definition at line 1091 of file cdr.c.
References ast_cdr::amaflags, ast_cdr_amaflags2int(), AST_CDR_FLAG_LOCKED, ast_channel_cdr(), ast_test_flag, 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 = ast_channel_cdr(chan); 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 873 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(), and dial_exec_full().
{
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 861 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(), 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 922 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_channel_set_caller_event(), 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 851 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(), parked_call_exec(), 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 886 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_setpeeraccount | ( | struct ast_channel * | chan, |
| const char * | account | ||
| ) |
Set the peer account.
Definition at line 1061 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_channel_cdr(), ast_channel_name(), ast_channel_peeraccount(), ast_channel_uniqueid(), ast_copy_string(), ast_manager_event, ast_strlen_zero(), ast_test_flag, EVENT_FLAG_CALL, ast_cdr::next, and ast_cdr::peeraccount.
Referenced by cdr_write().
{
struct ast_cdr *cdr = ast_channel_cdr(chan);
const char *old_acct = "";
if (!ast_strlen_zero(ast_channel_peeraccount(chan))) {
old_acct = ast_strdupa(ast_channel_peeraccount(chan));
}
ast_channel_peeraccount_set(chan, account);
for ( ; cdr ; cdr = cdr->next) {
if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
ast_copy_string(cdr->peeraccount, ast_channel_peeraccount(chan), sizeof(cdr->peeraccount));
}
}
/*** DOCUMENTATION
<managerEventInstance>
<synopsis>Raised when a CDR's PeerAccount is changed.</synopsis>
</managerEventInstance>
***/
ast_manager_event(chan, EVENT_FLAG_CALL, "NewPeerAccount",
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
"PeerAccount: %s\r\n"
"OldPeerAccount: %s\r\n",
ast_channel_name(chan), ast_channel_uniqueid(chan), ast_channel_peeraccount(chan), old_acct);
return 0;
}
| int ast_cdr_setuserfield | ( | struct ast_channel * | chan, |
| const char * | userfield | ||
| ) |
Set CDR user field for channel (stored in CDR)
Definition at line 1106 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_channel_cdr(), ast_copy_string(), ast_test_flag, ast_cdr::next, and ast_cdr::userfield.
Referenced by __agent_start_monitoring(), ast_bridge_call(), cdr_write(), handle_request_info(), and start_monitor_exec().
{
struct ast_cdr *cdr = ast_channel_cdr(chan);
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 354 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;
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;
}
| void ast_cdr_specialized_reset | ( | struct ast_cdr * | cdr, |
| struct ast_flags * | flags | ||
| ) |
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 1241 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 738 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_tvnow(), check_post(), ast_cdr::next, 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(), and clear_caller().
{
for (; cdr; cdr = cdr->next) {
if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
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 1319 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 171 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(), odbc_load_module(), 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);
break;
}
}
AST_RWLIST_TRAVERSE_SAFE_END;
AST_RWLIST_UNLOCK(&be_list);
if (i) {
ast_verb(2, "Unregistered '%s' CDR backend\n", name);
ast_free(i);
}
}
| int ast_cdr_update | ( | struct ast_channel * | chan | ) |
Update CDR on a channel.
Definition at line 1132 of file cdr.c.
References ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_channel_accountcode(), ast_channel_cdr(), ast_channel_context(), ast_channel_exten(), ast_channel_linkedid(), ast_channel_macrocontext(), ast_channel_macroexten(), ast_channel_peeraccount(), ast_copy_string(), ast_test_flag, ast_cdr::dcontext, ast_cdr::dst, ast_cdr::linkedid, ast_cdr::next, ast_cdr::peeraccount, S_OR, and set_one_cid().
Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_bridge_call(), cb_events(), clear_caller(), and local_call().
{
struct ast_cdr *cdr = ast_channel_cdr(c);
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, ast_channel_accountcode(c), sizeof(cdr->accountcode));
ast_copy_string(cdr->peeraccount, ast_channel_peeraccount(c), sizeof(cdr->peeraccount));
ast_copy_string(cdr->linkedid, ast_channel_linkedid(c), sizeof(cdr->linkedid));
/* Destination information */ /* XXX privilege macro* ? */
ast_copy_string(cdr->dst, S_OR(ast_channel_macroexten(c), ast_channel_exten(c)), sizeof(cdr->dst));
ast_copy_string(cdr->dcontext, S_OR(ast_channel_macrocontext(c), ast_channel_context(c)), sizeof(cdr->dcontext));
}
}
return 0;
}
| int check_cdr_enabled | ( | void | ) |
Return TRUE if CDR subsystem is enabled.
Definition at line 126 of file cdr.c.
References enabled.
Referenced by action_coresettings(), and handle_show_settings().
{
return enabled;
}
Definition at line 63 of file cdr.c.
Referenced by __ast_channel_alloc_ap().
Default AMA flag for billing records (CDR's)
Definition at line 62 of file cdr.c.
Referenced by __ast_channel_alloc_ap(), ast_bridge_call(), and ast_cdr_init().