Call Detail Record API. More...
#include "asterisk.h"
#include <signal.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/callerid.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/stringfields.h"
#include "asterisk/data.h"
Go to the source code of this file.
Data Structures | |
struct | ast_cdr_batch |
struct | ast_cdr_batch_item |
struct | ast_cdr_beitem |
struct | be_list |
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) |
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) |
the same as a cdr_free call, only with no checks; just get rid of it | |
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 flag) |
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) |
static const char * | ast_cdr_getvar_internal (struct ast_cdr *cdr, const char *name, int recur) |
int | ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *c) |
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 driver. Each registered CDR driver generates a CDR. | |
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 *flag) |
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 *c) |
Initialize based on a channel. | |
void | ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chann) |
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 do_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 *c) |
Update CDR on a channel. | |
static void | cdr_engine_shutdown (void) |
static void | cdr_get_tv (struct timeval when, const char *fmt, char *buf, int bufsize) |
static void | cdr_merge_vars (struct ast_cdr *to, struct ast_cdr *from) |
static int | cdr_seq_inc (struct ast_cdr *cdr) |
int | check_cdr_enabled (void) |
Return TRUE if CDR subsystem is enabled. | |
static void | check_post (struct ast_cdr *cdr) |
print a warning if cdr already posted | |
static void * | do_batch_backend_process (void *data) |
static void * | do_cdr (void *data) |
static void | do_reload (int reload) |
static char * | handle_cli_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_cli_submit (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static int | init_batch (void) |
static void | post_cdr (struct ast_cdr *cdr) |
static void | reset_batch (void) |
static void | set_one_cid (struct ast_cdr *cdr, struct ast_channel *c) |
static int | submit_scheduled_batch (const void *data) |
static void | submit_unscheduled_batch (void) |
Variables | |
char | ast_default_accountcode [AST_MAX_ACCOUNT_CODE] |
int | ast_default_amaflags = AST_CDR_DOCUMENTATION |
static struct ast_cdr_batch * | batch |
static const int | BATCH_SAFE_SHUTDOWN_DEFAULT = 1 |
static const int | BATCH_SCHEDULER_ONLY_DEFAULT = 0 |
static const int | BATCH_SIZE_DEFAULT = 100 |
static const int | BATCH_TIME_DEFAULT = 300 |
static int | batchmode |
static const int | BATCHMODE_DEFAULT = 0 |
static int | batchsafeshutdown |
static int | batchscheduleronly |
static int | batchsize |
static int | batchtime |
static ast_mutex_t | cdr_batch_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static ast_cond_t | cdr_pending_cond |
static ast_mutex_t | cdr_pending_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static const char *const | cdr_readonly_vars [] |
static int | cdr_sched = -1 |
static ast_mutex_t | cdr_sched_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
static int | cdr_sequence = 0 |
static pthread_t | cdr_thread = AST_PTHREADT_NULL |
static struct ast_cli_entry | cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CDR status") |
static struct ast_cli_entry | cli_submit = AST_CLI_DEFINE(handle_cli_submit, "Posts all pending batched CDR data") |
static int | enabled |
static const int | ENABLED_DEFAULT = 1 |
static struct sched_context * | sched |
static int | unanswered |
static const int | UNANSWERED_DEFAULT = 0 |
Call Detail Record API.
Definition in file cdr.c.
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 500 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(), findmeexec(), and start_monitor_exec().
00501 { 00502 struct ast_cdr *x; 00503 x = ast_calloc(1, sizeof(*x)); 00504 if (!x) 00505 ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n"); 00506 return x; 00507 }
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 1106 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().
01107 { 01108 if (!strcasecmp(flag, "default")) 01109 return 0; 01110 if (!strcasecmp(flag, "omit")) 01111 return AST_CDR_OMIT; 01112 if (!strcasecmp(flag, "billing")) 01113 return AST_CDR_BILLING; 01114 if (!strcasecmp(flag, "documentation")) 01115 return AST_CDR_DOCUMENTATION; 01116 return -1; 01117 }
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 738 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().
00739 { 00740 00741 for (; cdr; cdr = cdr->next) { 00742 if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 00743 continue; 00744 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00745 continue; 00746 check_post(cdr); 00747 if (cdr->disposition < AST_CDR_ANSWERED) 00748 cdr->disposition = AST_CDR_ANSWERED; 00749 if (ast_tvzero(cdr->answer)) 00750 cdr->answer = ast_tvnow(); 00751 } 00752 }
Definition at line 1217 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 1070 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.
Referenced by ast_bridge_call().
01071 { 01072 struct ast_cdr *cdr = chan->cdr; 01073 01074 for ( ; cdr ; cdr = cdr->next) { 01075 int len = strlen(cdr->userfield); 01076 01077 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 01078 ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len); 01079 } 01080 01081 return 0; 01082 }
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 754 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(), and ring_entry().
00755 { 00756 00757 for (; cdr; cdr = cdr->next) { 00758 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00759 check_post(cdr); 00760 cdr->disposition = AST_CDR_BUSY; 00761 } 00762 } 00763 }
Definition at line 384 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().
00385 { 00386 struct ast_var_t *variables, *newvariable = NULL; 00387 struct varshead *headpa, *headpb; 00388 const char *var, *val; 00389 int x = 0; 00390 00391 if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */ 00392 return 0; 00393 00394 headpa = &from_cdr->varshead; 00395 headpb = &to_cdr->varshead; 00396 00397 AST_LIST_TRAVERSE(headpa,variables,entries) { 00398 if (variables && 00399 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00400 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00401 newvariable = ast_var_assign(var, val); 00402 AST_LIST_INSERT_HEAD(headpb, newvariable, entries); 00403 x++; 00404 } 00405 } 00406 00407 return x; 00408 }
[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 1675 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_cdr::next, var, and ast_cdr::varshead.
Referenced by ast_channel_data_add_structure().
01676 { 01677 struct ast_cdr *tmpcdr; 01678 struct ast_data *level; 01679 struct ast_var_t *variables; 01680 const char *var, *val; 01681 int x = 1, i; 01682 char workspace[256]; 01683 char *tmp; 01684 01685 if (!cdr) { 01686 return -1; 01687 } 01688 01689 for (tmpcdr = cdr; tmpcdr; tmpcdr = (recur ? tmpcdr->next : NULL)) { 01690 level = ast_data_add_node(tree, "level"); 01691 if (!level) { 01692 continue; 01693 } 01694 01695 ast_data_add_int(level, "level_number", x); 01696 01697 AST_LIST_TRAVERSE(&tmpcdr->varshead, variables, entries) { 01698 if (variables && (var = ast_var_name(variables)) && 01699 (val = ast_var_value(variables)) && !ast_strlen_zero(var) 01700 && !ast_strlen_zero(val)) { 01701 ast_data_add_str(level, var, val); 01702 } else { 01703 break; 01704 } 01705 } 01706 01707 for (i = 0; cdr_readonly_vars[i]; i++) { 01708 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 */ 01709 ast_cdr_getvar(tmpcdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0); 01710 if (!tmp) { 01711 continue; 01712 } 01713 ast_data_add_str(level, cdr_readonly_vars[i], tmp); 01714 } 01715 01716 x++; 01717 } 01718 01719 return 0; 01720 }
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 1329 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().
01330 { 01331 struct ast_cdr_batch_item *newtail; 01332 int curr; 01333 int submit_batch = 0; 01334 01335 if (!cdr) 01336 return; 01337 01338 /* maybe they disabled CDR stuff completely, so just drop it */ 01339 if (!enabled) { 01340 ast_debug(1, "Dropping CDR !\n"); 01341 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01342 ast_cdr_free(cdr); 01343 return; 01344 } 01345 01346 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */ 01347 if (!batchmode) { 01348 post_cdr(cdr); 01349 ast_cdr_free(cdr); 01350 return; 01351 } 01352 01353 /* otherwise, each CDR gets put into a batch list (at the end) */ 01354 ast_debug(1, "CDR detaching from this thread\n"); 01355 01356 /* we'll need a new tail for every CDR */ 01357 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) { 01358 post_cdr(cdr); 01359 ast_cdr_free(cdr); 01360 return; 01361 } 01362 01363 /* don't traverse a whole list (just keep track of the tail) */ 01364 ast_mutex_lock(&cdr_batch_lock); 01365 if (!batch) 01366 init_batch(); 01367 if (!batch->head) { 01368 /* new batch is empty, so point the head at the new tail */ 01369 batch->head = newtail; 01370 } else { 01371 /* already got a batch with something in it, so just append a new tail */ 01372 batch->tail->next = newtail; 01373 } 01374 newtail->cdr = cdr; 01375 batch->tail = newtail; 01376 curr = batch->size++; 01377 01378 /* if we have enough stuff to post, then do it */ 01379 if (curr >= (batchsize - 1)) { 01380 submit_batch = 1; 01381 } 01382 ast_mutex_unlock(&cdr_batch_lock); 01383 01384 /* Don't call submit_unscheduled_batch with the cdr_batch_lock held */ 01385 if (submit_batch) { 01386 submit_unscheduled_batch(); 01387 } 01388 }
void ast_cdr_discard | ( | struct ast_cdr * | cdr | ) |
the same as a cdr_free call, only with no checks; just get rid of it
Discard and free a CDR record.
Definition at line 489 of file cdr.c.
References ast_cdr_free_vars(), ast_free, ast_cdr::next, and ast_cdr_beitem::next.
Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_merge(), ast_channel_destructor(), and ast_dummy_channel_destructor().
00490 { 00491 while (cdr) { 00492 struct ast_cdr *next = cdr->next; 00493 00494 ast_cdr_free_vars(cdr, 0); 00495 ast_free(cdr); 00496 cdr = next; 00497 } 00498 }
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 960 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().
00961 { 00962 switch (disposition) { 00963 case AST_CDR_NULL: 00964 return "NO ANSWER"; /* by default, for backward compatibility */ 00965 case AST_CDR_NOANSWER: 00966 return "NO ANSWER"; 00967 case AST_CDR_FAILED: 00968 return "FAILED"; 00969 case AST_CDR_BUSY: 00970 return "BUSY"; 00971 case AST_CDR_ANSWERED: 00972 return "ANSWERED"; 00973 } 00974 return "UNKNOWN"; 00975 }
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 791 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().
00792 { 00793 int res = 0; 00794 00795 for (; cdr; cdr = cdr->next) { 00796 switch (cause) { /* handle all the non failure, busy cases, return 0 not to set disposition, 00797 return -1 to set disposition to FAILED */ 00798 case AST_CAUSE_BUSY: 00799 ast_cdr_busy(cdr); 00800 break; 00801 case AST_CAUSE_NO_ANSWER: 00802 ast_cdr_noanswer(cdr); 00803 break; 00804 case AST_CAUSE_NORMAL: 00805 break; 00806 default: 00807 res = -1; 00808 } 00809 } 00810 return res; 00811 }
Duplicate a record.
Duplicate a CDR record
Definition at line 213 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().
00214 { 00215 struct ast_cdr *newcdr; 00216 00217 if (!cdr) /* don't die if we get a null cdr pointer */ 00218 return NULL; 00219 newcdr = ast_cdr_alloc(); 00220 if (!newcdr) 00221 return NULL; 00222 00223 memcpy(newcdr, cdr, sizeof(*newcdr)); 00224 /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */ 00225 memset(&newcdr->varshead, 0, sizeof(newcdr->varshead)); 00226 ast_cdr_copy_vars(newcdr, cdr); 00227 newcdr->next = NULL; 00228 00229 return newcdr; 00230 }
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 190 of file cdr.c.
References ast_cdr_dup(), and cdr_seq_inc().
Referenced by ast_cdr_fork().
00191 { 00192 struct ast_cdr *newcdr = ast_cdr_dup(cdr); 00193 if (!newcdr) 00194 return NULL; 00195 00196 cdr_seq_inc(newcdr); 00197 return newcdr; 00198 }
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 200 of file cdr.c.
References ast_cdr_dup(), and cdr_seq_inc().
Referenced by ast_bridge_call(), and ast_cdr_reset().
00201 { 00202 struct ast_cdr *newcdr = ast_cdr_dup(cdr); 00203 if (!newcdr) 00204 return NULL; 00205 00206 cdr_seq_inc(cdr); 00207 return newcdr; 00208 }
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 934 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().
00935 { 00936 for ( ; cdr ; cdr = cdr->next) { 00937 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00938 continue; 00939 check_post(cdr); 00940 if (ast_tvzero(cdr->end)) 00941 cdr->end = ast_tvnow(); 00942 if (ast_tvzero(cdr->start)) { 00943 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>")); 00944 cdr->disposition = AST_CDR_FAILED; 00945 } else 00946 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec; 00947 if (ast_tvzero(cdr->answer)) { 00948 if (cdr->disposition == AST_CDR_ANSWERED) { 00949 ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>")); 00950 cdr->disposition = AST_CDR_FAILED; 00951 } 00952 } else { 00953 cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec; 00954 if (ast_test_flag(&ast_options, AST_OPT_FLAG_INITIATED_SECONDS)) 00955 cdr->billsec += cdr->end.tv_usec > cdr->answer.tv_usec ? 1 : 0; 00956 } 00957 } 00958 }
int ast_cdr_engine_init | ( | void | ) |
Load the configuration file cdr.conf and possibly start the CDR scheduling thread.
Definition at line 1647 of file cdr.c.
References ast_cli_register(), ast_log(), ast_register_atexit(), cdr_engine_shutdown(), cli_status, do_reload(), LOG_ERROR, and sched_context_create().
Referenced by main().
01648 { 01649 sched = sched_context_create(); 01650 if (!sched) { 01651 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 01652 return -1; 01653 } 01654 01655 ast_cli_register(&cli_status); 01656 do_reload(0); 01657 ast_register_atexit(cdr_engine_shutdown); 01658 01659 return 0; 01660 }
int ast_cdr_engine_reload | ( | void | ) |
Reload the configuration file cdr.conf and start/stop CDR scheduling thread.
Definition at line 1669 of file cdr.c.
References do_reload().
01670 { 01671 do_reload(1); 01672 return 0; 01673 }
void ast_cdr_engine_term | ( | void | ) |
Submit any remaining CDRs and prepare for shutdown
Definition at line 1664 of file cdr.c.
References ast_cdr_submit_batch(), and batchsafeshutdown.
Referenced by can_safely_quit(), and do_reload().
01665 { 01666 ast_cdr_submit_batch(batchsafeshutdown); 01667 }
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 765 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().
00766 { 00767 for (; cdr; cdr = cdr->next) { 00768 check_post(cdr); 00769 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00770 check_post(cdr); 00771 if (cdr->disposition < AST_CDR_FAILED) 00772 cdr->disposition = AST_CDR_FAILED; 00773 } 00774 } 00775 }
char* ast_cdr_flags2str | ( | int | flag | ) |
Converts AMA flag to printable string
Definition at line 978 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().
00979 { 00980 switch (flag) { 00981 case AST_CDR_OMIT: 00982 return "OMIT"; 00983 case AST_CDR_BILLING: 00984 return "BILLING"; 00985 case AST_CDR_DOCUMENTATION: 00986 return "DOCUMENTATION"; 00987 } 00988 return "Unknown"; 00989 }
void ast_cdr_free | ( | struct ast_cdr * | cdr | ) |
Free a CDR record.
cdr | ast_cdr structure to free Returns nothing |
Definition at line 476 of file cdr.c.
References ast_cdr_free_vars(), ast_free, ast_cdr::next, and ast_cdr_beitem::next.
Referenced by ast_cdr_detach(), and do_batch_backend_process().
00477 { 00478 00479 while (cdr) { 00480 struct ast_cdr *next = cdr->next; 00481 00482 ast_cdr_free_vars(cdr, 0); 00483 ast_free(cdr); 00484 cdr = next; 00485 } 00486 }
void ast_cdr_free_vars | ( | struct ast_cdr * | cdr, | |
int | recur | |||
) |
Definition at line 455 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().
00456 { 00457 00458 /* clear variables */ 00459 for (; cdr; cdr = recur ? cdr->next : NULL) { 00460 struct ast_var_t *vardata; 00461 struct varshead *headp = &cdr->varshead; 00462 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 00463 ast_var_delete(vardata); 00464 } 00465 }
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 264 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().
00265 { 00266 const char *fmt = "%Y-%m-%d %T"; 00267 const char *varbuf; 00268 00269 if (!cdr) /* don't die if the cdr is null */ 00270 return; 00271 00272 *ret = NULL; 00273 /* special vars (the ones from the struct ast_cdr when requested by name) 00274 I'd almost say we should convert all the stringed vals to vars */ 00275 00276 if (!strcasecmp(name, "clid")) 00277 ast_copy_string(workspace, cdr->clid, workspacelen); 00278 else if (!strcasecmp(name, "src")) 00279 ast_copy_string(workspace, cdr->src, workspacelen); 00280 else if (!strcasecmp(name, "dst")) 00281 ast_copy_string(workspace, cdr->dst, workspacelen); 00282 else if (!strcasecmp(name, "dcontext")) 00283 ast_copy_string(workspace, cdr->dcontext, workspacelen); 00284 else if (!strcasecmp(name, "channel")) 00285 ast_copy_string(workspace, cdr->channel, workspacelen); 00286 else if (!strcasecmp(name, "dstchannel")) 00287 ast_copy_string(workspace, cdr->dstchannel, workspacelen); 00288 else if (!strcasecmp(name, "lastapp")) 00289 ast_copy_string(workspace, cdr->lastapp, workspacelen); 00290 else if (!strcasecmp(name, "lastdata")) 00291 ast_copy_string(workspace, cdr->lastdata, workspacelen); 00292 else if (!strcasecmp(name, "start")) 00293 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen); 00294 else if (!strcasecmp(name, "answer")) 00295 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen); 00296 else if (!strcasecmp(name, "end")) 00297 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen); 00298 else if (!strcasecmp(name, "duration")) { 00299 snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000); 00300 } else if (!strcasecmp(name, "billsec")) { 00301 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); 00302 } else if (!strcasecmp(name, "disposition")) { 00303 if (raw) { 00304 snprintf(workspace, workspacelen, "%ld", cdr->disposition); 00305 } else { 00306 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); 00307 } 00308 } else if (!strcasecmp(name, "amaflags")) { 00309 if (raw) { 00310 snprintf(workspace, workspacelen, "%ld", cdr->amaflags); 00311 } else { 00312 ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); 00313 } 00314 } else if (!strcasecmp(name, "accountcode")) 00315 ast_copy_string(workspace, cdr->accountcode, workspacelen); 00316 else if (!strcasecmp(name, "peeraccount")) 00317 ast_copy_string(workspace, cdr->peeraccount, workspacelen); 00318 else if (!strcasecmp(name, "uniqueid")) 00319 ast_copy_string(workspace, cdr->uniqueid, workspacelen); 00320 else if (!strcasecmp(name, "linkedid")) 00321 ast_copy_string(workspace, cdr->linkedid, workspacelen); 00322 else if (!strcasecmp(name, "userfield")) 00323 ast_copy_string(workspace, cdr->userfield, workspacelen); 00324 else if (!strcasecmp(name, "sequence")) 00325 snprintf(workspace, workspacelen, "%d", cdr->sequence); 00326 else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) 00327 ast_copy_string(workspace, varbuf, workspacelen); 00328 else 00329 workspace[0] = '\0'; 00330 00331 if (!ast_strlen_zero(workspace)) 00332 *ret = workspace; 00333 }
static const char* ast_cdr_getvar_internal | ( | struct ast_cdr * | cdr, | |
const char * | name, | |||
int | recur | |||
) | [static] |
Definition at line 232 of file cdr.c.
References AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_name(), ast_var_value(), ast_cdr::next, and ast_cdr::varshead.
Referenced by ast_cdr_getvar().
00233 { 00234 if (ast_strlen_zero(name)) 00235 return NULL; 00236 00237 for (; cdr; cdr = recur ? cdr->next : NULL) { 00238 struct ast_var_t *variables; 00239 struct varshead *headp = &cdr->varshead; 00240 AST_LIST_TRAVERSE(headp, variables, entries) { 00241 if (!strcasecmp(name, ast_var_name(variables))) 00242 return ast_var_value(variables); 00243 } 00244 } 00245 00246 return NULL; 00247 }
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 898 of file cdr.c.
References ast_channel::_state, ast_cdr::accountcode, ast_channel::amaflags, ast_cdr::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_copy_string(), AST_STATE_UP, ast_test_flag, cdr_seq_inc(), ast_cdr::channel, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, ast_cdr::linkedid, ast_channel::macrocontext, ast_channel::macroexten, 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().
00899 { 00900 for ( ; cdr ; cdr = cdr->next) { 00901 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00902 ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); 00903 set_one_cid(cdr, c); 00904 cdr_seq_inc(cdr); 00905 00906 cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 00907 cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; 00908 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00909 ast_copy_string(cdr->peeraccount, c->peeraccount, sizeof(cdr->peeraccount)); 00910 /* Destination information */ 00911 ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst)); 00912 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext)); 00913 /* Unique call identifier */ 00914 ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid)); 00915 /* Linked call identifier */ 00916 ast_copy_string(cdr->linkedid, c->linkedid, sizeof(cdr->linkedid)); 00917 } 00918 } 00919 return 0; 00920 }
int ast_cdr_isset_unanswered | ( | void | ) |
Definition at line 185 of file cdr.c.
References unanswered.
Referenced by ring_entry(), and try_calling().
00186 { 00187 return unanswered; 00188 }
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 544 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.
00545 { 00546 struct ast_cdr *zcdr; 00547 struct ast_cdr *lto = NULL; 00548 struct ast_cdr *lfrom = NULL; 00549 int discard_from = 0; 00550 00551 if (!to || !from) 00552 return; 00553 00554 /* don't merge into locked CDR's -- it's bad business */ 00555 if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { 00556 zcdr = to; /* safety valve? */ 00557 while (to->next) { 00558 lto = to; 00559 to = to->next; 00560 } 00561 00562 if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { 00563 ast_log(LOG_WARNING, "Merging into locked CDR... no choice.\n"); 00564 to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */ 00565 lto = NULL; 00566 } 00567 } 00568 00569 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) { 00570 struct ast_cdr *llfrom = NULL; 00571 discard_from = 1; 00572 if (lto) { 00573 /* insert the from stuff after lto */ 00574 lto->next = from; 00575 lfrom = from; 00576 while (lfrom && lfrom->next) { 00577 if (!lfrom->next->next) 00578 llfrom = lfrom; 00579 lfrom = lfrom->next; 00580 } 00581 /* rip off the last entry and put a copy of the to at the end */ 00582 if (llfrom) { 00583 llfrom->next = to; 00584 } 00585 from = lfrom; 00586 } else { 00587 /* save copy of the current *to cdr */ 00588 struct ast_cdr tcdr; 00589 memcpy(&tcdr, to, sizeof(tcdr)); 00590 /* copy in the locked from cdr */ 00591 memcpy(to, from, sizeof(*to)); 00592 lfrom = from; 00593 while (lfrom && lfrom->next) { 00594 if (!lfrom->next->next) 00595 llfrom = lfrom; 00596 lfrom = lfrom->next; 00597 } 00598 from->next = NULL; 00599 /* rip off the last entry and put a copy of the to at the end */ 00600 if (llfrom == from) { 00601 to = to->next = ast_cdr_dup(&tcdr); 00602 } else if (llfrom) { 00603 to = llfrom->next = ast_cdr_dup(&tcdr); 00604 } 00605 from = lfrom; 00606 } 00607 } 00608 00609 if (!ast_tvzero(from->start)) { 00610 if (!ast_tvzero(to->start)) { 00611 if (ast_tvcmp(to->start, from->start) > 0 ) { 00612 to->start = from->start; /* use the earliest time */ 00613 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00614 } 00615 /* else nothing to do */ 00616 } else { 00617 to->start = from->start; 00618 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00619 } 00620 } 00621 if (!ast_tvzero(from->answer)) { 00622 if (!ast_tvzero(to->answer)) { 00623 if (ast_tvcmp(to->answer, from->answer) > 0 ) { 00624 to->answer = from->answer; /* use the earliest time */ 00625 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00626 } 00627 /* we got the earliest answer time, so we'll settle for that? */ 00628 } else { 00629 to->answer = from->answer; 00630 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00631 } 00632 } 00633 if (!ast_tvzero(from->end)) { 00634 if (!ast_tvzero(to->end)) { 00635 if (ast_tvcmp(to->end, from->end) < 0 ) { 00636 to->end = from->end; /* use the latest time */ 00637 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00638 to->duration = to->end.tv_sec - to->start.tv_sec; /* don't forget to update the duration, billsec, when we set end */ 00639 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00640 } 00641 /* else, nothing to do */ 00642 } else { 00643 to->end = from->end; 00644 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00645 to->duration = to->end.tv_sec - to->start.tv_sec; 00646 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00647 } 00648 } 00649 if (to->disposition < from->disposition) { 00650 to->disposition = from->disposition; 00651 from->disposition = AST_CDR_NOANSWER; 00652 } 00653 if (ast_strlen_zero(to->lastapp) && !ast_strlen_zero(from->lastapp)) { 00654 ast_copy_string(to->lastapp, from->lastapp, sizeof(to->lastapp)); 00655 from->lastapp[0] = 0; /* theft */ 00656 } 00657 if (ast_strlen_zero(to->lastdata) && !ast_strlen_zero(from->lastdata)) { 00658 ast_copy_string(to->lastdata, from->lastdata, sizeof(to->lastdata)); 00659 from->lastdata[0] = 0; /* theft */ 00660 } 00661 if (ast_strlen_zero(to->dcontext) && !ast_strlen_zero(from->dcontext)) { 00662 ast_copy_string(to->dcontext, from->dcontext, sizeof(to->dcontext)); 00663 from->dcontext[0] = 0; /* theft */ 00664 } 00665 if (ast_strlen_zero(to->dstchannel) && !ast_strlen_zero(from->dstchannel)) { 00666 ast_copy_string(to->dstchannel, from->dstchannel, sizeof(to->dstchannel)); 00667 from->dstchannel[0] = 0; /* theft */ 00668 } 00669 if (!ast_strlen_zero(from->channel) && (ast_strlen_zero(to->channel) || !strncasecmp(from->channel, "Agent/", 6))) { 00670 ast_copy_string(to->channel, from->channel, sizeof(to->channel)); 00671 from->channel[0] = 0; /* theft */ 00672 } 00673 if (ast_strlen_zero(to->src) && !ast_strlen_zero(from->src)) { 00674 ast_copy_string(to->src, from->src, sizeof(to->src)); 00675 from->src[0] = 0; /* theft */ 00676 } 00677 if (ast_strlen_zero(to->clid) && !ast_strlen_zero(from->clid)) { 00678 ast_copy_string(to->clid, from->clid, sizeof(to->clid)); 00679 from->clid[0] = 0; /* theft */ 00680 } 00681 if (ast_strlen_zero(to->dst) && !ast_strlen_zero(from->dst)) { 00682 ast_copy_string(to->dst, from->dst, sizeof(to->dst)); 00683 from->dst[0] = 0; /* theft */ 00684 } 00685 if (!to->amaflags) 00686 to->amaflags = AST_CDR_DOCUMENTATION; 00687 if (!from->amaflags) 00688 from->amaflags = AST_CDR_DOCUMENTATION; /* make sure both amaflags are set to something (DOC is default) */ 00689 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) { 00690 to->amaflags = from->amaflags; 00691 } 00692 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) { 00693 ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode)); 00694 } 00695 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->peeraccount) && !ast_strlen_zero(from->peeraccount))) { 00696 ast_copy_string(to->peeraccount, from->peeraccount, sizeof(to->peeraccount)); 00697 } 00698 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) { 00699 ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield)); 00700 } 00701 /* flags, varsead, ? */ 00702 cdr_merge_vars(from, to); 00703 00704 if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS)) 00705 ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS); 00706 if (ast_test_flag(from, AST_CDR_FLAG_POSTED)) 00707 ast_set_flag(to, AST_CDR_FLAG_POSTED); 00708 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) 00709 ast_set_flag(to, AST_CDR_FLAG_LOCKED); 00710 if (ast_test_flag(from, AST_CDR_FLAG_CHILD)) 00711 ast_set_flag(to, AST_CDR_FLAG_CHILD); 00712 if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED)) 00713 ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED); 00714 00715 /* last, but not least, we need to merge any forked CDRs to the 'to' cdr */ 00716 while (from->next) { 00717 /* just rip 'em off the 'from' and insert them on the 'to' */ 00718 zcdr = from->next; 00719 from->next = zcdr->next; 00720 zcdr->next = NULL; 00721 /* zcdr is now ripped from the current list; */ 00722 ast_cdr_append(to, zcdr); 00723 } 00724 if (discard_from) 00725 ast_cdr_discard(from); 00726 }
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 777 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().
00778 { 00779 while (cdr) { 00780 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00781 check_post(cdr); 00782 cdr->disposition = AST_CDR_NOANSWER; 00783 } 00784 cdr = cdr->next; 00785 } 00786 }
int ast_cdr_register | ( | const char * | name, | |
const char * | desc, | |||
ast_cdrbe | be | |||
) |
Register a CDR driver. Each registered CDR driver generates a CDR.
Register a CDR handling engine.
0 | on success. | |
-1 | on error |
Definition at line 130 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, ast_cdr_beitem::list, LOG_WARNING, and ast_cdr_beitem::name.
Referenced by load_config(), load_module(), odbc_load_module(), and unload_module().
00131 { 00132 struct ast_cdr_beitem *i = NULL; 00133 00134 if (!name) 00135 return -1; 00136 00137 if (!be) { 00138 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name); 00139 return -1; 00140 } 00141 00142 AST_RWLIST_WRLOCK(&be_list); 00143 AST_RWLIST_TRAVERSE(&be_list, i, list) { 00144 if (!strcasecmp(name, i->name)) { 00145 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name); 00146 AST_RWLIST_UNLOCK(&be_list); 00147 return -1; 00148 } 00149 } 00150 00151 if (!(i = ast_calloc(1, sizeof(*i)))) 00152 return -1; 00153 00154 i->be = be; 00155 ast_copy_string(i->name, name, sizeof(i->name)); 00156 ast_copy_string(i->desc, desc, sizeof(i->desc)); 00157 00158 AST_RWLIST_INSERT_HEAD(&be_list, i, list); 00159 AST_RWLIST_UNLOCK(&be_list); 00160 00161 return 0; 00162 }
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 1150 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().
01151 { 01152 struct ast_cdr *duplicate; 01153 struct ast_flags flags = { 0 }; 01154 01155 if (_flags) 01156 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); 01157 01158 for ( ; cdr ; cdr = cdr->next) { 01159 /* Detach if post is requested */ 01160 if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01161 if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) { 01162 ast_cdr_end(cdr); 01163 if ((duplicate = ast_cdr_dup_unique_swap(cdr))) { 01164 ast_cdr_detach(duplicate); 01165 } 01166 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 01167 } 01168 01169 /* enable CDR only */ 01170 if (ast_test_flag(&flags, AST_CDR_FLAG_POST_ENABLE)) { 01171 ast_clear_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01172 continue; 01173 } 01174 01175 /* clear variables */ 01176 if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) { 01177 ast_cdr_free_vars(cdr, 0); 01178 } 01179 01180 /* Reset to initial state */ 01181 ast_clear_flag(cdr, AST_FLAGS_ALL); 01182 memset(&cdr->start, 0, sizeof(cdr->start)); 01183 memset(&cdr->end, 0, sizeof(cdr->end)); 01184 memset(&cdr->answer, 0, sizeof(cdr->answer)); 01185 cdr->billsec = 0; 01186 cdr->duration = 0; 01187 ast_cdr_start(cdr); 01188 cdr->disposition = AST_CDR_NOANSWER; 01189 } 01190 } 01191 }
int ast_cdr_serialize_variables | ( | struct ast_cdr * | cdr, | |
struct ast_str ** | buf, | |||
char | delim, | |||
char | sep, | |||
int | recur | |||
) |
Definition at line 410 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, LOG_ERROR, ast_cdr::next, S_OR, total, var, and ast_cdr::varshead.
Referenced by handle_showchan().
00411 { 00412 struct ast_var_t *variables; 00413 const char *var; 00414 char *tmp; 00415 char workspace[256]; 00416 int total = 0, x = 0, i; 00417 00418 ast_str_reset(*buf); 00419 00420 for (; cdr; cdr = recur ? cdr->next : NULL) { 00421 if (++x > 1) 00422 ast_str_append(buf, 0, "\n"); 00423 00424 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) { 00425 if (!(var = ast_var_name(variables))) { 00426 continue; 00427 } 00428 00429 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variables), ""), sep) < 0) { 00430 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00431 break; 00432 } 00433 00434 total++; 00435 } 00436 00437 for (i = 0; cdr_readonly_vars[i]; i++) { 00438 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 */ 00439 ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0); 00440 if (!tmp) 00441 continue; 00442 00443 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep) < 0) { 00444 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00445 break; 00446 } else 00447 total++; 00448 } 00449 } 00450 00451 return total; 00452 }
int ast_cdr_setaccount | ( | struct ast_channel * | chan, | |
const char * | account | |||
) |
Set account code, will generate AMI event.
Definition at line 991 of file cdr.c.
References ast_cdr::accountcode, accountcode, AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_manager_event, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, 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().
00992 { 00993 struct ast_cdr *cdr = chan->cdr; 00994 const char *old_acct = ""; 00995 00996 if (!ast_strlen_zero(chan->accountcode)) { 00997 old_acct = ast_strdupa(chan->accountcode); 00998 } 00999 01000 ast_string_field_set(chan, accountcode, account); 01001 for ( ; cdr ; cdr = cdr->next) { 01002 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01003 ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode)); 01004 } 01005 } 01006 01007 ast_manager_event(chan, EVENT_FLAG_CALL, "NewAccountCode", 01008 "Channel: %s\r\n" 01009 "Uniqueid: %s\r\n" 01010 "AccountCode: %s\r\n" 01011 "OldAccountCode: %s\r\n", 01012 chan->name, chan->uniqueid, chan->accountcode, old_acct); 01013 01014 return 0; 01015 }
int ast_cdr_setamaflags | ( | struct ast_channel * | chan, | |
const char * | amaflags | |||
) |
Set AMA flags for channel.
Definition at line 1043 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().
01044 { 01045 struct ast_cdr *cdr; 01046 int newflag = ast_cdr_amaflags2int(flag); 01047 if (newflag) { 01048 for (cdr = chan->cdr; cdr; cdr = cdr->next) { 01049 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01050 cdr->amaflags = newflag; 01051 } 01052 } 01053 } 01054 01055 return 0; 01056 }
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 835 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().
00836 { 00837 00838 for (; cdr; cdr = cdr->next) { 00839 if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 00840 continue; 00841 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00842 continue; 00843 check_post(cdr); 00844 cdr->answer = t; 00845 } 00846 }
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 823 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().
00824 { 00825 00826 for (; cdr; cdr = cdr->next) { 00827 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00828 check_post(cdr); 00829 ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp)); 00830 ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata)); 00831 } 00832 } 00833 }
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 884 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().
00885 { 00886 for (; cdr; cdr = cdr->next) { 00887 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00888 set_one_cid(cdr, c); 00889 } 00890 return 0; 00891 }
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 813 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().
00814 { 00815 for (; cdr; cdr = cdr->next) { 00816 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00817 check_post(cdr); 00818 ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel)); 00819 } 00820 } 00821 }
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 848 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().
00849 { 00850 00851 for (; cdr; cdr = cdr->next) { 00852 if (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00853 continue; 00854 check_post(cdr); 00855 cdr->disposition = disposition; 00856 } 00857 }
int ast_cdr_setpeeraccount | ( | struct ast_channel * | chan, | |
const char * | account | |||
) |
Set the peer account.
Definition at line 1017 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_manager_event, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, EVENT_FLAG_CALL, ast_cdr::next, and ast_cdr::peeraccount.
Referenced by cdr_write().
01018 { 01019 struct ast_cdr *cdr = chan->cdr; 01020 const char *old_acct = ""; 01021 01022 if (!ast_strlen_zero(chan->peeraccount)) { 01023 old_acct = ast_strdupa(chan->peeraccount); 01024 } 01025 01026 ast_string_field_set(chan, peeraccount, account); 01027 for ( ; cdr ; cdr = cdr->next) { 01028 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01029 ast_copy_string(cdr->peeraccount, chan->peeraccount, sizeof(cdr->peeraccount)); 01030 } 01031 } 01032 01033 ast_manager_event(chan, EVENT_FLAG_CALL, "NewPeerAccount", 01034 "Channel: %s\r\n" 01035 "Uniqueid: %s\r\n" 01036 "PeerAccount: %s\r\n" 01037 "OldPeerAccount: %s\r\n", 01038 chan->name, chan->uniqueid, chan->peeraccount, old_acct); 01039 01040 return 0; 01041 }
int ast_cdr_setuserfield | ( | struct ast_channel * | chan, | |
const char * | userfield | |||
) |
Set CDR user field for channel (stored in CDR).
Definition at line 1058 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(), ast_bridge_call(), cdr_write(), handle_request_info(), and start_monitor_exec().
01059 { 01060 struct ast_cdr *cdr = chan->cdr; 01061 01062 for ( ; cdr ; cdr = cdr->next) { 01063 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 01064 ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield)); 01065 } 01066 01067 return 0; 01068 }
int ast_cdr_setvar | ( | struct ast_cdr * | cdr, | |
const char * | name, | |||
const char * | value, | |||
int | recur | |||
) |
Set a CDR channel variable
Definition at line 343 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().
00344 { 00345 struct ast_var_t *newvariable; 00346 struct varshead *headp; 00347 int x; 00348 00349 for (x = 0; cdr_readonly_vars[x]; x++) { 00350 if (!strcasecmp(name, cdr_readonly_vars[x])) { 00351 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name); 00352 return -1; 00353 } 00354 } 00355 00356 if (!cdr) { 00357 ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n"); 00358 return -1; 00359 } 00360 00361 for (; cdr; cdr = recur ? cdr->next : NULL) { 00362 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00363 continue; 00364 headp = &cdr->varshead; 00365 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 00366 if (!strcasecmp(ast_var_name(newvariable), name)) { 00367 /* there is already such a variable, delete it */ 00368 AST_LIST_REMOVE_CURRENT(entries); 00369 ast_var_delete(newvariable); 00370 break; 00371 } 00372 } 00373 AST_LIST_TRAVERSE_SAFE_END; 00374 00375 if (value) { 00376 newvariable = ast_var_assign(name, value); 00377 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 00378 } 00379 } 00380 00381 return 0; 00382 }
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 1193 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().
01194 { 01195 struct ast_flags flags = { 0 }; 01196 01197 if (_flags) 01198 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); 01199 01200 /* Reset to initial state */ 01201 if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) { /* But do NOT lose the NoCDR() setting */ 01202 ast_clear_flag(cdr, AST_FLAGS_ALL); 01203 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01204 } else { 01205 ast_clear_flag(cdr, AST_FLAGS_ALL); 01206 } 01207 01208 memset(&cdr->start, 0, sizeof(cdr->start)); 01209 memset(&cdr->end, 0, sizeof(cdr->end)); 01210 memset(&cdr->answer, 0, sizeof(cdr->answer)); 01211 cdr->billsec = 0; 01212 cdr->duration = 0; 01213 ast_cdr_start(cdr); 01214 cdr->disposition = AST_CDR_NULL; 01215 }
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 728 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(), clear_caller(), and findmeexec().
00729 { 00730 for (; cdr; cdr = cdr->next) { 00731 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00732 check_post(cdr); 00733 cdr->start = ast_tvnow(); 00734 } 00735 } 00736 }
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 1271 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().
01272 { 01273 struct ast_cdr_batch_item *oldbatchitems = NULL; 01274 pthread_t batch_post_thread = AST_PTHREADT_NULL; 01275 01276 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */ 01277 if (!batch || !batch->head) 01278 return; 01279 01280 /* move the old CDRs aside, and prepare a new CDR batch */ 01281 ast_mutex_lock(&cdr_batch_lock); 01282 oldbatchitems = batch->head; 01283 reset_batch(); 01284 ast_mutex_unlock(&cdr_batch_lock); 01285 01286 /* if configured, spawn a new thread to post these CDRs, 01287 also try to save as much as possible if we are shutting down safely */ 01288 if (batchscheduleronly || do_shutdown) { 01289 ast_debug(1, "CDR single-threaded batch processing begins now\n"); 01290 do_batch_backend_process(oldbatchitems); 01291 } else { 01292 if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) { 01293 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n"); 01294 do_batch_backend_process(oldbatchitems); 01295 } else { 01296 ast_debug(1, "CDR multi-threaded batch processing begins now\n"); 01297 } 01298 } 01299 }
void ast_cdr_unregister | ( | const char * | name | ) |
Unregister a CDR handling engine.
unregister a CDR driver
Definition at line 165 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, ast_cdr_beitem::list, and ast_cdr_beitem::name.
Referenced by load_config(), odbc_load_module(), reload(), tds_unload_module(), and unload_module().
00166 { 00167 struct ast_cdr_beitem *i = NULL; 00168 00169 AST_RWLIST_WRLOCK(&be_list); 00170 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { 00171 if (!strcasecmp(name, i->name)) { 00172 AST_RWLIST_REMOVE_CURRENT(list); 00173 break; 00174 } 00175 } 00176 AST_RWLIST_TRAVERSE_SAFE_END; 00177 AST_RWLIST_UNLOCK(&be_list); 00178 00179 if (i) { 00180 ast_verb(2, "Unregistered '%s' CDR backend\n", name); 00181 ast_free(i); 00182 } 00183 }
int ast_cdr_update | ( | struct ast_channel * | chan | ) |
Update CDR on a channel.
Definition at line 1084 of file cdr.c.
References 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_cdr::linkedid, ast_channel::macrocontext, ast_channel::macroexten, 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(), findmeexec(), and local_call().
01085 { 01086 struct ast_cdr *cdr = c->cdr; 01087 01088 for ( ; cdr ; cdr = cdr->next) { 01089 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01090 set_one_cid(cdr, c); 01091 01092 /* Copy account code et-al */ 01093 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 01094 ast_copy_string(cdr->peeraccount, c->peeraccount, sizeof(cdr->peeraccount)); 01095 ast_copy_string(cdr->linkedid, c->linkedid, sizeof(cdr->linkedid)); 01096 01097 /* Destination information */ /* XXX privilege macro* ? */ 01098 ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst)); 01099 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext)); 01100 } 01101 } 01102 01103 return 0; 01104 }
static void cdr_engine_shutdown | ( | void | ) | [static] |
Definition at line 1628 of file cdr.c.
References ast_cli_unregister(), ast_cond_destroy, ast_free, AST_PTHREADT_NULL, batch, cdr_pending_cond, cdr_thread, cli_status, cli_submit, and sched_context_destroy().
Referenced by ast_cdr_engine_init().
01629 { 01630 if (cdr_thread != AST_PTHREADT_NULL) { 01631 /* wake up the thread so it will exit */ 01632 pthread_cancel(cdr_thread); 01633 pthread_kill(cdr_thread, SIGURG); 01634 pthread_join(cdr_thread, NULL); 01635 cdr_thread = AST_PTHREADT_NULL; 01636 ast_cond_destroy(&cdr_pending_cond); 01637 } 01638 ast_cli_unregister(&cli_submit); 01639 01640 ast_cli_unregister(&cli_status); 01641 sched_context_destroy(sched); 01642 sched = NULL; 01643 ast_free(batch); 01644 batch = NULL; 01645 }
static void cdr_get_tv | ( | struct timeval | when, | |
const char * | fmt, | |||
char * | buf, | |||
int | bufsize | |||
) | [static] |
Definition at line 249 of file cdr.c.
References ast_localtime(), and ast_strftime().
Referenced by ast_cdr_getvar().
00250 { 00251 if (fmt == NULL) { /* raw mode */ 00252 snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec); 00253 } else { 00254 if (when.tv_sec) { 00255 struct ast_tm tm; 00256 00257 ast_localtime(&when, &tm, NULL); 00258 ast_strftime(buf, bufsize, fmt, &tm); 00259 } 00260 } 00261 }
Definition at line 509 of file cdr.c.
References AST_LIST_MOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_var_name(), ast_var_value(), LOG_NOTICE, and ast_cdr::varshead.
Referenced by ast_cdr_merge().
00510 { 00511 struct ast_var_t *variablesfrom,*variablesto; 00512 struct varshead *headpfrom = &to->varshead; 00513 struct varshead *headpto = &from->varshead; 00514 AST_LIST_TRAVERSE_SAFE_BEGIN(headpfrom, variablesfrom, entries) { 00515 /* for every var in from, stick it in to */ 00516 const char *fromvarname, *fromvarval; 00517 const char *tovarname = NULL, *tovarval = NULL; 00518 fromvarname = ast_var_name(variablesfrom); 00519 fromvarval = ast_var_value(variablesfrom); 00520 tovarname = 0; 00521 00522 /* now, quick see if that var is in the 'to' cdr already */ 00523 AST_LIST_TRAVERSE(headpto, variablesto, entries) { 00524 00525 /* now, quick see if that var is in the 'to' cdr already */ 00526 if ( strcasecmp(fromvarname, ast_var_name(variablesto)) == 0 ) { 00527 tovarname = ast_var_name(variablesto); 00528 tovarval = ast_var_value(variablesto); 00529 break; 00530 } 00531 } 00532 if (tovarname && strcasecmp(fromvarval,tovarval) != 0) { /* this message here to see how irritating the userbase finds it */ 00533 ast_log(LOG_NOTICE, "Merging CDR's: variable %s value %s dropped in favor of value %s\n", tovarname, fromvarval, tovarval); 00534 continue; 00535 } else if (tovarname && strcasecmp(fromvarval,tovarval) == 0) /* if they are the same, the job is done */ 00536 continue; 00537 00538 /* rip this var out of the from cdr, and stick it in the to cdr */ 00539 AST_LIST_MOVE_CURRENT(headpto, entries); 00540 } 00541 AST_LIST_TRAVERSE_SAFE_END; 00542 }
static int cdr_seq_inc | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 893 of file cdr.c.
References ast_atomic_fetchadd_int(), cdr_sequence, and ast_cdr::sequence.
Referenced by ast_cdr_dup_unique(), ast_cdr_dup_unique_swap(), and ast_cdr_init().
00894 { 00895 return (cdr->sequence = ast_atomic_fetchadd_int(&cdr_sequence, +1)); 00896 }
int check_cdr_enabled | ( | void | ) |
Return TRUE if CDR subsystem is enabled.
Definition at line 120 of file cdr.c.
References enabled.
Referenced by action_coresettings(), and handle_show_settings().
00121 { 00122 return enabled; 00123 }
static void check_post | ( | struct ast_cdr * | cdr | ) | [static] |
print a warning if cdr already posted
Definition at line 468 of file cdr.c.
References AST_CDR_FLAG_POSTED, ast_log(), ast_test_flag, ast_cdr::channel, LOG_NOTICE, and S_OR.
Referenced by ast_cdr_answer(), ast_cdr_busy(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_noanswer(), ast_cdr_setanswer(), ast_cdr_setapp(), ast_cdr_setdestchan(), ast_cdr_setdisposition(), ast_cdr_start(), and post_cdr().
00469 { 00470 if (!cdr) 00471 return; 00472 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00473 ast_log(LOG_NOTICE, "CDR on channel '%s' already posted\n", S_OR(cdr->channel, "<unknown>")); 00474 }
static void* do_batch_backend_process | ( | void * | data | ) | [static] |
Definition at line 1254 of file cdr.c.
References ast_cdr_free(), ast_free, ast_cdr_batch_item::cdr, ast_cdr_batch_item::next, and post_cdr().
Referenced by ast_cdr_submit_batch().
01255 { 01256 struct ast_cdr_batch_item *processeditem; 01257 struct ast_cdr_batch_item *batchitem = data; 01258 01259 /* Push each CDR into storage mechanism(s) and free all the memory */ 01260 while (batchitem) { 01261 post_cdr(batchitem->cdr); 01262 ast_cdr_free(batchitem->cdr); 01263 processeditem = batchitem; 01264 batchitem = batchitem->next; 01265 ast_free(processeditem); 01266 } 01267 01268 return NULL; 01269 }
static void* do_cdr | ( | void * | data | ) | [static] |
Definition at line 1390 of file cdr.c.
References ast_cond_timedwait, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_samp2tv(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), ast_tvnow(), cdr_pending_cond, and cdr_pending_lock.
Referenced by do_reload().
01391 { 01392 struct timespec timeout; 01393 int schedms; 01394 int numevents = 0; 01395 01396 for (;;) { 01397 struct timeval now; 01398 schedms = ast_sched_wait(sched); 01399 /* this shouldn't happen, but provide a 1 second default just in case */ 01400 if (schedms <= 0) 01401 schedms = 1000; 01402 now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000)); 01403 timeout.tv_sec = now.tv_sec; 01404 timeout.tv_nsec = now.tv_usec * 1000; 01405 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */ 01406 ast_mutex_lock(&cdr_pending_lock); 01407 ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout); 01408 numevents = ast_sched_runq(sched); 01409 ast_mutex_unlock(&cdr_pending_lock); 01410 ast_debug(2, "Processed %d scheduled CDR batches from the run queue\n", numevents); 01411 } 01412 01413 return NULL; 01414 }
static void do_reload | ( | int | reload | ) | [static] |
Definition at line 1498 of file cdr.c.
References ast_cdr_engine_term(), ast_cli_register(), ast_cli_unregister(), ast_cond_destroy, ast_cond_init, ast_config_destroy(), ast_config_load2(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN, AST_OPT_FLAG_INITIATED_SECONDS, ast_options, ast_pthread_create_background, AST_PTHREADT_NULL, ast_register_atexit(), ast_sched_add(), AST_SCHED_DEL, ast_set2_flag, ast_true(), ast_unregister_atexit(), ast_variable_retrieve(), BATCH_SAFE_SHUTDOWN_DEFAULT, BATCH_SCHEDULER_ONLY_DEFAULT, BATCH_SIZE_DEFAULT, BATCH_TIME_DEFAULT, batchmode, BATCHMODE_DEFAULT, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_batch_lock, cdr_pending_cond, cdr_sched, cdr_sched_lock, cdr_thread, cli_submit, config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, do_cdr(), enabled, ENABLED_DEFAULT, EVENT_FLAG_SYSTEM, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, submit_scheduled_batch(), unanswered, and UNANSWERED_DEFAULT.
Referenced by ast_cdr_engine_init(), and ast_cdr_engine_reload().
01499 { 01500 struct ast_config *config; 01501 const char *enabled_value; 01502 const char *unanswered_value; 01503 const char *batched_value; 01504 const char *scheduleronly_value; 01505 const char *batchsafeshutdown_value; 01506 const char *size_value; 01507 const char *time_value; 01508 const char *end_before_h_value; 01509 const char *initiatedseconds_value; 01510 int cfg_size; 01511 int cfg_time; 01512 int was_enabled; 01513 int was_batchmode; 01514 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01515 01516 if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 01517 return; 01518 } 01519 01520 ast_mutex_lock(&cdr_batch_lock); 01521 01522 was_enabled = enabled; 01523 was_batchmode = batchmode; 01524 01525 batchsize = BATCH_SIZE_DEFAULT; 01526 batchtime = BATCH_TIME_DEFAULT; 01527 batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT; 01528 batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT; 01529 enabled = ENABLED_DEFAULT; 01530 batchmode = BATCHMODE_DEFAULT; 01531 unanswered = UNANSWERED_DEFAULT; 01532 01533 if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) { 01534 ast_mutex_unlock(&cdr_batch_lock); 01535 return; 01536 } 01537 01538 /* don't run the next scheduled CDR posting while reloading */ 01539 ast_mutex_lock(&cdr_sched_lock); 01540 AST_SCHED_DEL(sched, cdr_sched); 01541 ast_mutex_unlock(&cdr_sched_lock); 01542 01543 if (config) { 01544 if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { 01545 enabled = ast_true(enabled_value); 01546 } 01547 if ((unanswered_value = ast_variable_retrieve(config, "general", "unanswered"))) { 01548 unanswered = ast_true(unanswered_value); 01549 } 01550 if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) { 01551 batchmode = ast_true(batched_value); 01552 } 01553 if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) { 01554 batchscheduleronly = ast_true(scheduleronly_value); 01555 } 01556 if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) { 01557 batchsafeshutdown = ast_true(batchsafeshutdown_value); 01558 } 01559 if ((size_value = ast_variable_retrieve(config, "general", "size"))) { 01560 if (sscanf(size_value, "%30d", &cfg_size) < 1) 01561 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value); 01562 else if (cfg_size < 0) 01563 ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size); 01564 else 01565 batchsize = cfg_size; 01566 } 01567 if ((time_value = ast_variable_retrieve(config, "general", "time"))) { 01568 if (sscanf(time_value, "%30d", &cfg_time) < 1) 01569 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value); 01570 else if (cfg_time < 0) 01571 ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time); 01572 else 01573 batchtime = cfg_time; 01574 } 01575 if ((end_before_h_value = ast_variable_retrieve(config, "general", "endbeforehexten"))) 01576 ast_set2_flag(&ast_options, ast_true(end_before_h_value), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN); 01577 if ((initiatedseconds_value = ast_variable_retrieve(config, "general", "initiatedseconds"))) 01578 ast_set2_flag(&ast_options, ast_true(initiatedseconds_value), AST_OPT_FLAG_INITIATED_SECONDS); 01579 } 01580 01581 if (enabled && !batchmode) { 01582 ast_log(LOG_NOTICE, "CDR simple logging enabled.\n"); 01583 } else if (enabled && batchmode) { 01584 ast_mutex_lock(&cdr_sched_lock); 01585 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); 01586 ast_mutex_unlock(&cdr_sched_lock); 01587 ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime); 01588 } else { 01589 ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n"); 01590 } 01591 01592 /* if this reload enabled the CDR batch mode, create the background thread 01593 if it does not exist */ 01594 if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) { 01595 ast_cond_init(&cdr_pending_cond, NULL); 01596 if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) { 01597 ast_log(LOG_ERROR, "Unable to start CDR thread.\n"); 01598 ast_mutex_lock(&cdr_sched_lock); 01599 AST_SCHED_DEL(sched, cdr_sched); 01600 ast_mutex_unlock(&cdr_sched_lock); 01601 } else { 01602 ast_cli_register(&cli_submit); 01603 ast_register_atexit(ast_cdr_engine_term); 01604 } 01605 /* if this reload disabled the CDR and/or batch mode and there is a background thread, 01606 kill it */ 01607 } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) { 01608 /* wake up the thread so it will exit */ 01609 pthread_cancel(cdr_thread); 01610 pthread_kill(cdr_thread, SIGURG); 01611 pthread_join(cdr_thread, NULL); 01612 cdr_thread = AST_PTHREADT_NULL; 01613 ast_cond_destroy(&cdr_pending_cond); 01614 ast_cli_unregister(&cli_submit); 01615 ast_unregister_atexit(ast_cdr_engine_term); 01616 /* if leaving batch mode, then post the CDRs in the batch, 01617 and don't reschedule, since we are stopping CDR logging */ 01618 if (!batchmode && was_batchmode) { 01619 ast_cdr_engine_term(); 01620 } 01621 } 01622 01623 ast_mutex_unlock(&cdr_batch_lock); 01624 ast_config_destroy(config); 01625 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: CDR\r\nMessage: CDR subsystem reload requested\r\n"); 01626 }
static char* handle_cli_status | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1416 of file cdr.c.
References ast_cli_args::argc, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_sched_when(), batch, batchmode, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_sched, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, enabled, ESS, ast_cli_args::fd, ast_cdr_beitem::list, ast_cdr_beitem::name, ast_cdr_batch::size, unanswered, and ast_cli_entry::usage.
01417 { 01418 struct ast_cdr_beitem *beitem=NULL; 01419 int cnt=0; 01420 long nextbatchtime=0; 01421 01422 switch (cmd) { 01423 case CLI_INIT: 01424 e->command = "cdr show status"; 01425 e->usage = 01426 "Usage: cdr show status\n" 01427 " Displays the Call Detail Record engine system status.\n"; 01428 return NULL; 01429 case CLI_GENERATE: 01430 return NULL; 01431 } 01432 01433 if (a->argc > 3) 01434 return CLI_SHOWUSAGE; 01435 01436 ast_cli(a->fd, "\n"); 01437 ast_cli(a->fd, "Call Detail Record (CDR) settings\n"); 01438 ast_cli(a->fd, "----------------------------------\n"); 01439 ast_cli(a->fd, " Logging: %s\n", enabled ? "Enabled" : "Disabled"); 01440 ast_cli(a->fd, " Mode: %s\n", batchmode ? "Batch" : "Simple"); 01441 if (enabled) { 01442 ast_cli(a->fd, " Log unanswered calls: %s\n\n", unanswered ? "Yes" : "No"); 01443 if (batchmode) { 01444 ast_cli(a->fd, "* Batch Mode Settings\n"); 01445 ast_cli(a->fd, " -------------------\n"); 01446 if (batch) 01447 cnt = batch->size; 01448 if (cdr_sched > -1) 01449 nextbatchtime = ast_sched_when(sched, cdr_sched); 01450 ast_cli(a->fd, " Safe shutdown: %s\n", batchsafeshutdown ? "Enabled" : "Disabled"); 01451 ast_cli(a->fd, " Threading model: %s\n", batchscheduleronly ? "Scheduler only" : "Scheduler plus separate threads"); 01452 ast_cli(a->fd, " Current batch size: %d record%s\n", cnt, ESS(cnt)); 01453 ast_cli(a->fd, " Maximum batch size: %d record%s\n", batchsize, ESS(batchsize)); 01454 ast_cli(a->fd, " Maximum batch time: %d second%s\n", batchtime, ESS(batchtime)); 01455 ast_cli(a->fd, " Next batch processing time: %ld second%s\n\n", nextbatchtime, ESS(nextbatchtime)); 01456 } 01457 ast_cli(a->fd, "* Registered Backends\n"); 01458 ast_cli(a->fd, " -------------------\n"); 01459 AST_RWLIST_RDLOCK(&be_list); 01460 if (AST_RWLIST_EMPTY(&be_list)) { 01461 ast_cli(a->fd, " (none)\n"); 01462 } else { 01463 AST_RWLIST_TRAVERSE(&be_list, beitem, list) { 01464 ast_cli(a->fd, " %s\n", beitem->name); 01465 } 01466 } 01467 AST_RWLIST_UNLOCK(&be_list); 01468 ast_cli(a->fd, "\n"); 01469 } 01470 01471 return CLI_SUCCESS; 01472 }
static char* handle_cli_submit | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1474 of file cdr.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, submit_unscheduled_batch(), and ast_cli_entry::usage.
01475 { 01476 switch (cmd) { 01477 case CLI_INIT: 01478 e->command = "cdr submit"; 01479 e->usage = 01480 "Usage: cdr submit\n" 01481 " Posts all pending batched CDR data to the configured CDR backend engine modules.\n"; 01482 return NULL; 01483 case CLI_GENERATE: 01484 return NULL; 01485 } 01486 if (a->argc > 2) 01487 return CLI_SHOWUSAGE; 01488 01489 submit_unscheduled_batch(); 01490 ast_cli(a->fd, "Submitted CDRs to backend engines for processing. This may take a while.\n"); 01491 01492 return CLI_SUCCESS; 01493 }
static int init_batch | ( | void | ) | [static] |
Definition at line 1243 of file cdr.c.
References ast_malloc, batch, and reset_batch().
Referenced by ast_cdr_detach().
01244 { 01245 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */ 01246 if (!(batch = ast_malloc(sizeof(*batch)))) 01247 return -1; 01248 01249 reset_batch(); 01250 01251 return 0; 01252 }
static void post_cdr | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 1119 of file cdr.c.
References AST_CDR_ANSWERED, AST_CDR_FLAG_DIALED, AST_CDR_FLAG_ORIGINATED, AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_cdr_beitem::be, ast_cdr::channel, check_post(), ast_cdr::disposition, ast_cdr::dstchannel, ast_cdr_beitem::list, ast_cdr::next, and unanswered.
Referenced by ast_cdr_detach(), and do_batch_backend_process().
01120 { 01121 struct ast_cdr_beitem *i; 01122 01123 for ( ; cdr ; cdr = cdr->next) { 01124 if (!unanswered && cdr->disposition < AST_CDR_ANSWERED && (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) { 01125 /* For people, who don't want to see unanswered single-channel events */ 01126 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01127 continue; 01128 } 01129 01130 /* don't post CDRs that are for dialed channels unless those 01131 * channels were originated from asterisk (pbx_spool, manager, 01132 * cli) */ 01133 if (ast_test_flag(cdr, AST_CDR_FLAG_DIALED) && !ast_test_flag(cdr, AST_CDR_FLAG_ORIGINATED)) { 01134 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01135 continue; 01136 } 01137 01138 check_post(cdr); 01139 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 01140 if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) 01141 continue; 01142 AST_RWLIST_RDLOCK(&be_list); 01143 AST_RWLIST_TRAVERSE(&be_list, i, list) { 01144 i->be(cdr); 01145 } 01146 AST_RWLIST_UNLOCK(&be_list); 01147 } 01148 }
static void reset_batch | ( | void | ) | [static] |
Definition at line 1235 of file cdr.c.
References batch, ast_cdr_batch::head, ast_cdr_batch::size, and ast_cdr_batch::tail.
Referenced by ast_cdr_submit_batch(), and init_batch().
static void set_one_cid | ( | struct ast_cdr * | cdr, | |
struct ast_channel * | c | |||
) | [static] |
Definition at line 860 of file cdr.c.
References ast_party_caller::ani, ast_callerid_merge(), ast_cdr_setvar(), ast_copy_string(), ast_channel::caller, ast_cdr::clid, ast_channel::dialed, ast_party_caller::id, ast_party_id::name, ast_party_dialed::number, ast_party_id::number, S_COR, S_OR, ast_cdr::src, ast_party_subaddress::str, ast_party_dialed::str, ast_party_name::str, ast_party_number::str, ast_party_dialed::subaddress, ast_party_id::subaddress, ast_party_subaddress::valid, ast_party_name::valid, and ast_party_number::valid.
Referenced by ast_cdr_init(), ast_cdr_setcid(), and ast_cdr_update().
00861 { 00862 const char *num; 00863 00864 if (!cdr) { 00865 return; 00866 } 00867 00868 /* Grab source from ANI or normal Caller*ID */ 00869 num = S_COR(c->caller.ani.number.valid, c->caller.ani.number.str, 00870 S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)); 00871 ast_callerid_merge(cdr->clid, sizeof(cdr->clid), 00872 S_COR(c->caller.id.name.valid, c->caller.id.name.str, NULL), num, ""); 00873 ast_copy_string(cdr->src, S_OR(num, ""), sizeof(cdr->src)); 00874 ast_cdr_setvar(cdr, "dnid", S_OR(c->dialed.number.str, ""), 0); 00875 00876 if (c->caller.id.subaddress.valid) { 00877 ast_cdr_setvar(cdr, "callingsubaddr", S_OR(c->caller.id.subaddress.str, ""), 0); 00878 } 00879 if (c->dialed.subaddress.valid) { 00880 ast_cdr_setvar(cdr, "calledsubaddr", S_OR(c->dialed.subaddress.str, ""), 0); 00881 } 00882 }
static int submit_scheduled_batch | ( | const void * | data | ) | [static] |
Definition at line 1301 of file cdr.c.
References ast_cdr_submit_batch(), ast_mutex_lock, ast_mutex_unlock, ast_sched_add(), batchtime, cdr_sched, and cdr_sched_lock.
Referenced by do_reload(), and submit_unscheduled_batch().
01302 { 01303 ast_cdr_submit_batch(0); 01304 /* manually reschedule from this point in time */ 01305 ast_mutex_lock(&cdr_sched_lock); 01306 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); 01307 ast_mutex_unlock(&cdr_sched_lock); 01308 /* returning zero so the scheduler does not automatically reschedule */ 01309 return 0; 01310 }
static void submit_unscheduled_batch | ( | void | ) | [static] |
Do not hold the batch lock while calling this function
Definition at line 1313 of file cdr.c.
References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, ast_sched_add(), AST_SCHED_DEL, cdr_pending_cond, cdr_pending_lock, cdr_sched, cdr_sched_lock, and submit_scheduled_batch().
Referenced by ast_cdr_detach(), and handle_cli_submit().
01314 { 01315 /* Prevent two deletes from happening at the same time */ 01316 ast_mutex_lock(&cdr_sched_lock); 01317 /* this is okay since we are not being called from within the scheduler */ 01318 AST_SCHED_DEL(sched, cdr_sched); 01319 /* schedule the submission to occur ASAP (1 ms) */ 01320 cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL); 01321 ast_mutex_unlock(&cdr_sched_lock); 01322 01323 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */ 01324 ast_mutex_lock(&cdr_pending_lock); 01325 ast_cond_signal(&cdr_pending_cond); 01326 ast_mutex_unlock(&cdr_pending_lock); 01327 }
char ast_default_accountcode[AST_MAX_ACCOUNT_CODE] |
Definition at line 60 of file cdr.c.
Referenced by __ast_channel_alloc_ap().
int ast_default_amaflags = AST_CDR_DOCUMENTATION |
Default AMA flag for billing records (CDR's)
Definition at line 59 of file cdr.c.
Referenced by __ast_channel_alloc_ap(), and ast_bridge_call().
struct ast_cdr_batch * batch [static] |
Referenced by ast_cdr_detach(), ast_cdr_submit_batch(), cdr_engine_shutdown(), handle_cli_status(), init_batch(), and reset_batch().
const int BATCH_SAFE_SHUTDOWN_DEFAULT = 1 [static] |
Definition at line 110 of file cdr.c.
Referenced by do_reload().
const int BATCH_SCHEDULER_ONLY_DEFAULT = 0 [static] |
Definition at line 107 of file cdr.c.
Referenced by do_reload().
const int BATCH_SIZE_DEFAULT = 100 [static] |
Definition at line 101 of file cdr.c.
Referenced by do_reload().
const int BATCH_TIME_DEFAULT = 300 [static] |
Definition at line 104 of file cdr.c.
Referenced by do_reload().
int batchmode [static] |
Definition at line 94 of file cdr.c.
Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().
const int BATCHMODE_DEFAULT = 0 [static] |
Definition at line 95 of file cdr.c.
Referenced by do_reload().
int batchsafeshutdown [static] |
Definition at line 109 of file cdr.c.
Referenced by ast_cdr_engine_term(), do_reload(), and handle_cli_status().
int batchscheduleronly [static] |
Definition at line 106 of file cdr.c.
Referenced by ast_cdr_submit_batch(), do_reload(), and handle_cli_status().
int batchsize [static] |
Definition at line 100 of file cdr.c.
Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().
int batchtime [static] |
Definition at line 103 of file cdr.c.
Referenced by do_reload(), handle_cli_status(), and submit_scheduled_batch().
ast_mutex_t cdr_batch_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 114 of file cdr.c.
Referenced by ast_cdr_detach(), ast_cdr_submit_batch(), and do_reload().
ast_cond_t cdr_pending_cond [static] |
Definition at line 118 of file cdr.c.
Referenced by cdr_engine_shutdown(), do_cdr(), do_reload(), and submit_unscheduled_batch().
ast_mutex_t cdr_pending_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 117 of file cdr.c.
Referenced by do_cdr(), and submit_unscheduled_batch().
const char* const cdr_readonly_vars[] [static] |
{ "clid", "src", "dst", "dcontext", "channel", "dstchannel", "lastapp", "lastdata", "start", "answer", "end", "duration", "billsec", "disposition", "amaflags", "accountcode", "uniqueid", "linkedid", "userfield", "sequence", NULL }
Definition at line 336 of file cdr.c.
Referenced by ast_cdr_data_add_structure(), ast_cdr_serialize_variables(), and ast_cdr_setvar().
int cdr_sched = -1 [static] |
Definition at line 88 of file cdr.c.
Referenced by do_reload(), handle_cli_status(), submit_scheduled_batch(), and submit_unscheduled_batch().
ast_mutex_t cdr_sched_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 112 of file cdr.c.
Referenced by do_reload(), submit_scheduled_batch(), and submit_unscheduled_batch().
int cdr_sequence = 0 [static] |
Definition at line 83 of file cdr.c.
Referenced by cdr_seq_inc().
pthread_t cdr_thread = AST_PTHREADT_NULL [static] |
Definition at line 89 of file cdr.c.
Referenced by cdr_engine_shutdown(), and do_reload().
struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CDR status") [static] |
Definition at line 1496 of file cdr.c.
Referenced by ast_cdr_engine_init(), and cdr_engine_shutdown().
struct ast_cli_entry cli_submit = AST_CLI_DEFINE(handle_cli_submit, "Posts all pending batched CDR data") [static] |
Definition at line 1495 of file cdr.c.
Referenced by cdr_engine_shutdown(), and do_reload().
int enabled [static] |
Definition at line 91 of file cdr.c.
Referenced by ast_cdr_detach(), check_cdr_enabled(), do_reload(), handle_cli_refresh(), handle_cli_status(), and internal_dnsmgr_lookup().
const int ENABLED_DEFAULT = 1 [static] |
Definition at line 92 of file cdr.c.
Referenced by do_reload().
struct sched_context* sched [static] |
int unanswered [static] |
Definition at line 97 of file cdr.c.
Referenced by ast_cdr_isset_unanswered(), do_reload(), handle_cli_status(), and post_cdr().
const int UNANSWERED_DEFAULT = 0 [static] |
Definition at line 98 of file cdr.c.
Referenced by do_reload().