#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"

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 |
Defines | |
| #define | BATCH_SAFE_SHUTDOWN_DEFAULT 1 |
| #define | BATCH_SCHEDULER_ONLY_DEFAULT 0 |
| #define | BATCH_SIZE_DEFAULT 100 |
| #define | BATCH_TIME_DEFAULT 300 |
Functions | |
| static void | __fini_be_list (void) |
| static void | __init_be_list (void) |
| struct ast_cdr * | ast_cdr_alloc (void) |
| Allocate a CDR record. | |
| int | ast_cdr_amaflags2int (const char *flag) |
| Convert a string to a detail record AMA flag. | |
| void | ast_cdr_answer (struct ast_cdr *cdr) |
| Answer a call. | |
| struct ast_cdr * | ast_cdr_append (struct ast_cdr *cdr, struct ast_cdr *newcdr) |
| int | ast_cdr_appenduserfield (struct ast_channel *chan, const char *userfield) |
| Append to CDR user field for channel (stored in CDR). | |
| void | ast_cdr_busy (struct ast_cdr *cdr) |
| Busy a call. | |
| int | ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr) |
| void | ast_cdr_detach (struct ast_cdr *cdr) |
| Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other records during batch mode operation. | |
| void | ast_cdr_discard (struct ast_cdr *cdr) |
| 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. | |
| 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 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 *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) |
| 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) |
| int | check_cdr_enabled () |
| 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 int | 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 int | batchmode |
| static int | batchsafeshutdown |
| static int | batchscheduleronly |
| static int | batchsize |
| static int | batchtime |
| static ast_mutex_t | cdr_batch_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| static ast_cond_t | cdr_pending_cond |
| static ast_mutex_t | cdr_pending_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| static const char *const | cdr_readonly_vars [] |
| static int | cdr_sched = -1 |
| 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 struct sched_context * | sched |
| static int | unanswered |
We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip through our fingers somehow. If someone allocates a CDR, it must be completely handled normally or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR isn't properly generated and posted.
Definition in file cdr.c.
| #define BATCH_SAFE_SHUTDOWN_DEFAULT 1 |
| #define BATCH_SCHEDULER_ONLY_DEFAULT 0 |
| #define BATCH_SIZE_DEFAULT 100 |
| #define BATCH_TIME_DEFAULT 300 |
| 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 456 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().
00457 { 00458 struct ast_cdr *x; 00459 x = ast_calloc(1, sizeof(*x)); 00460 if (!x) 00461 ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n"); 00462 return x; 00463 }
| 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 1060 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().
01061 { 01062 if (!strcasecmp(flag, "default")) 01063 return 0; 01064 if (!strcasecmp(flag, "omit")) 01065 return AST_CDR_OMIT; 01066 if (!strcasecmp(flag, "billing")) 01067 return AST_CDR_BILLING; 01068 if (!strcasecmp(flag, "documentation")) 01069 return AST_CDR_DOCUMENTATION; 01070 return -1; 01071 }
| 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 694 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_bridge_call(), and ast_raw_answer().
00695 { 00696 00697 for (; cdr; cdr = cdr->next) { 00698 if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 00699 continue; 00700 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00701 continue; 00702 check_post(cdr); 00703 if (cdr->disposition < AST_CDR_ANSWERED) 00704 cdr->disposition = AST_CDR_ANSWERED; 00705 if (ast_tvzero(cdr->answer)) 00706 cdr->answer = ast_tvnow(); 00707 } 00708 }
Definition at line 1173 of file cdr.c.
References ast_cdr::next.
Referenced by ast_cdr_fork(), ast_cdr_merge(), and attempt_transfer().
01174 { 01175 struct ast_cdr *ret; 01176 01177 if (cdr) { 01178 ret = cdr; 01179 01180 while (cdr->next) 01181 cdr = cdr->next; 01182 cdr->next = newcdr; 01183 } else { 01184 ret = newcdr; 01185 } 01186 01187 return ret; 01188 }
| int ast_cdr_appenduserfield | ( | struct ast_channel * | chan, | |
| const char * | userfield | |||
| ) |
Append to CDR user field for channel (stored in CDR).
Definition at line 1024 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().
01025 { 01026 struct ast_cdr *cdr = chan->cdr; 01027 01028 for ( ; cdr ; cdr = cdr->next) { 01029 int len = strlen(cdr->userfield); 01030 01031 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 01032 ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len); 01033 } 01034 01035 return 0; 01036 }
| 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 710 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_cdr_disposition(), handle_cause(), pbx_builtin_busy(), ring_entry(), and wait_for_answer().
00711 { 00712 00713 for (; cdr; cdr = cdr->next) { 00714 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00715 check_post(cdr); 00716 if (cdr->disposition < AST_CDR_BUSY) 00717 cdr->disposition = AST_CDR_BUSY; 00718 } 00719 } 00720 }
Definition at line 340 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_cdr_dup().
00341 { 00342 struct ast_var_t *variables, *newvariable = NULL; 00343 struct varshead *headpa, *headpb; 00344 const char *var, *val; 00345 int x = 0; 00346 00347 if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */ 00348 return 0; 00349 00350 headpa = &from_cdr->varshead; 00351 headpb = &to_cdr->varshead; 00352 00353 AST_LIST_TRAVERSE(headpa,variables,entries) { 00354 if (variables && 00355 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00356 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00357 newvariable = ast_var_assign(var, val); 00358 AST_LIST_INSERT_HEAD(headpb, newvariable, entries); 00359 x++; 00360 } 00361 } 00362 00363 return x; 00364 }
| 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 1278 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().
01279 { 01280 struct ast_cdr_batch_item *newtail; 01281 int curr; 01282 01283 if (!cdr) 01284 return; 01285 01286 /* maybe they disabled CDR stuff completely, so just drop it */ 01287 if (!enabled) { 01288 ast_debug(1, "Dropping CDR !\n"); 01289 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01290 ast_cdr_free(cdr); 01291 return; 01292 } 01293 01294 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */ 01295 if (!batchmode) { 01296 post_cdr(cdr); 01297 ast_cdr_free(cdr); 01298 return; 01299 } 01300 01301 /* otherwise, each CDR gets put into a batch list (at the end) */ 01302 ast_debug(1, "CDR detaching from this thread\n"); 01303 01304 /* we'll need a new tail for every CDR */ 01305 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) { 01306 post_cdr(cdr); 01307 ast_cdr_free(cdr); 01308 return; 01309 } 01310 01311 /* don't traverse a whole list (just keep track of the tail) */ 01312 ast_mutex_lock(&cdr_batch_lock); 01313 if (!batch) 01314 init_batch(); 01315 if (!batch->head) { 01316 /* new batch is empty, so point the head at the new tail */ 01317 batch->head = newtail; 01318 } else { 01319 /* already got a batch with something in it, so just append a new tail */ 01320 batch->tail->next = newtail; 01321 } 01322 newtail->cdr = cdr; 01323 batch->tail = newtail; 01324 curr = batch->size++; 01325 ast_mutex_unlock(&cdr_batch_lock); 01326 01327 /* if we have enough stuff to post, then do it */ 01328 if (curr >= (batchsize - 1)) 01329 submit_unscheduled_batch(); 01330 }
| 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 445 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().
00446 { 00447 while (cdr) { 00448 struct ast_cdr *next = cdr->next; 00449 00450 ast_cdr_free_vars(cdr, 0); 00451 ast_free(cdr); 00452 cdr = next; 00453 } 00454 }
| 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 914 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().
00915 { 00916 switch (disposition) { 00917 case AST_CDR_NULL: 00918 return "NO ANSWER"; /* by default, for backward compatibility */ 00919 case AST_CDR_NOANSWER: 00920 return "NO ANSWER"; 00921 case AST_CDR_FAILED: 00922 return "FAILED"; 00923 case AST_CDR_BUSY: 00924 return "BUSY"; 00925 case AST_CDR_ANSWERED: 00926 return "ANSWERED"; 00927 } 00928 return "UNKNOWN"; 00929 }
| 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 753 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().
00754 { 00755 int res = 0; 00756 00757 for (; cdr; cdr = cdr->next) { 00758 switch (cause) { /* handle all the non failure, busy cases, return 0 not to set disposition, 00759 return -1 to set disposition to FAILED */ 00760 case AST_CAUSE_BUSY: 00761 ast_cdr_busy(cdr); 00762 break; 00763 case AST_CAUSE_NO_ANSWER: 00764 ast_cdr_noanswer(cdr); 00765 break; 00766 case AST_CAUSE_NORMAL: 00767 break; 00768 default: 00769 res = -1; 00770 } 00771 } 00772 return res; 00773 }
Duplicate a record.
Duplicate a CDR record
Definition at line 171 of file cdr.c.
References ast_cdr_alloc(), ast_cdr_copy_vars(), ast_cdr::next, and ast_cdr::varshead.
Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_merge(), ast_cdr_reset(), custom_log(), manager_log(), sqlite3_log(), and syslog_log().
00172 { 00173 struct ast_cdr *newcdr; 00174 00175 if (!cdr) /* don't die if we get a null cdr pointer */ 00176 return NULL; 00177 newcdr = ast_cdr_alloc(); 00178 if (!newcdr) 00179 return NULL; 00180 00181 memcpy(newcdr, cdr, sizeof(*newcdr)); 00182 /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */ 00183 memset(&newcdr->varshead, 0, sizeof(newcdr->varshead)); 00184 ast_cdr_copy_vars(newcdr, cdr); 00185 newcdr->next = NULL; 00186 00187 return newcdr; 00188 }
| 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 888 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().
00889 { 00890 for ( ; cdr ; cdr = cdr->next) { 00891 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00892 continue; 00893 check_post(cdr); 00894 if (ast_tvzero(cdr->end)) 00895 cdr->end = ast_tvnow(); 00896 if (ast_tvzero(cdr->start)) { 00897 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>")); 00898 cdr->disposition = AST_CDR_FAILED; 00899 } else 00900 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec; 00901 if (ast_tvzero(cdr->answer)) { 00902 if (cdr->disposition == AST_CDR_ANSWERED) { 00903 ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>")); 00904 cdr->disposition = AST_CDR_FAILED; 00905 } 00906 } else { 00907 cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec; 00908 if (ast_test_flag(&ast_options, AST_OPT_FLAG_INITIATED_SECONDS)) 00909 cdr->billsec += cdr->end.tv_usec > cdr->answer.tv_usec ? 1 : 0; 00910 } 00911 } 00912 }
| int ast_cdr_engine_init | ( | void | ) |
Load the configuration file cdr.conf and possibly start the CDR scheduling thread.
Definition at line 1566 of file cdr.c.
References ast_cli_register(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cdr_batch_lock, cli_status, do_reload(), init_batch(), LOG_ERROR, and sched_context_create().
Referenced by main().
01567 { 01568 int res; 01569 01570 sched = sched_context_create(); 01571 if (!sched) { 01572 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 01573 return -1; 01574 } 01575 01576 ast_cli_register(&cli_status); 01577 01578 res = do_reload(0); 01579 if (res) { 01580 ast_mutex_lock(&cdr_batch_lock); 01581 res = init_batch(); 01582 ast_mutex_unlock(&cdr_batch_lock); 01583 } 01584 01585 return res; 01586 }
| int ast_cdr_engine_reload | ( | void | ) |
Reload the configuration file cdr.conf and start/stop CDR scheduling thread.
Definition at line 1595 of file cdr.c.
References do_reload().
01596 { 01597 return do_reload(1); 01598 }
| void ast_cdr_engine_term | ( | void | ) |
Submit any remaining CDRs and prepare for shutdown
Definition at line 1590 of file cdr.c.
References ast_cdr_submit_batch(), and batchsafeshutdown.
Referenced by do_reload(), and quit_handler().
01591 { 01592 ast_cdr_submit_batch(batchsafeshutdown); 01593 }
| void ast_cdr_failed | ( | struct ast_cdr * | cdr | ) |
Fail a call.
| cdr | the cdr you wish to associate with the call Marks the channel disposition as "FAILED" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. Returns nothing |
Definition at line 722 of file cdr.c.
References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), clear_caller(), findmeexec(), handle_cause(), and try_calling().
00723 { 00724 for (; cdr; cdr = cdr->next) { 00725 check_post(cdr); 00726 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00727 check_post(cdr); 00728 if (cdr->disposition < AST_CDR_FAILED) 00729 cdr->disposition = AST_CDR_FAILED; 00730 } 00731 } 00732 }
| char* ast_cdr_flags2str | ( | int | flag | ) |
Converts AMA flag to printable string
Definition at line 932 of file cdr.c.
References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
Referenced by _sip_show_peer(), _skinny_show_line(), ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), manager_log(), sip_show_user(), and tds_log().
00933 { 00934 switch (flag) { 00935 case AST_CDR_OMIT: 00936 return "OMIT"; 00937 case AST_CDR_BILLING: 00938 return "BILLING"; 00939 case AST_CDR_DOCUMENTATION: 00940 return "DOCUMENTATION"; 00941 } 00942 return "Unknown"; 00943 }
| void ast_cdr_free | ( | struct ast_cdr * | cdr | ) |
Free a CDR record.
| cdr | ast_cdr structure to free Returns nothing |
Definition at line 432 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().
00433 { 00434 00435 while (cdr) { 00436 struct ast_cdr *next = cdr->next; 00437 00438 ast_cdr_free_vars(cdr, 0); 00439 ast_free(cdr); 00440 cdr = next; 00441 } 00442 }
| void ast_cdr_free_vars | ( | struct ast_cdr * | cdr, | |
| int | recur | |||
| ) |
Definition at line 411 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().
00412 { 00413 00414 /* clear variables */ 00415 for (; cdr; cdr = recur ? cdr->next : NULL) { 00416 struct ast_var_t *vardata; 00417 struct varshead *headp = &cdr->varshead; 00418 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 00419 ast_var_delete(vardata); 00420 } 00421 }
| 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 222 of file cdr.c.
References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_disp2str(), ast_cdr_flags2str(), ast_cdr_getvar_internal(), ast_copy_string(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_cdr::billsec, cdr_get_tv(), ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::linkedid, ast_cdr::peeraccount, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.
Referenced by ast_cdr_serialize_variables(), cdr_handler(), cdr_read(), odbc_log(), and pgsql_log().
00223 { 00224 const char *fmt = "%Y-%m-%d %T"; 00225 const char *varbuf; 00226 00227 if (!cdr) /* don't die if the cdr is null */ 00228 return; 00229 00230 *ret = NULL; 00231 /* special vars (the ones from the struct ast_cdr when requested by name) 00232 I'd almost say we should convert all the stringed vals to vars */ 00233 00234 if (!strcasecmp(name, "clid")) 00235 ast_copy_string(workspace, cdr->clid, workspacelen); 00236 else if (!strcasecmp(name, "src")) 00237 ast_copy_string(workspace, cdr->src, workspacelen); 00238 else if (!strcasecmp(name, "dst")) 00239 ast_copy_string(workspace, cdr->dst, workspacelen); 00240 else if (!strcasecmp(name, "dcontext")) 00241 ast_copy_string(workspace, cdr->dcontext, workspacelen); 00242 else if (!strcasecmp(name, "channel")) 00243 ast_copy_string(workspace, cdr->channel, workspacelen); 00244 else if (!strcasecmp(name, "dstchannel")) 00245 ast_copy_string(workspace, cdr->dstchannel, workspacelen); 00246 else if (!strcasecmp(name, "lastapp")) 00247 ast_copy_string(workspace, cdr->lastapp, workspacelen); 00248 else if (!strcasecmp(name, "lastdata")) 00249 ast_copy_string(workspace, cdr->lastdata, workspacelen); 00250 else if (!strcasecmp(name, "start")) 00251 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen); 00252 else if (!strcasecmp(name, "answer")) 00253 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen); 00254 else if (!strcasecmp(name, "end")) 00255 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen); 00256 else if (!strcasecmp(name, "duration")) 00257 snprintf(workspace, workspacelen, "%ld", cdr->duration ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000); 00258 else if (!strcasecmp(name, "billsec")) 00259 snprintf(workspace, workspacelen, "%ld", cdr->billsec || cdr->answer.tv_sec == 0 ? cdr->billsec : (long)ast_tvdiff_ms(ast_tvnow(), cdr->answer) / 1000); 00260 else if (!strcasecmp(name, "disposition")) { 00261 if (raw) { 00262 snprintf(workspace, workspacelen, "%ld", cdr->disposition); 00263 } else { 00264 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); 00265 } 00266 } else if (!strcasecmp(name, "amaflags")) { 00267 if (raw) { 00268 snprintf(workspace, workspacelen, "%ld", cdr->amaflags); 00269 } else { 00270 ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); 00271 } 00272 } else if (!strcasecmp(name, "accountcode")) 00273 ast_copy_string(workspace, cdr->accountcode, workspacelen); 00274 else if (!strcasecmp(name, "peeraccount")) 00275 ast_copy_string(workspace, cdr->peeraccount, workspacelen); 00276 else if (!strcasecmp(name, "uniqueid")) 00277 ast_copy_string(workspace, cdr->uniqueid, workspacelen); 00278 else if (!strcasecmp(name, "linkedid")) 00279 ast_copy_string(workspace, cdr->linkedid, workspacelen); 00280 else if (!strcasecmp(name, "userfield")) 00281 ast_copy_string(workspace, cdr->userfield, workspacelen); 00282 else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) 00283 ast_copy_string(workspace, varbuf, workspacelen); 00284 else 00285 workspace[0] = '\0'; 00286 00287 if (!ast_strlen_zero(workspace)) 00288 *ret = workspace; 00289 }
| static const char* ast_cdr_getvar_internal | ( | struct ast_cdr * | cdr, | |
| const char * | name, | |||
| int | recur | |||
| ) | [static] |
Definition at line 190 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().
00191 { 00192 if (ast_strlen_zero(name)) 00193 return NULL; 00194 00195 for (; cdr; cdr = recur ? cdr->next : NULL) { 00196 struct ast_var_t *variables; 00197 struct varshead *headp = &cdr->varshead; 00198 AST_LIST_TRAVERSE(headp, variables, entries) { 00199 if (!strcasecmp(name, ast_var_name(variables))) 00200 return ast_var_value(variables); 00201 } 00202 } 00203 00204 return NULL; 00205 }
| 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 850 of file cdr.c.
References ast_channel::_state, ast_channel::accountcode, ast_cdr::accountcode, ast_channel::amaflags, ast_cdr::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_copy_string(), AST_STATE_UP, ast_test_flag, chan, ast_cdr::channel, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, ast_channel::linkedid, ast_cdr::linkedid, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::name, ast_cdr::next, ast_channel::peeraccount, ast_cdr::peeraccount, S_OR, set_one_cid(), ast_channel::uniqueid, and ast_cdr::uniqueid.
Referenced by __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().
00851 { 00852 char *chan; 00853 00854 for ( ; cdr ; cdr = cdr->next) { 00855 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00856 chan = S_OR(cdr->channel, "<unknown>"); 00857 ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); 00858 set_one_cid(cdr, c); 00859 00860 cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 00861 cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; 00862 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00863 ast_copy_string(cdr->peeraccount, c->peeraccount, sizeof(cdr->peeraccount)); 00864 /* Destination information */ 00865 ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst)); 00866 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext)); 00867 /* Unique call identifier */ 00868 ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid)); 00869 /* Linked call identifier */ 00870 ast_copy_string(cdr->linkedid, c->linkedid, sizeof(cdr->linkedid)); 00871 } 00872 } 00873 return 0; 00874 }
| int ast_cdr_isset_unanswered | ( | void | ) |
Definition at line 163 of file cdr.c.
References unanswered.
Referenced by ring_entry(), and try_calling().
00164 { 00165 return unanswered; 00166 }
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 500 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.
00501 { 00502 struct ast_cdr *zcdr; 00503 struct ast_cdr *lto = NULL; 00504 struct ast_cdr *lfrom = NULL; 00505 int discard_from = 0; 00506 00507 if (!to || !from) 00508 return; 00509 00510 /* don't merge into locked CDR's -- it's bad business */ 00511 if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { 00512 zcdr = to; /* safety valve? */ 00513 while (to->next) { 00514 lto = to; 00515 to = to->next; 00516 } 00517 00518 if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { 00519 ast_log(LOG_WARNING, "Merging into locked CDR... no choice."); 00520 to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */ 00521 lto = NULL; 00522 } 00523 } 00524 00525 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) { 00526 struct ast_cdr *llfrom = NULL; 00527 discard_from = 1; 00528 if (lto) { 00529 /* insert the from stuff after lto */ 00530 lto->next = from; 00531 lfrom = from; 00532 while (lfrom && lfrom->next) { 00533 if (!lfrom->next->next) 00534 llfrom = lfrom; 00535 lfrom = lfrom->next; 00536 } 00537 /* rip off the last entry and put a copy of the to at the end */ 00538 llfrom->next = to; 00539 from = lfrom; 00540 } else { 00541 /* save copy of the current *to cdr */ 00542 struct ast_cdr tcdr; 00543 memcpy(&tcdr, to, sizeof(tcdr)); 00544 /* copy in the locked from cdr */ 00545 memcpy(to, from, sizeof(*to)); 00546 lfrom = from; 00547 while (lfrom && lfrom->next) { 00548 if (!lfrom->next->next) 00549 llfrom = lfrom; 00550 lfrom = lfrom->next; 00551 } 00552 from->next = NULL; 00553 /* rip off the last entry and put a copy of the to at the end */ 00554 if (llfrom == from) 00555 to = to->next = ast_cdr_dup(&tcdr); 00556 else 00557 to = llfrom->next = ast_cdr_dup(&tcdr); 00558 from = lfrom; 00559 } 00560 } 00561 00562 if (!ast_tvzero(from->start)) { 00563 if (!ast_tvzero(to->start)) { 00564 if (ast_tvcmp(to->start, from->start) > 0 ) { 00565 to->start = from->start; /* use the earliest time */ 00566 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00567 } 00568 /* else nothing to do */ 00569 } else { 00570 to->start = from->start; 00571 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00572 } 00573 } 00574 if (!ast_tvzero(from->answer)) { 00575 if (!ast_tvzero(to->answer)) { 00576 if (ast_tvcmp(to->answer, from->answer) > 0 ) { 00577 to->answer = from->answer; /* use the earliest time */ 00578 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00579 } 00580 /* we got the earliest answer time, so we'll settle for that? */ 00581 } else { 00582 to->answer = from->answer; 00583 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00584 } 00585 } 00586 if (!ast_tvzero(from->end)) { 00587 if (!ast_tvzero(to->end)) { 00588 if (ast_tvcmp(to->end, from->end) < 0 ) { 00589 to->end = from->end; /* use the latest time */ 00590 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00591 to->duration = to->end.tv_sec - to->start.tv_sec; /* don't forget to update the duration, billsec, when we set end */ 00592 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00593 } 00594 /* else, nothing to do */ 00595 } else { 00596 to->end = from->end; 00597 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00598 to->duration = to->end.tv_sec - to->start.tv_sec; 00599 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00600 } 00601 } 00602 if (to->disposition < from->disposition) { 00603 to->disposition = from->disposition; 00604 from->disposition = AST_CDR_NOANSWER; 00605 } 00606 if (ast_strlen_zero(to->lastapp) && !ast_strlen_zero(from->lastapp)) { 00607 ast_copy_string(to->lastapp, from->lastapp, sizeof(to->lastapp)); 00608 from->lastapp[0] = 0; /* theft */ 00609 } 00610 if (ast_strlen_zero(to->lastdata) && !ast_strlen_zero(from->lastdata)) { 00611 ast_copy_string(to->lastdata, from->lastdata, sizeof(to->lastdata)); 00612 from->lastdata[0] = 0; /* theft */ 00613 } 00614 if (ast_strlen_zero(to->dcontext) && !ast_strlen_zero(from->dcontext)) { 00615 ast_copy_string(to->dcontext, from->dcontext, sizeof(to->dcontext)); 00616 from->dcontext[0] = 0; /* theft */ 00617 } 00618 if (ast_strlen_zero(to->dstchannel) && !ast_strlen_zero(from->dstchannel)) { 00619 ast_copy_string(to->dstchannel, from->dstchannel, sizeof(to->dstchannel)); 00620 from->dstchannel[0] = 0; /* theft */ 00621 } 00622 if (!ast_strlen_zero(from->channel) && (ast_strlen_zero(to->channel) || !strncasecmp(from->channel, "Agent/", 6))) { 00623 ast_copy_string(to->channel, from->channel, sizeof(to->channel)); 00624 from->channel[0] = 0; /* theft */ 00625 } 00626 if (ast_strlen_zero(to->src) && !ast_strlen_zero(from->src)) { 00627 ast_copy_string(to->src, from->src, sizeof(to->src)); 00628 from->src[0] = 0; /* theft */ 00629 } 00630 if (ast_strlen_zero(to->clid) && !ast_strlen_zero(from->clid)) { 00631 ast_copy_string(to->clid, from->clid, sizeof(to->clid)); 00632 from->clid[0] = 0; /* theft */ 00633 } 00634 if (ast_strlen_zero(to->dst) && !ast_strlen_zero(from->dst)) { 00635 ast_copy_string(to->dst, from->dst, sizeof(to->dst)); 00636 from->dst[0] = 0; /* theft */ 00637 } 00638 if (!to->amaflags) 00639 to->amaflags = AST_CDR_DOCUMENTATION; 00640 if (!from->amaflags) 00641 from->amaflags = AST_CDR_DOCUMENTATION; /* make sure both amaflags are set to something (DOC is default) */ 00642 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) { 00643 to->amaflags = from->amaflags; 00644 } 00645 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) { 00646 ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode)); 00647 } 00648 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->peeraccount) && !ast_strlen_zero(from->peeraccount))) { 00649 ast_copy_string(to->peeraccount, from->peeraccount, sizeof(to->peeraccount)); 00650 } 00651 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) { 00652 ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield)); 00653 } 00654 /* flags, varsead, ? */ 00655 cdr_merge_vars(from, to); 00656 00657 if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS)) 00658 ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS); 00659 if (ast_test_flag(from, AST_CDR_FLAG_POSTED)) 00660 ast_set_flag(to, AST_CDR_FLAG_POSTED); 00661 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) 00662 ast_set_flag(to, AST_CDR_FLAG_LOCKED); 00663 if (ast_test_flag(from, AST_CDR_FLAG_CHILD)) 00664 ast_set_flag(to, AST_CDR_FLAG_CHILD); 00665 if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED)) 00666 ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED); 00667 00668 /* last, but not least, we need to merge any forked CDRs to the 'to' cdr */ 00669 while (from->next) { 00670 /* just rip 'em off the 'from' and insert them on the 'to' */ 00671 zcdr = from->next; 00672 from->next = zcdr->next; 00673 zcdr->next = NULL; 00674 /* zcdr is now ripped from the current list; */ 00675 ast_cdr_append(to, zcdr); 00676 } 00677 if (discard_from) 00678 ast_cdr_discard(from); 00679 }
| void ast_cdr_noanswer | ( | struct ast_cdr * | cdr | ) |
A call wasn't answered.
| cdr | the cdr you wish to associate with the call Marks the channel disposition as "NO ANSWER" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. |
Definition at line 734 of file cdr.c.
References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, AST_CDR_NOANSWER, ast_log(), ast_strlen_zero(), ast_test_flag, chan, ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::next.
Referenced by ast_cdr_disposition(), handle_cause(), queue_exec(), try_calling(), and wait_for_answer().
00735 { 00736 char *chan; 00737 00738 while (cdr) { 00739 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00740 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00741 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00742 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00743 if (cdr->disposition < AST_CDR_NOANSWER) 00744 cdr->disposition = AST_CDR_NOANSWER; 00745 } 00746 cdr = cdr->next; 00747 } 00748 }
| int ast_cdr_register | ( | const char * | name, | |
| const char * | desc, | |||
| ast_cdrbe | be | |||
| ) |
Register a CDR handling engine.
Register a CDR driver. Each registered CDR driver generates a CDR
Definition at line 108 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 config_module(), load_config(), load_module(), odbc_load_module(), and unload_module().
00109 { 00110 struct ast_cdr_beitem *i = NULL; 00111 00112 if (!name) 00113 return -1; 00114 00115 if (!be) { 00116 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name); 00117 return -1; 00118 } 00119 00120 AST_RWLIST_WRLOCK(&be_list); 00121 AST_RWLIST_TRAVERSE(&be_list, i, list) { 00122 if (!strcasecmp(name, i->name)) { 00123 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name); 00124 AST_RWLIST_UNLOCK(&be_list); 00125 return -1; 00126 } 00127 } 00128 00129 if (!(i = ast_calloc(1, sizeof(*i)))) 00130 return -1; 00131 00132 i->be = be; 00133 ast_copy_string(i->name, name, sizeof(i->name)); 00134 ast_copy_string(i->desc, desc, sizeof(i->desc)); 00135 00136 AST_RWLIST_INSERT_HEAD(&be_list, i, list); 00137 AST_RWLIST_UNLOCK(&be_list); 00138 00139 return 0; 00140 }
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 1106 of file cdr.c.
References ast_cdr::answer, ast_cdr_detach(), ast_cdr_dup(), ast_cdr_end(), AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POST_ENABLE, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), AST_CDR_NOANSWER, ast_cdr_start(), ast_clear_flag, ast_copy_flags, AST_FLAGS_ALL, ast_set_flag, ast_test_flag, ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, ast_cdr::next, and ast_cdr::start.
Referenced by ast_cdr_fork(), dial_exec_full(), disa_exec(), and pbx_builtin_resetcdr().
01107 { 01108 struct ast_cdr *duplicate; 01109 struct ast_flags flags = { 0 }; 01110 01111 if (_flags) 01112 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); 01113 01114 for ( ; cdr ; cdr = cdr->next) { 01115 /* Detach if post is requested */ 01116 if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01117 if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) { 01118 ast_cdr_end(cdr); 01119 if ((duplicate = ast_cdr_dup(cdr))) { 01120 ast_cdr_detach(duplicate); 01121 } 01122 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 01123 } 01124 01125 /* enable CDR only */ 01126 if (ast_test_flag(&flags, AST_CDR_FLAG_POST_ENABLE)) { 01127 ast_clear_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01128 continue; 01129 } 01130 01131 /* clear variables */ 01132 if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) { 01133 ast_cdr_free_vars(cdr, 0); 01134 } 01135 01136 /* Reset to initial state */ 01137 ast_clear_flag(cdr, AST_FLAGS_ALL); 01138 memset(&cdr->start, 0, sizeof(cdr->start)); 01139 memset(&cdr->end, 0, sizeof(cdr->end)); 01140 memset(&cdr->answer, 0, sizeof(cdr->answer)); 01141 cdr->billsec = 0; 01142 cdr->duration = 0; 01143 ast_cdr_start(cdr); 01144 cdr->disposition = AST_CDR_NOANSWER; 01145 } 01146 } 01147 }
| int ast_cdr_serialize_variables | ( | struct ast_cdr * | cdr, | |
| struct ast_str ** | buf, | |||
| char | delim, | |||
| char | sep, | |||
| int | recur | |||
| ) |
Definition at line 366 of file cdr.c.
References ast_cdr_getvar(), AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_strlen_zero(), ast_var_name(), ast_var_value(), cdr_readonly_vars, ast_var_t::entries, LOG_ERROR, ast_cdr::next, total, var, and ast_cdr::varshead.
Referenced by handle_showchan().
00367 { 00368 struct ast_var_t *variables; 00369 const char *var, *val; 00370 char *tmp; 00371 char workspace[256]; 00372 int total = 0, x = 0, i; 00373 00374 ast_str_reset(*buf); 00375 00376 for (; cdr; cdr = recur ? cdr->next : NULL) { 00377 if (++x > 1) 00378 ast_str_append(buf, 0, "\n"); 00379 00380 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) { 00381 if (variables && 00382 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00383 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00384 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, val, sep) < 0) { 00385 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00386 break; 00387 } else 00388 total++; 00389 } else 00390 break; 00391 } 00392 00393 for (i = 0; cdr_readonly_vars[i]; i++) { 00394 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 */ 00395 ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0); 00396 if (!tmp) 00397 continue; 00398 00399 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep) < 0) { 00400 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00401 break; 00402 } else 00403 total++; 00404 } 00405 } 00406 00407 return total; 00408 }
| int ast_cdr_setaccount | ( | struct ast_channel * | chan, | |
| const char * | account | |||
| ) |
Set account code, will generate AMI event.
Definition at line 945 of file cdr.c.
References ast_cdr::accountcode, accountcode, ast_channel::accountcode, AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, EVENT_FLAG_CALL, manager_event, ast_channel::name, ast_cdr::next, and ast_channel::uniqueid.
Referenced by __ast_request_and_dial(), ast_call_forward(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), auth_exec(), cdr_write(), and rpt_call().
00946 { 00947 struct ast_cdr *cdr = chan->cdr; 00948 const char *old_acct = ""; 00949 00950 if (!ast_strlen_zero(chan->accountcode)) { 00951 old_acct = ast_strdupa(chan->accountcode); 00952 } 00953 00954 ast_string_field_set(chan, accountcode, account); 00955 for ( ; cdr ; cdr = cdr->next) { 00956 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00957 ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode)); 00958 } 00959 } 00960 00961 manager_event(EVENT_FLAG_CALL, "NewAccountCode", 00962 "Channel: %s\r\n" 00963 "Uniqueid: %s\r\n" 00964 "AccountCode: %s\r\n" 00965 "OldAccountCode: %s\r\n", 00966 chan->name, chan->uniqueid, chan->accountcode, old_acct); 00967 00968 return 0; 00969 }
| int ast_cdr_setamaflags | ( | struct ast_channel * | chan, | |
| const char * | flag | |||
| ) |
Set AMA flags for channel.
Definition at line 997 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().
00998 { 00999 struct ast_cdr *cdr; 01000 int newflag = ast_cdr_amaflags2int(flag); 01001 if (newflag) { 01002 for (cdr = chan->cdr; cdr; cdr = cdr->next) { 01003 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01004 cdr->amaflags = newflag; 01005 } 01006 } 01007 } 01008 01009 return 0; 01010 }
| 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 797 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.
00798 { 00799 00800 for (; cdr; cdr = cdr->next) { 00801 if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 00802 continue; 00803 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00804 continue; 00805 check_post(cdr); 00806 cdr->answer = t; 00807 } 00808 }
| 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 785 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().
00786 { 00787 00788 for (; cdr; cdr = cdr->next) { 00789 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00790 check_post(cdr); 00791 ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp)); 00792 ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata)); 00793 } 00794 } 00795 }
| 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 841 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_cdr::next, and set_one_cid().
Referenced by ast_bridge_call(), and callerid_write().
00842 { 00843 for (; cdr; cdr = cdr->next) { 00844 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00845 set_one_cid(cdr, c); 00846 } 00847 return 0; 00848 }
| 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 775 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, check_post(), ast_cdr::dstchannel, and ast_cdr::next.
Referenced by dial_exec_full(), park_exec_full(), ring_entry(), and try_calling().
00776 { 00777 for (; cdr; cdr = cdr->next) { 00778 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00779 check_post(cdr); 00780 ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel)); 00781 } 00782 } 00783 }
| 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 810 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
00811 { 00812 00813 for (; cdr; cdr = cdr->next) { 00814 if (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00815 continue; 00816 check_post(cdr); 00817 cdr->disposition = disposition; 00818 } 00819 }
| int ast_cdr_setpeeraccount | ( | struct ast_channel * | chan, | |
| const char * | account | |||
| ) |
Set the peer account.
Definition at line 971 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, EVENT_FLAG_CALL, manager_event, ast_channel::name, ast_cdr::next, ast_cdr::peeraccount, ast_channel::peeraccount, and ast_channel::uniqueid.
Referenced by cdr_write().
00972 { 00973 struct ast_cdr *cdr = chan->cdr; 00974 const char *old_acct = ""; 00975 00976 if (!ast_strlen_zero(chan->peeraccount)) { 00977 old_acct = ast_strdupa(chan->peeraccount); 00978 } 00979 00980 ast_string_field_set(chan, peeraccount, account); 00981 for ( ; cdr ; cdr = cdr->next) { 00982 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00983 ast_copy_string(cdr->peeraccount, chan->peeraccount, sizeof(cdr->peeraccount)); 00984 } 00985 } 00986 00987 manager_event(EVENT_FLAG_CALL, "NewPeerAccount", 00988 "Channel: %s\r\n" 00989 "Uniqueid: %s\r\n" 00990 "PeerAccount: %s\r\n" 00991 "OldPeerAccount: %s\r\n", 00992 chan->name, chan->uniqueid, chan->peeraccount, old_acct); 00993 00994 return 0; 00995 }
| int ast_cdr_setuserfield | ( | struct ast_channel * | chan, | |
| const char * | userfield | |||
| ) |
Set CDR user field for channel (stored in CDR).
Definition at line 1012 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().
01013 { 01014 struct ast_cdr *cdr = chan->cdr; 01015 01016 for ( ; cdr ; cdr = cdr->next) { 01017 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 01018 ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield)); 01019 } 01020 01021 return 0; 01022 }
| int ast_cdr_setvar | ( | struct ast_cdr * | cdr, | |
| const char * | name, | |||
| const char * | value, | |||
| int | recur | |||
| ) |
Set a CDR channel variable
Definition at line 299 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(), and cdr_write().
00300 { 00301 struct ast_var_t *newvariable; 00302 struct varshead *headp; 00303 int x; 00304 00305 for (x = 0; cdr_readonly_vars[x]; x++) { 00306 if (!strcasecmp(name, cdr_readonly_vars[x])) { 00307 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name); 00308 return -1; 00309 } 00310 } 00311 00312 if (!cdr) { 00313 ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n"); 00314 return -1; 00315 } 00316 00317 for (; cdr; cdr = recur ? cdr->next : NULL) { 00318 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00319 continue; 00320 headp = &cdr->varshead; 00321 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 00322 if (!strcasecmp(ast_var_name(newvariable), name)) { 00323 /* there is already such a variable, delete it */ 00324 AST_LIST_REMOVE_CURRENT(entries); 00325 ast_var_delete(newvariable); 00326 break; 00327 } 00328 } 00329 AST_LIST_TRAVERSE_SAFE_END; 00330 00331 if (value) { 00332 newvariable = ast_var_assign(name, value); 00333 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 00334 } 00335 } 00336 00337 return 0; 00338 }
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 1149 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().
01150 { 01151 struct ast_flags flags = { 0 }; 01152 01153 if (_flags) 01154 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); 01155 01156 /* Reset to initial state */ 01157 if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) { /* But do NOT lose the NoCDR() setting */ 01158 ast_clear_flag(cdr, AST_FLAGS_ALL); 01159 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01160 } else { 01161 ast_clear_flag(cdr, AST_FLAGS_ALL); 01162 } 01163 01164 memset(&cdr->start, 0, sizeof(cdr->start)); 01165 memset(&cdr->end, 0, sizeof(cdr->end)); 01166 memset(&cdr->answer, 0, sizeof(cdr->answer)); 01167 cdr->billsec = 0; 01168 cdr->duration = 0; 01169 ast_cdr_start(cdr); 01170 cdr->disposition = AST_CDR_NULL; 01171 }
| 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 681 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_tvnow(), chan, ast_cdr::channel, check_post(), ast_cdr::next, S_OR, and ast_cdr::start.
Referenced by __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_reset(), ast_cdr_specialized_reset(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().
00682 { 00683 char *chan; 00684 00685 for (; cdr; cdr = cdr->next) { 00686 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00687 chan = S_OR(cdr->channel, "<unknown>"); 00688 check_post(cdr); 00689 cdr->start = ast_tvnow(); 00690 } 00691 } 00692 }
| 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 1227 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().
01228 { 01229 struct ast_cdr_batch_item *oldbatchitems = NULL; 01230 pthread_t batch_post_thread = AST_PTHREADT_NULL; 01231 01232 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */ 01233 if (!batch || !batch->head) 01234 return; 01235 01236 /* move the old CDRs aside, and prepare a new CDR batch */ 01237 ast_mutex_lock(&cdr_batch_lock); 01238 oldbatchitems = batch->head; 01239 reset_batch(); 01240 ast_mutex_unlock(&cdr_batch_lock); 01241 01242 /* if configured, spawn a new thread to post these CDRs, 01243 also try to save as much as possible if we are shutting down safely */ 01244 if (batchscheduleronly || do_shutdown) { 01245 ast_debug(1, "CDR single-threaded batch processing begins now\n"); 01246 do_batch_backend_process(oldbatchitems); 01247 } else { 01248 if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) { 01249 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n"); 01250 do_batch_backend_process(oldbatchitems); 01251 } else { 01252 ast_debug(1, "CDR multi-threaded batch processing begins now\n"); 01253 } 01254 } 01255 }
| void ast_cdr_unregister | ( | const char * | name | ) |
Unregister a CDR handling engine.
unregister a CDR driver
Definition at line 143 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(), reload(), tds_unload_module(), and unload_module().
00144 { 00145 struct ast_cdr_beitem *i = NULL; 00146 00147 AST_RWLIST_WRLOCK(&be_list); 00148 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { 00149 if (!strcasecmp(name, i->name)) { 00150 AST_RWLIST_REMOVE_CURRENT(list); 00151 break; 00152 } 00153 } 00154 AST_RWLIST_TRAVERSE_SAFE_END; 00155 AST_RWLIST_UNLOCK(&be_list); 00156 00157 if (i) { 00158 ast_verb(2, "Unregistered '%s' CDR backend\n", name); 00159 ast_free(i); 00160 } 00161 }
| int ast_cdr_update | ( | struct ast_channel * | chan | ) |
Update CDR on a channel
Definition at line 1038 of file cdr.c.
References ast_channel::accountcode, ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, ast_channel::cdr, ast_channel::context, ast_cdr::dcontext, ast_cdr::dst, ast_channel::exten, ast_channel::linkedid, ast_cdr::linkedid, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, ast_channel::peeraccount, 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().
01039 { 01040 struct ast_cdr *cdr = c->cdr; 01041 01042 for ( ; cdr ; cdr = cdr->next) { 01043 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01044 set_one_cid(cdr, c); 01045 01046 /* Copy account code et-al */ 01047 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 01048 ast_copy_string(cdr->peeraccount, c->peeraccount, sizeof(cdr->peeraccount)); 01049 ast_copy_string(cdr->linkedid, c->linkedid, sizeof(cdr->linkedid)); 01050 01051 /* Destination information */ /* XXX privilege macro* ? */ 01052 ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst)); 01053 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext)); 01054 } 01055 } 01056 01057 return 0; 01058 }
| static void cdr_get_tv | ( | struct timeval | when, | |
| const char * | fmt, | |||
| char * | buf, | |||
| int | bufsize | |||
| ) | [static] |
Definition at line 207 of file cdr.c.
References ast_localtime(), and ast_strftime().
Referenced by ast_cdr_getvar().
00208 { 00209 if (fmt == NULL) { /* raw mode */ 00210 snprintf(buf, bufsize, "%ld.%06ld", (long)when.tv_sec, (long)when.tv_usec); 00211 } else { 00212 if (when.tv_sec) { 00213 struct ast_tm tm; 00214 00215 ast_localtime(&when, &tm, NULL); 00216 ast_strftime(buf, bufsize, fmt, &tm); 00217 } 00218 } 00219 }
Definition at line 465 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().
00466 { 00467 struct ast_var_t *variablesfrom,*variablesto; 00468 struct varshead *headpfrom = &to->varshead; 00469 struct varshead *headpto = &from->varshead; 00470 AST_LIST_TRAVERSE_SAFE_BEGIN(headpfrom, variablesfrom, entries) { 00471 /* for every var in from, stick it in to */ 00472 const char *fromvarname, *fromvarval; 00473 const char *tovarname = NULL, *tovarval = NULL; 00474 fromvarname = ast_var_name(variablesfrom); 00475 fromvarval = ast_var_value(variablesfrom); 00476 tovarname = 0; 00477 00478 /* now, quick see if that var is in the 'to' cdr already */ 00479 AST_LIST_TRAVERSE(headpto, variablesto, entries) { 00480 00481 /* now, quick see if that var is in the 'to' cdr already */ 00482 if ( strcasecmp(fromvarname, ast_var_name(variablesto)) == 0 ) { 00483 tovarname = ast_var_name(variablesto); 00484 tovarval = ast_var_value(variablesto); 00485 break; 00486 } 00487 } 00488 if (tovarname && strcasecmp(fromvarval,tovarval) != 0) { /* this message here to see how irritating the userbase finds it */ 00489 ast_log(LOG_NOTICE, "Merging CDR's: variable %s value %s dropped in favor of value %s\n", tovarname, fromvarval, tovarval); 00490 continue; 00491 } else if (tovarname && strcasecmp(fromvarval,tovarval) == 0) /* if they are the same, the job is done */ 00492 continue; 00493 00494 /* rip this var out of the from cdr, and stick it in the to cdr */ 00495 AST_LIST_MOVE_CURRENT(headpto, entries); 00496 } 00497 AST_LIST_TRAVERSE_SAFE_END; 00498 }
| int check_cdr_enabled | ( | void | ) |
Return TRUE if CDR subsystem is enabled.
Definition at line 100 of file cdr.c.
References enabled.
Referenced by action_coresettings(), and handle_show_settings().
00101 { 00102 return enabled; 00103 }
| static void check_post | ( | struct ast_cdr * | cdr | ) | [static] |
print a warning if cdr already posted
Definition at line 424 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_setanswer(), ast_cdr_setapp(), ast_cdr_setdestchan(), ast_cdr_setdisposition(), ast_cdr_start(), and post_cdr().
00425 { 00426 if (!cdr) 00427 return; 00428 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00429 ast_log(LOG_NOTICE, "CDR on channel '%s' already posted\n", S_OR(cdr->channel, "<unknown>")); 00430 }
| static void* do_batch_backend_process | ( | void * | data | ) | [static] |
Definition at line 1210 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().
01211 { 01212 struct ast_cdr_batch_item *processeditem; 01213 struct ast_cdr_batch_item *batchitem = data; 01214 01215 /* Push each CDR into storage mechanism(s) and free all the memory */ 01216 while (batchitem) { 01217 post_cdr(batchitem->cdr); 01218 ast_cdr_free(batchitem->cdr); 01219 processeditem = batchitem; 01220 batchitem = batchitem->next; 01221 ast_free(processeditem); 01222 } 01223 01224 return NULL; 01225 }
| static void* do_cdr | ( | void * | data | ) | [static] |
Definition at line 1332 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().
01333 { 01334 struct timespec timeout; 01335 int schedms; 01336 int numevents = 0; 01337 01338 for (;;) { 01339 struct timeval now; 01340 schedms = ast_sched_wait(sched); 01341 /* this shouldn't happen, but provide a 1 second default just in case */ 01342 if (schedms <= 0) 01343 schedms = 1000; 01344 now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000)); 01345 timeout.tv_sec = now.tv_sec; 01346 timeout.tv_nsec = now.tv_usec * 1000; 01347 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */ 01348 ast_mutex_lock(&cdr_pending_lock); 01349 ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout); 01350 numevents = ast_sched_runq(sched); 01351 ast_mutex_unlock(&cdr_pending_lock); 01352 ast_debug(2, "Processed %d scheduled CDR batches from the run queue\n", numevents); 01353 } 01354 01355 return NULL; 01356 }
| static int do_reload | ( | int | reload | ) | [static] |
Definition at line 1440 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, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_batch_lock, cdr_pending_cond, cdr_sched, cdr_thread, cli_submit, config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, do_cdr(), enabled, EVENT_FLAG_SYSTEM, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, submit_scheduled_batch(), and unanswered.
Referenced by ast_cdr_engine_init(), ast_cdr_engine_reload(), ast_cel_engine_init(), ast_cel_engine_reload(), dnsmgr_init(), dnsmgr_reload(), and handle_cli_reload().
01441 { 01442 struct ast_config *config; 01443 const char *enabled_value; 01444 const char *unanswered_value; 01445 const char *batched_value; 01446 const char *scheduleronly_value; 01447 const char *batchsafeshutdown_value; 01448 const char *size_value; 01449 const char *time_value; 01450 const char *end_before_h_value; 01451 const char *initiatedseconds_value; 01452 int cfg_size; 01453 int cfg_time; 01454 int was_enabled; 01455 int was_batchmode; 01456 int res=0; 01457 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 01458 01459 if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 01460 return 0; 01461 if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEUNCHANGED || config == CONFIG_STATUS_FILEINVALID) { 01462 return 0; 01463 } 01464 01465 ast_mutex_lock(&cdr_batch_lock); 01466 01467 batchsize = BATCH_SIZE_DEFAULT; 01468 batchtime = BATCH_TIME_DEFAULT; 01469 batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT; 01470 batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT; 01471 was_enabled = enabled; 01472 was_batchmode = batchmode; 01473 enabled = 1; 01474 batchmode = 0; 01475 01476 /* don't run the next scheduled CDR posting while reloading */ 01477 AST_SCHED_DEL(sched, cdr_sched); 01478 01479 if (config) { 01480 if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { 01481 enabled = ast_true(enabled_value); 01482 } 01483 if ((unanswered_value = ast_variable_retrieve(config, "general", "unanswered"))) { 01484 unanswered = ast_true(unanswered_value); 01485 } 01486 if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) { 01487 batchmode = ast_true(batched_value); 01488 } 01489 if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) { 01490 batchscheduleronly = ast_true(scheduleronly_value); 01491 } 01492 if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) { 01493 batchsafeshutdown = ast_true(batchsafeshutdown_value); 01494 } 01495 if ((size_value = ast_variable_retrieve(config, "general", "size"))) { 01496 if (sscanf(size_value, "%30d", &cfg_size) < 1) 01497 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value); 01498 else if (cfg_size < 0) 01499 ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size); 01500 else 01501 batchsize = cfg_size; 01502 } 01503 if ((time_value = ast_variable_retrieve(config, "general", "time"))) { 01504 if (sscanf(time_value, "%30d", &cfg_time) < 1) 01505 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value); 01506 else if (cfg_time < 0) 01507 ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time); 01508 else 01509 batchtime = cfg_time; 01510 } 01511 if ((end_before_h_value = ast_variable_retrieve(config, "general", "endbeforehexten"))) 01512 ast_set2_flag(&ast_options, ast_true(end_before_h_value), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN); 01513 if ((initiatedseconds_value = ast_variable_retrieve(config, "general", "initiatedseconds"))) 01514 ast_set2_flag(&ast_options, ast_true(initiatedseconds_value), AST_OPT_FLAG_INITIATED_SECONDS); 01515 } 01516 01517 if (enabled && !batchmode) { 01518 ast_log(LOG_NOTICE, "CDR simple logging enabled.\n"); 01519 } else if (enabled && batchmode) { 01520 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); 01521 ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime); 01522 } else { 01523 ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n"); 01524 } 01525 01526 /* if this reload enabled the CDR batch mode, create the background thread 01527 if it does not exist */ 01528 if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) { 01529 ast_cond_init(&cdr_pending_cond, NULL); 01530 if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) { 01531 ast_log(LOG_ERROR, "Unable to start CDR thread.\n"); 01532 AST_SCHED_DEL(sched, cdr_sched); 01533 } else { 01534 ast_cli_register(&cli_submit); 01535 ast_register_atexit(ast_cdr_engine_term); 01536 res = 0; 01537 } 01538 /* if this reload disabled the CDR and/or batch mode and there is a background thread, 01539 kill it */ 01540 } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) { 01541 /* wake up the thread so it will exit */ 01542 pthread_cancel(cdr_thread); 01543 pthread_kill(cdr_thread, SIGURG); 01544 pthread_join(cdr_thread, NULL); 01545 cdr_thread = AST_PTHREADT_NULL; 01546 ast_cond_destroy(&cdr_pending_cond); 01547 ast_cli_unregister(&cli_submit); 01548 ast_unregister_atexit(ast_cdr_engine_term); 01549 res = 0; 01550 /* if leaving batch mode, then post the CDRs in the batch, 01551 and don't reschedule, since we are stopping CDR logging */ 01552 if (!batchmode && was_batchmode) { 01553 ast_cdr_engine_term(); 01554 } 01555 } else { 01556 res = 0; 01557 } 01558 01559 ast_mutex_unlock(&cdr_batch_lock); 01560 ast_config_destroy(config); 01561 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: CDR\r\nMessage: CDR subsystem reload requested\r\n"); 01562 01563 return res; 01564 }
| static char* handle_cli_status | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1358 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.
01359 { 01360 struct ast_cdr_beitem *beitem=NULL; 01361 int cnt=0; 01362 long nextbatchtime=0; 01363 01364 switch (cmd) { 01365 case CLI_INIT: 01366 e->command = "cdr show status"; 01367 e->usage = 01368 "Usage: cdr show status\n" 01369 " Displays the Call Detail Record engine system status.\n"; 01370 return NULL; 01371 case CLI_GENERATE: 01372 return NULL; 01373 } 01374 01375 if (a->argc > 3) 01376 return CLI_SHOWUSAGE; 01377 01378 ast_cli(a->fd, "\n"); 01379 ast_cli(a->fd, "Call Detail Record (CDR) settings\n"); 01380 ast_cli(a->fd, "----------------------------------\n"); 01381 ast_cli(a->fd, " Logging: %s\n", enabled ? "Enabled" : "Disabled"); 01382 ast_cli(a->fd, " Mode: %s\n", batchmode ? "Batch" : "Simple"); 01383 if (enabled) { 01384 ast_cli(a->fd, " Log unanswered calls: %s\n\n", unanswered ? "Yes" : "No"); 01385 if (batchmode) { 01386 ast_cli(a->fd, "* Batch Mode Settings\n"); 01387 ast_cli(a->fd, " -------------------\n"); 01388 if (batch) 01389 cnt = batch->size; 01390 if (cdr_sched > -1) 01391 nextbatchtime = ast_sched_when(sched, cdr_sched); 01392 ast_cli(a->fd, " Safe shutdown: %s\n", batchsafeshutdown ? "Enabled" : "Disabled"); 01393 ast_cli(a->fd, " Threading model: %s\n", batchscheduleronly ? "Scheduler only" : "Scheduler plus separate threads"); 01394 ast_cli(a->fd, " Current batch size: %d record%s\n", cnt, ESS(cnt)); 01395 ast_cli(a->fd, " Maximum batch size: %d record%s\n", batchsize, ESS(batchsize)); 01396 ast_cli(a->fd, " Maximum batch time: %d second%s\n", batchtime, ESS(batchtime)); 01397 ast_cli(a->fd, " Next batch processing time: %ld second%s\n\n", nextbatchtime, ESS(nextbatchtime)); 01398 } 01399 ast_cli(a->fd, "* Registered Backends\n"); 01400 ast_cli(a->fd, " -------------------\n"); 01401 AST_RWLIST_RDLOCK(&be_list); 01402 if (AST_RWLIST_EMPTY(&be_list)) { 01403 ast_cli(a->fd, " (none)\n"); 01404 } else { 01405 AST_RWLIST_TRAVERSE(&be_list, beitem, list) { 01406 ast_cli(a->fd, " %s\n", beitem->name); 01407 } 01408 } 01409 AST_RWLIST_UNLOCK(&be_list); 01410 ast_cli(a->fd, "\n"); 01411 } 01412 01413 return CLI_SUCCESS; 01414 }
| static char* handle_cli_submit | ( | 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(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, submit_unscheduled_batch(), and ast_cli_entry::usage.
01417 { 01418 switch (cmd) { 01419 case CLI_INIT: 01420 e->command = "cdr submit"; 01421 e->usage = 01422 "Usage: cdr submit\n" 01423 " Posts all pending batched CDR data to the configured CDR backend engine modules.\n"; 01424 return NULL; 01425 case CLI_GENERATE: 01426 return NULL; 01427 } 01428 if (a->argc > 2) 01429 return CLI_SHOWUSAGE; 01430 01431 submit_unscheduled_batch(); 01432 ast_cli(a->fd, "Submitted CDRs to backend engines for processing. This may take a while.\n"); 01433 01434 return CLI_SUCCESS; 01435 }
| static int init_batch | ( | void | ) | [static] |
Definition at line 1199 of file cdr.c.
References ast_malloc, batch, and reset_batch().
Referenced by ast_cdr_detach(), and ast_cdr_engine_init().
01200 { 01201 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */ 01202 if (!(batch = ast_malloc(sizeof(*batch)))) 01203 return -1; 01204 01205 reset_batch(); 01206 01207 return 0; 01208 }
| static void post_cdr | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 1073 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, chan, ast_cdr::channel, check_post(), ast_cdr::disposition, ast_cdr::dstchannel, ast_cdr_beitem::list, ast_cdr::next, S_OR, and unanswered.
Referenced by ast_cdr_detach(), and do_batch_backend_process().
01074 { 01075 char *chan; 01076 struct ast_cdr_beitem *i; 01077 01078 for ( ; cdr ; cdr = cdr->next) { 01079 if (!unanswered && cdr->disposition < AST_CDR_ANSWERED && (ast_strlen_zero(cdr->channel) || ast_strlen_zero(cdr->dstchannel))) { 01080 /* For people, who don't want to see unanswered single-channel events */ 01081 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01082 continue; 01083 } 01084 01085 /* don't post CDRs that are for dialed channels unless those 01086 * channels were originated from asterisk (pbx_spool, manager, 01087 * cli) */ 01088 if (ast_test_flag(cdr, AST_CDR_FLAG_DIALED) && !ast_test_flag(cdr, AST_CDR_FLAG_ORIGINATED)) { 01089 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01090 continue; 01091 } 01092 01093 chan = S_OR(cdr->channel, "<unknown>"); 01094 check_post(cdr); 01095 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 01096 if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) 01097 continue; 01098 AST_RWLIST_RDLOCK(&be_list); 01099 AST_RWLIST_TRAVERSE(&be_list, i, list) { 01100 i->be(cdr); 01101 } 01102 AST_RWLIST_UNLOCK(&be_list); 01103 } 01104 }
| static void reset_batch | ( | void | ) | [static] |
Definition at line 1191 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 822 of file cdr.c.
References ast_copy_string(), ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, num, S_OR, and ast_cdr::src.
Referenced by ast_cdr_init(), ast_cdr_setcid(), and ast_cdr_update().
00823 { 00824 /* Grab source from ANI or normal Caller*ID */ 00825 const char *num = S_OR(c->cid.cid_ani, c->cid.cid_num); 00826 if (!cdr) 00827 return; 00828 if (!ast_strlen_zero(c->cid.cid_name)) { 00829 if (!ast_strlen_zero(num)) /* both name and number */ 00830 snprintf(cdr->clid, sizeof(cdr->clid), "\"%s\" <%s>", c->cid.cid_name, num); 00831 else /* only name */ 00832 ast_copy_string(cdr->clid, c->cid.cid_name, sizeof(cdr->clid)); 00833 } else if (!ast_strlen_zero(num)) { /* only number */ 00834 ast_copy_string(cdr->clid, num, sizeof(cdr->clid)); 00835 } else { /* nothing known */ 00836 cdr->clid[0] = '\0'; 00837 } 00838 ast_copy_string(cdr->src, S_OR(num, ""), sizeof(cdr->src)); 00839 00840 }
| static int submit_scheduled_batch | ( | const void * | data | ) | [static] |
Definition at line 1257 of file cdr.c.
References ast_cdr_submit_batch(), ast_sched_add(), batchtime, and cdr_sched.
Referenced by do_reload(), and submit_unscheduled_batch().
01258 { 01259 ast_cdr_submit_batch(0); 01260 /* manually reschedule from this point in time */ 01261 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); 01262 /* returning zero so the scheduler does not automatically reschedule */ 01263 return 0; 01264 }
| static void submit_unscheduled_batch | ( | void | ) | [static] |
Definition at line 1266 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, and submit_scheduled_batch().
Referenced by ast_cdr_detach(), and handle_cli_submit().
01267 { 01268 /* this is okay since we are not being called from within the scheduler */ 01269 AST_SCHED_DEL(sched, cdr_sched); 01270 /* schedule the submission to occur ASAP (1 ms) */ 01271 cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL); 01272 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */ 01273 ast_mutex_lock(&cdr_pending_lock); 01274 ast_cond_signal(&cdr_pending_cond); 01275 ast_mutex_unlock(&cdr_pending_lock); 01276 }
| char ast_default_accountcode[AST_MAX_ACCOUNT_CODE] |
| int ast_default_amaflags = AST_CDR_DOCUMENTATION |
Default AMA flag for billing records (CDR's)
Definition at line 54 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(), handle_cli_status(), init_batch(), and reset_batch().
int batchmode [static] |
Definition at line 88 of file cdr.c.
Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().
int batchsafeshutdown [static] |
Definition at line 92 of file cdr.c.
Referenced by ast_cdr_engine_term(), do_reload(), and handle_cli_status().
int batchscheduleronly [static] |
Definition at line 91 of file cdr.c.
Referenced by ast_cdr_submit_batch(), do_reload(), and handle_cli_status().
int batchsize [static] |
Definition at line 89 of file cdr.c.
Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().
int batchtime [static] |
Definition at line 90 of file cdr.c.
Referenced by do_reload(), handle_cli_status(), and submit_scheduled_batch().
ast_mutex_t cdr_batch_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Definition at line 94 of file cdr.c.
Referenced by ast_cdr_detach(), ast_cdr_engine_init(), ast_cdr_submit_batch(), and do_reload().
ast_cond_t cdr_pending_cond [static] |
Definition at line 98 of file cdr.c.
Referenced by do_cdr(), do_reload(), and submit_unscheduled_batch().
ast_mutex_t cdr_pending_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
const char* const cdr_readonly_vars[] [static] |
Initial value:
{ "clid", "src", "dst", "dcontext", "channel", "dstchannel",
"lastapp", "lastdata", "start", "answer", "end", "duration",
"billsec", "disposition", "amaflags", "accountcode", "uniqueid", "linkedid",
"userfield", NULL }
Definition at line 292 of file cdr.c.
Referenced by ast_cdr_serialize_variables(), and ast_cdr_setvar().
int cdr_sched = -1 [static] |
Definition at line 78 of file cdr.c.
Referenced by do_reload(), handle_cli_status(), submit_scheduled_batch(), and submit_unscheduled_batch().
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] |
Definition at line 86 of file cdr.c.
Referenced by __ast_http_load(), ast_cdr_detach(), ast_dnsmgr_lookup(), check_cdr_enabled(), do_reload(), handle_cli_refresh(), handle_cli_status(), load_odbc_config(), and osp_check_destination().
struct sched_context* sched [static] |
int unanswered [static] |
Is the CDR subsystem enabled ?
Definition at line 87 of file cdr.c.
Referenced by ast_cdr_isset_unanswered(), do_reload(), handle_cli_status(), and post_cdr().
1.5.6