#include "asterisk.h"
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/logger.h"
#include "asterisk/callerid.h"
#include "asterisk/causes.h"
#include "asterisk/options.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 dependency graph for cdr.c:
Go to the source code of this file.
Data Structures | |
struct | ast_cdr_batch |
struct | ast_cdr_batch_item |
struct | ast_cdr_beitem |
Defines | |
#define | BATCH_SAFE_SHUTDOWN_DEFAULT 1 |
#define | BATCH_SCHEDULER_ONLY_DEFAULT 0 |
#define | BATCH_SIZE_DEFAULT 100 |
#define | BATCH_TIME_DEFAULT 300 |
Functions | |
ast_cdr * | ast_cdr_alloc (void) |
Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure). | |
int | ast_cdr_amaflags2int (const char *flag) |
void | ast_cdr_answer (struct ast_cdr *cdr) |
ast_cdr * | ast_cdr_append (struct ast_cdr *cdr, struct ast_cdr *newcdr) |
int | ast_cdr_appenduserfield (struct ast_channel *chan, const char *userfield) |
void | ast_cdr_busy (struct ast_cdr *cdr) |
int | ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr) |
void | ast_cdr_detach (struct ast_cdr *cdr) |
void | ast_cdr_discard (struct ast_cdr *cdr) |
Discard and free a CDR record. | |
char * | ast_cdr_disp2str (int disposition) |
int | ast_cdr_disposition (struct ast_cdr *cdr, int cause) |
ast_cdr * | ast_cdr_dup (struct ast_cdr *cdr) |
Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure). | |
void | ast_cdr_end (struct ast_cdr *cdr) |
int | ast_cdr_engine_init (void) |
int | ast_cdr_engine_reload (void) |
void | ast_cdr_engine_term (void) |
void | ast_cdr_failed (struct ast_cdr *cdr) |
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. | |
void | ast_cdr_merge (struct ast_cdr *to, struct ast_cdr *from) |
int | ast_cdr_register (const char *name, const char *desc, ast_cdrbe be) |
void | ast_cdr_reset (struct ast_cdr *cdr, struct ast_flags *_flags) |
int | ast_cdr_serialize_variables (struct ast_cdr *cdr, char *buf, size_t size, char delim, char sep, int recur) |
int | ast_cdr_setaccount (struct ast_channel *chan, const char *account) |
int | ast_cdr_setamaflags (struct ast_channel *chan, const char *flag) |
void | ast_cdr_setapp (struct ast_cdr *cdr, char *app, char *data) |
int | ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *c) |
void | ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chann) |
int | ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield) |
int | ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur) |
void | ast_cdr_start (struct ast_cdr *cdr) |
void | ast_cdr_submit_batch (int shutdown) |
void | ast_cdr_unregister (const char *name) |
int | ast_cdr_update (struct ast_channel *c) |
static | AST_LIST_HEAD_STATIC (be_list, ast_cdr_beitem) |
AST_MUTEX_DEFINE_STATIC (cdr_pending_lock) | |
AST_MUTEX_DEFINE_STATIC (cdr_batch_lock) | |
static void | cdr_get_tv (struct timeval tv, const char *fmt, char *buf, int bufsize) |
static void | cdr_merge_vars (struct ast_cdr *to, struct ast_cdr *from) |
static void | check_post (struct ast_cdr *cdr) |
print a warning if cdr already posted | |
static void | check_start (struct ast_cdr *cdr) |
print a warning if cdr already started | |
static void * | do_batch_backend_process (void *data) |
static void * | do_cdr (void *data) |
static int | do_reload (void) |
static int | handle_cli_status (int fd, int argc, char *argv[]) |
static int | handle_cli_submit (int fd, int argc, char *argv[]) |
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 (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_cond_t | cdr_pending_cond |
static const char * | cdr_readonly_vars [] |
static int | cdr_sched = -1 |
static pthread_t | cdr_thread = AST_PTHREADT_NULL |
static struct ast_cli_entry | cli_status |
static struct ast_cli_entry | cli_submit |
static int | enabled |
static struct sched_context * | sched |
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 | ) |
Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
Definition at line 464 of file cdr.c.
References ast_calloc, ast_log(), and LOG_ERROR.
Referenced by __agent_start_monitoring(), __ast_pbx_run(), __ast_read(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_dup(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), builtin_blindtransfer(), clear_caller(), findmeexec(), and start_monitor_exec().
00465 { 00466 struct ast_cdr *x = ast_calloc(1, sizeof(struct ast_cdr)); 00467 if (!x) 00468 ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n"); 00469 return x; 00470 }
int ast_cdr_amaflags2int | ( | const char * | flag | ) |
flag | string form of flag Converts the string form of the flag to the binary form. Returns the binary form of the flag |
Definition at line 893 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(), process_zap(), and set_config().
00894 { 00895 if (!strcasecmp(flag, "default")) 00896 return 0; 00897 if (!strcasecmp(flag, "omit")) 00898 return AST_CDR_OMIT; 00899 if (!strcasecmp(flag, "billing")) 00900 return AST_CDR_BILLING; 00901 if (!strcasecmp(flag, "documentation")) 00902 return AST_CDR_DOCUMENTATION; 00903 return -1; 00904 }
void ast_cdr_answer | ( | struct ast_cdr * | cdr | ) |
cdr | the cdr you wish to associate with the call Starts all CDR stuff necessary for doing CDR when answering a call NULL argument is just fine. |
Definition at line 638 of file cdr.c.
References ast_cdr::answer, AST_CDR_ANSWERED, check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by __ast_read(), and ast_answer().
00639 { 00640 00641 for (; cdr; cdr = cdr->next) { 00642 check_post(cdr); 00643 if (cdr->disposition < AST_CDR_ANSWERED) 00644 cdr->disposition = AST_CDR_ANSWERED; 00645 if (ast_tvzero(cdr->answer)) 00646 cdr->answer = ast_tvnow(); 00647 } 00648 }
Definition at line 966 of file cdr.c.
References ast_cdr::next.
Referenced by ast_cdr_fork(), ast_cdr_merge(), and attempt_transfer().
00967 { 00968 struct ast_cdr *ret; 00969 00970 if (cdr) { 00971 ret = cdr; 00972 00973 while (cdr->next) 00974 cdr = cdr->next; 00975 cdr->next = newcdr; 00976 } else { 00977 ret = newcdr; 00978 } 00979 00980 return ret; 00981 }
int ast_cdr_appenduserfield | ( | struct ast_channel * | chan, | |
const char * | userfield | |||
) |
Definition at line 858 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, len, ast_cdr::next, and ast_cdr::userfield.
Referenced by action_setcdruserfield(), appendcdruserfield_exec(), and ast_bridge_call().
00859 { 00860 struct ast_cdr *cdr = chan->cdr; 00861 00862 for ( ; cdr ; cdr = cdr->next) { 00863 int len = strlen(cdr->userfield); 00864 00865 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00866 ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len); 00867 } 00868 00869 return 0; 00870 }
void ast_cdr_busy | ( | struct ast_cdr * | cdr | ) |
cdr | the cdr you wish to associate with the call Returns nothing |
Definition at line 650 of file cdr.c.
References AST_CDR_BUSY, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), and ast_cdr::next.
Referenced by ast_cdr_disposition(), and ring_entry().
00651 { 00652 00653 for (; cdr; cdr = cdr->next) { 00654 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00655 check_post(cdr); 00656 if (cdr->disposition < AST_CDR_BUSY) 00657 cdr->disposition = AST_CDR_BUSY; 00658 } 00659 } 00660 }
Definition at line 333 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().
00334 { 00335 struct ast_var_t *variables, *newvariable = NULL; 00336 struct varshead *headpa, *headpb; 00337 const char *var, *val; 00338 int x = 0; 00339 00340 if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */ 00341 return 0; 00342 00343 headpa = &from_cdr->varshead; 00344 headpb = &to_cdr->varshead; 00345 00346 AST_LIST_TRAVERSE(headpa,variables,entries) { 00347 if (variables && 00348 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00349 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00350 newvariable = ast_var_assign(var, val); 00351 AST_LIST_INSERT_HEAD(headpb, newvariable, entries); 00352 x++; 00353 } 00354 } 00355 00356 return x; 00357 }
void ast_cdr_detach | ( | struct ast_cdr * | cdr | ) |
cdr | Which CDR to detach from the channel thread Prevents the channel thread from blocking on the CDR handling Returns nothing |
Definition at line 1078 of file cdr.c.
References ast_calloc, AST_CDR_FLAG_POST_DISABLED, ast_cdr_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, batch, batchmode, batchsize, ast_cdr_batch_item::cdr, enabled, ast_cdr_batch::head, init_batch(), LOG_DEBUG, ast_cdr_batch_item::next, option_debug, post_cdr(), ast_cdr_batch::size, submit_unscheduled_batch(), and ast_cdr_batch::tail.
Referenced by ast_cdr_reset(), ast_hangup(), and ast_pbx_outgoing_cdr_failed().
01079 { 01080 struct ast_cdr_batch_item *newtail; 01081 int curr; 01082 01083 if (!cdr) 01084 return; 01085 01086 /* maybe they disabled CDR stuff completely, so just drop it */ 01087 if (!enabled) { 01088 if (option_debug) 01089 ast_log(LOG_DEBUG, "Dropping CDR !\n"); 01090 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01091 ast_cdr_free(cdr); 01092 return; 01093 } 01094 01095 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */ 01096 if (!batchmode) { 01097 post_cdr(cdr); 01098 ast_cdr_free(cdr); 01099 return; 01100 } 01101 01102 /* otherwise, each CDR gets put into a batch list (at the end) */ 01103 if (option_debug) 01104 ast_log(LOG_DEBUG, "CDR detaching from this thread\n"); 01105 01106 /* we'll need a new tail for every CDR */ 01107 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) { 01108 post_cdr(cdr); 01109 ast_cdr_free(cdr); 01110 return; 01111 } 01112 01113 /* don't traverse a whole list (just keep track of the tail) */ 01114 ast_mutex_lock(&cdr_batch_lock); 01115 if (!batch) 01116 init_batch(); 01117 if (!batch->head) { 01118 /* new batch is empty, so point the head at the new tail */ 01119 batch->head = newtail; 01120 } else { 01121 /* already got a batch with something in it, so just append a new tail */ 01122 batch->tail->next = newtail; 01123 } 01124 newtail->cdr = cdr; 01125 batch->tail = newtail; 01126 curr = batch->size++; 01127 ast_mutex_unlock(&cdr_batch_lock); 01128 01129 /* if we have enough stuff to post, then do it */ 01130 if (curr >= (batchsize - 1)) 01131 submit_unscheduled_batch(); 01132 }
void ast_cdr_discard | ( | struct ast_cdr * | cdr | ) |
Discard and free a CDR record.
cdr | ast_cdr structure to free Returns nothing -- same as free, but no checks or complaints |
Definition at line 453 of file cdr.c.
References ast_cdr_free_vars(), free, and ast_cdr::next.
Referenced by ast_bridge_call().
00454 { 00455 while (cdr) { 00456 struct ast_cdr *next = cdr->next; 00457 00458 ast_cdr_free_vars(cdr, 0); 00459 free(cdr); 00460 cdr = next; 00461 } 00462 }
char* ast_cdr_disp2str | ( | int | disposition | ) |
disposition | input binary form Converts the binary form of a disposition to string form. Returns a pointer to the string form |
Definition at line 792 of file cdr.c.
References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, and AST_CDR_NOANSWER.
Referenced by ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), manager_log(), mysql_log(), odbc_log(), pgsql_log(), and tds_log().
00793 { 00794 switch (disposition) { 00795 case AST_CDR_NOANSWER: 00796 return "NO ANSWER"; 00797 case AST_CDR_FAILED: 00798 return "FAILED"; 00799 case AST_CDR_BUSY: 00800 return "BUSY"; 00801 case AST_CDR_ANSWERED: 00802 return "ANSWERED"; 00803 } 00804 return "UNKNOWN"; 00805 }
int ast_cdr_disposition | ( | struct ast_cdr * | cdr, | |
int | cause | |||
) |
cdr | the cdr you wish to associate with the call Returns nothing | |
cause | the AST_CAUSE_* |
Definition at line 673 of file cdr.c.
References AST_CAUSE_BUSY, AST_CAUSE_FAILURE, AST_CAUSE_NORMAL, AST_CAUSE_NOTDEFINED, ast_cdr_busy(), ast_cdr_failed(), ast_log(), LOG_WARNING, and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), clear_caller(), and findmeexec().
00674 { 00675 int res = 0; 00676 00677 for (; cdr; cdr = cdr->next) { 00678 switch(cause) { 00679 case AST_CAUSE_BUSY: 00680 ast_cdr_busy(cdr); 00681 break; 00682 case AST_CAUSE_FAILURE: 00683 ast_cdr_failed(cdr); 00684 break; 00685 case AST_CAUSE_NORMAL: 00686 break; 00687 case AST_CAUSE_NOTDEFINED: 00688 res = -1; 00689 break; 00690 default: 00691 res = -1; 00692 ast_log(LOG_WARNING, "Cause not handled\n"); 00693 } 00694 } 00695 return res; 00696 }
Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
Duplicate a CDR record
Definition at line 167 of file cdr.c.
References ast_cdr_alloc(), and ast_cdr_copy_vars().
Referenced by ast_async_goto(), ast_cdr_fork(), and ast_cdr_reset().
00168 { 00169 struct ast_cdr *newcdr; 00170 00171 if (!cdr) /* don't die if we get a null cdr pointer */ 00172 return NULL; 00173 newcdr = ast_cdr_alloc(); 00174 if (!newcdr) 00175 return NULL; 00176 00177 memcpy(newcdr, cdr, sizeof(*newcdr)); 00178 /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */ 00179 memset(&newcdr->varshead, 0, sizeof(newcdr->varshead)); 00180 ast_cdr_copy_vars(newcdr, cdr); 00181 newcdr->next = NULL; 00182 00183 return newcdr; 00184 }
void ast_cdr_end | ( | struct ast_cdr * | cdr | ) |
cdr | the cdr you have associated the call with Registers the end of call time in the cdr structure. Returns nothing |
Definition at line 777 of file cdr.c.
References ast_cdr::answer, AST_CDR_FAILED, ast_log(), 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_read(), __ast_request_and_dial(), ast_cdr_reset(), ast_feature_request_and_dial(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), clear_caller(), and findmeexec().
00778 { 00779 for ( ; cdr ; cdr = cdr->next) { 00780 check_post(cdr); 00781 if (ast_tvzero(cdr->end)) 00782 cdr->end = ast_tvnow(); 00783 if (ast_tvzero(cdr->start)) { 00784 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>")); 00785 cdr->disposition = AST_CDR_FAILED; 00786 } else 00787 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec; 00788 cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec; 00789 } 00790 }
int ast_cdr_engine_init | ( | void | ) |
Load the configuration file cdr.conf and possibly start the CDR scheduling thread
Definition at line 1332 of file cdr.c.
References ast_cli_register(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cli_status, do_reload(), init_batch(), LOG_ERROR, and sched_context_create().
Referenced by main().
01333 { 01334 int res; 01335 01336 sched = sched_context_create(); 01337 if (!sched) { 01338 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 01339 return -1; 01340 } 01341 01342 ast_cli_register(&cli_status); 01343 01344 res = do_reload(); 01345 if (res) { 01346 ast_mutex_lock(&cdr_batch_lock); 01347 res = init_batch(); 01348 ast_mutex_unlock(&cdr_batch_lock); 01349 } 01350 01351 return res; 01352 }
int ast_cdr_engine_reload | ( | void | ) |
Reload the configuration file cdr.conf and start/stop CDR scheduling thread
Definition at line 1361 of file cdr.c.
References do_reload().
01362 { 01363 return do_reload(); 01364 }
void ast_cdr_engine_term | ( | void | ) |
Submit any remaining CDRs and prepare for shutdown
Definition at line 1356 of file cdr.c.
References ast_cdr_submit_batch(), and batchsafeshutdown.
Referenced by do_reload(), and quit_handler().
01357 { 01358 ast_cdr_submit_batch(batchsafeshutdown); 01359 }
void ast_cdr_failed | ( | struct ast_cdr * | cdr | ) |
cdr | the cdr you wish to associate with the call Returns nothing |
Definition at line 662 of file cdr.c.
References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_cdr_disposition(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), clear_caller(), and findmeexec().
00663 { 00664 for (; cdr; cdr = cdr->next) { 00665 check_post(cdr); 00666 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00667 if (cdr->disposition < AST_CDR_FAILED) 00668 cdr->disposition = AST_CDR_FAILED; 00669 } 00670 } 00671 }
char* ast_cdr_flags2str | ( | int | flag | ) |
Converts AMA flag to printable string
Definition at line 808 of file cdr.c.
References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
Referenced by _sip_show_peer(), ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), manager_log(), sip_show_user(), and tds_log().
00809 { 00810 switch(flag) { 00811 case AST_CDR_OMIT: 00812 return "OMIT"; 00813 case AST_CDR_BILLING: 00814 return "BILLING"; 00815 case AST_CDR_DOCUMENTATION: 00816 return "DOCUMENTATION"; 00817 } 00818 return "Unknown"; 00819 }
void ast_cdr_free | ( | struct ast_cdr * | cdr | ) |
Free a CDR record.
cdr | ast_cdr structure to free Returns nothing |
Definition at line 433 of file cdr.c.
References AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), ast_log(), ast_test_flag, ast_cdr::channel, ast_cdr::end, free, LOG_NOTICE, ast_cdr::next, S_OR, and ast_cdr::start.
Referenced by ast_cdr_detach(), and do_batch_backend_process().
00434 { 00435 00436 while (cdr) { 00437 struct ast_cdr *next = cdr->next; 00438 char *chan = S_OR(cdr->channel, "<unknown>"); 00439 if (!ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) 00440 ast_log(LOG_NOTICE, "CDR on channel '%s' not posted\n", chan); 00441 if (ast_tvzero(cdr->end)) 00442 ast_log(LOG_NOTICE, "CDR on channel '%s' lacks end\n", chan); 00443 if (ast_tvzero(cdr->start)) 00444 ast_log(LOG_NOTICE, "CDR on channel '%s' lacks start\n", chan); 00445 00446 ast_cdr_free_vars(cdr, 0); 00447 free(cdr); 00448 cdr = next; 00449 } 00450 }
void ast_cdr_free_vars | ( | struct ast_cdr * | cdr, | |
int | recur | |||
) |
Definition at line 403 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().
00404 { 00405 00406 /* clear variables */ 00407 for (; cdr; cdr = recur ? cdr->next : NULL) { 00408 struct ast_var_t *vardata; 00409 struct varshead *headp = &cdr->varshead; 00410 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 00411 ast_var_delete(vardata); 00412 } 00413 }
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 218 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_strlen_zero(), 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, fmt, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.
Referenced by ast_cdr_serialize_variables(), and cdr_read().
00219 { 00220 const char *fmt = "%Y-%m-%d %T"; 00221 const char *varbuf; 00222 00223 if (!cdr) /* don't die if the cdr is null */ 00224 return; 00225 00226 *ret = NULL; 00227 /* special vars (the ones from the struct ast_cdr when requested by name) 00228 I'd almost say we should convert all the stringed vals to vars */ 00229 00230 if (!strcasecmp(name, "clid")) 00231 ast_copy_string(workspace, cdr->clid, workspacelen); 00232 else if (!strcasecmp(name, "src")) 00233 ast_copy_string(workspace, cdr->src, workspacelen); 00234 else if (!strcasecmp(name, "dst")) 00235 ast_copy_string(workspace, cdr->dst, workspacelen); 00236 else if (!strcasecmp(name, "dcontext")) 00237 ast_copy_string(workspace, cdr->dcontext, workspacelen); 00238 else if (!strcasecmp(name, "channel")) 00239 ast_copy_string(workspace, cdr->channel, workspacelen); 00240 else if (!strcasecmp(name, "dstchannel")) 00241 ast_copy_string(workspace, cdr->dstchannel, workspacelen); 00242 else if (!strcasecmp(name, "lastapp")) 00243 ast_copy_string(workspace, cdr->lastapp, workspacelen); 00244 else if (!strcasecmp(name, "lastdata")) 00245 ast_copy_string(workspace, cdr->lastdata, workspacelen); 00246 else if (!strcasecmp(name, "start")) 00247 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen); 00248 else if (!strcasecmp(name, "answer")) 00249 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen); 00250 else if (!strcasecmp(name, "end")) 00251 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen); 00252 else if (!strcasecmp(name, "duration")) 00253 snprintf(workspace, workspacelen, "%ld", cdr->duration); 00254 else if (!strcasecmp(name, "billsec")) 00255 snprintf(workspace, workspacelen, "%ld", cdr->billsec); 00256 else if (!strcasecmp(name, "disposition")) { 00257 if (raw) { 00258 snprintf(workspace, workspacelen, "%ld", cdr->disposition); 00259 } else { 00260 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); 00261 } 00262 } else if (!strcasecmp(name, "amaflags")) { 00263 if (raw) { 00264 snprintf(workspace, workspacelen, "%ld", cdr->amaflags); 00265 } else { 00266 ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); 00267 } 00268 } else if (!strcasecmp(name, "accountcode")) 00269 ast_copy_string(workspace, cdr->accountcode, workspacelen); 00270 else if (!strcasecmp(name, "uniqueid")) 00271 ast_copy_string(workspace, cdr->uniqueid, workspacelen); 00272 else if (!strcasecmp(name, "userfield")) 00273 ast_copy_string(workspace, cdr->userfield, workspacelen); 00274 else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) 00275 ast_copy_string(workspace, varbuf, workspacelen); 00276 else 00277 workspace[0] = '\0'; 00278 00279 if (!ast_strlen_zero(workspace)) 00280 *ret = workspace; 00281 }
static const char* ast_cdr_getvar_internal | ( | struct ast_cdr * | cdr, | |
const char * | name, | |||
int | recur | |||
) | [static] |
Definition at line 186 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().
00187 { 00188 if (ast_strlen_zero(name)) 00189 return NULL; 00190 00191 for (; cdr; cdr = recur ? cdr->next : NULL) { 00192 struct ast_var_t *variables; 00193 struct varshead *headp = &cdr->varshead; 00194 AST_LIST_TRAVERSE(headp, variables, entries) { 00195 if (!strcasecmp(name, ast_var_name(variables))) 00196 return ast_var_value(variables); 00197 } 00198 } 00199 00200 return NULL; 00201 }
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 Return is negligible. (returns 0 by default) |
Definition at line 752 of file cdr.c.
References ast_channel::_state, ast_cdr::accountcode, ast_cdr::amaflags, ast_channel::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_log(), AST_STATE_UP, ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, LOG_WARNING, ast_cdr::next, S_OR, set_one_cid(), and ast_cdr::uniqueid.
Referenced by __ast_pbx_run(), __ast_read(), __ast_request_and_dial(), ast_bridge_call(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), builtin_blindtransfer(), clear_caller(), and findmeexec().
00753 { 00754 char *chan; 00755 00756 for ( ; cdr ; cdr = cdr->next) { 00757 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00758 chan = S_OR(cdr->channel, "<unknown>"); 00759 if (!ast_strlen_zero(cdr->channel)) 00760 ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan); 00761 ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); 00762 set_one_cid(cdr, c); 00763 00764 cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 00765 cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; 00766 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00767 /* Destination information */ 00768 ast_copy_string(cdr->dst, c->exten, sizeof(cdr->dst)); 00769 ast_copy_string(cdr->dcontext, c->context, sizeof(cdr->dcontext)); 00770 /* Unique call identifier */ 00771 ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid)); 00772 } 00773 } 00774 return 0; 00775 }
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 508 of file cdr.c.
References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_append(), 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_set_flag, ast_strlen_zero(), ast_test_flag, ast_cdr::billsec, cdr_merge_vars(), ast_cdr::channel, 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::next, ast_cdr::src, ast_cdr::start, and ast_cdr::userfield.
Referenced by ast_bridge_call().
00509 { 00510 struct ast_cdr *tcdr; 00511 00512 if (!to || !from) 00513 return; 00514 00515 if (!ast_tvzero(from->start)) { 00516 if (!ast_tvzero(to->start)) { 00517 if (ast_tvcmp(to->start, from->start) > 0 ) { 00518 to->start = from->start; /* use the earliest time */ 00519 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00520 } 00521 /* else nothing to do */ 00522 } else { 00523 to->start = from->start; 00524 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00525 } 00526 } 00527 if (!ast_tvzero(from->answer)) { 00528 if (!ast_tvzero(to->answer)) { 00529 if (ast_tvcmp(to->answer, from->answer) > 0 ) { 00530 to->answer = from->answer; /* use the earliest time */ 00531 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00532 } 00533 /* we got the earliest answer time, so we'll settle for that? */ 00534 } else { 00535 to->answer = from->answer; 00536 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00537 } 00538 } 00539 if (!ast_tvzero(from->end)) { 00540 if (!ast_tvzero(to->end)) { 00541 if (ast_tvcmp(to->end, from->end) < 0 ) { 00542 to->end = from->end; /* use the latest time */ 00543 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00544 to->duration = to->end.tv_sec - to->start.tv_sec; /* don't forget to update the duration, billsec, when we set end */ 00545 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00546 } 00547 /* else, nothing to do */ 00548 } else { 00549 to->end = from->end; 00550 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00551 to->duration = to->end.tv_sec - to->start.tv_sec; 00552 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00553 } 00554 } 00555 if (to->disposition < from->disposition) { 00556 to->disposition = from->disposition; 00557 from->disposition = AST_CDR_NOANSWER; 00558 } 00559 if (ast_strlen_zero(to->lastapp) && !ast_strlen_zero(from->lastapp)) { 00560 ast_copy_string(to->lastapp, from->lastapp, sizeof(to->lastapp)); 00561 from->lastapp[0] = 0; /* theft */ 00562 } 00563 if (ast_strlen_zero(to->lastdata) && !ast_strlen_zero(from->lastdata)) { 00564 ast_copy_string(to->lastdata, from->lastdata, sizeof(to->lastdata)); 00565 from->lastdata[0] = 0; /* theft */ 00566 } 00567 if (ast_strlen_zero(to->dcontext) && !ast_strlen_zero(from->dcontext)) { 00568 ast_copy_string(to->dcontext, from->dcontext, sizeof(to->dcontext)); 00569 from->dcontext[0] = 0; /* theft */ 00570 } 00571 if (ast_strlen_zero(to->dstchannel) && !ast_strlen_zero(from->dstchannel)) { 00572 ast_copy_string(to->dstchannel, from->dstchannel, sizeof(to->dstchannel)); 00573 from->dstchannel[0] = 0; /* theft */ 00574 } 00575 if (ast_strlen_zero(to->channel) && !ast_strlen_zero(from->channel)) { 00576 ast_copy_string(to->channel, from->channel, sizeof(to->channel)); 00577 from->channel[0] = 0; /* theft */ 00578 } 00579 if (ast_strlen_zero(to->src) && !ast_strlen_zero(from->src)) { 00580 ast_copy_string(to->src, from->src, sizeof(to->src)); 00581 from->src[0] = 0; /* theft */ 00582 } 00583 if (ast_strlen_zero(to->dst) && !ast_strlen_zero(from->dst)) { 00584 ast_copy_string(to->dst, from->dst, sizeof(to->dst)); 00585 from->dst[0] = 0; /* theft */ 00586 } 00587 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (!to->amaflags && from->amaflags)) { 00588 to->amaflags = from->amaflags; 00589 from->amaflags = 0; /* theft */ 00590 } 00591 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) { 00592 ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode)); 00593 from->accountcode[0] = 0; /* theft */ 00594 } 00595 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) { 00596 ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield)); 00597 from->userfield[0] = 0; /* theft */ 00598 } 00599 /* flags, varsead, ? */ 00600 cdr_merge_vars(from, to); 00601 00602 if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS)) 00603 ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS); 00604 if (ast_test_flag(from, AST_CDR_FLAG_POSTED)) 00605 ast_set_flag(to, AST_CDR_FLAG_POSTED); 00606 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) 00607 ast_set_flag(to, AST_CDR_FLAG_LOCKED); 00608 if (ast_test_flag(from, AST_CDR_FLAG_CHILD)) 00609 ast_set_flag(to, AST_CDR_FLAG_CHILD); 00610 if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED)) 00611 ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED); 00612 00613 /* last, but not least, we need to merge any forked CDRs to the 'to' cdr */ 00614 while (from->next) { 00615 /* just rip 'em off the 'from' and insert them on the 'to' */ 00616 tcdr = from->next; 00617 from->next = tcdr->next; 00618 tcdr->next = NULL; 00619 /* tcdr is now ripped from the current list; */ 00620 ast_cdr_append(to, tcdr); 00621 } 00622 }
int ast_cdr_register | ( | const char * | name, | |
const char * | desc, | |||
ast_cdrbe | be | |||
) |
Register a CDR driver. Each registered CDR driver generates a CDR
Definition at line 108 of file cdr.c.
References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, and ast_cdr_beitem::name.
Referenced by load_module(), my_load_module(), odbc_load_module(), process_my_load_module(), and tds_load_module().
00109 { 00110 struct ast_cdr_beitem *i; 00111 00112 if (!name) 00113 return -1; 00114 if (!be) { 00115 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name); 00116 return -1; 00117 } 00118 00119 AST_LIST_LOCK(&be_list); 00120 AST_LIST_TRAVERSE(&be_list, i, list) { 00121 if (!strcasecmp(name, i->name)) 00122 break; 00123 } 00124 AST_LIST_UNLOCK(&be_list); 00125 00126 if (i) { 00127 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name); 00128 return -1; 00129 } 00130 00131 if (!(i = ast_calloc(1, sizeof(*i)))) 00132 return -1; 00133 00134 i->be = be; 00135 ast_copy_string(i->name, name, sizeof(i->name)); 00136 ast_copy_string(i->desc, desc, sizeof(i->desc)); 00137 00138 AST_LIST_LOCK(&be_list); 00139 AST_LIST_INSERT_HEAD(&be_list, i, list); 00140 AST_LIST_UNLOCK(&be_list); 00141 00142 return 0; 00143 }
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 929 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_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_flags::flags, ast_cdr::next, and ast_cdr::start.
Referenced by ast_bridge_call_thread(), ast_cdr_fork(), disa_exec(), and pbx_builtin_resetcdr().
00930 { 00931 struct ast_cdr *dup; 00932 struct ast_flags flags = { 0 }; 00933 00934 if (_flags) 00935 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); 00936 00937 for ( ; cdr ; cdr = cdr->next) { 00938 /* Detach if post is requested */ 00939 if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00940 if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) { 00941 ast_cdr_end(cdr); 00942 if ((dup = ast_cdr_dup(cdr))) { 00943 ast_cdr_detach(dup); 00944 } 00945 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 00946 } 00947 00948 /* clear variables */ 00949 if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) { 00950 ast_cdr_free_vars(cdr, 0); 00951 } 00952 00953 /* Reset to initial state */ 00954 ast_clear_flag(cdr, AST_FLAGS_ALL); 00955 memset(&cdr->start, 0, sizeof(cdr->start)); 00956 memset(&cdr->end, 0, sizeof(cdr->end)); 00957 memset(&cdr->answer, 0, sizeof(cdr->answer)); 00958 cdr->billsec = 0; 00959 cdr->duration = 0; 00960 ast_cdr_start(cdr); 00961 cdr->disposition = AST_CDR_NOANSWER; 00962 } 00963 } 00964 }
int ast_cdr_serialize_variables | ( | struct ast_cdr * | cdr, | |
char * | buf, | |||
size_t | size, | |||
char | delim, | |||
char | sep, | |||
int | recur | |||
) |
Definition at line 359 of file cdr.c.
References ast_build_string(), ast_cdr_getvar(), AST_LIST_TRAVERSE, ast_log(), ast_strlen_zero(), ast_var_name(), ast_var_value(), cdr_readonly_vars, LOG_ERROR, ast_cdr::next, total, var, and ast_cdr::varshead.
Referenced by handle_showchan(), and handle_showchan_deprecated().
00360 { 00361 struct ast_var_t *variables; 00362 const char *var, *val; 00363 char *tmp; 00364 char workspace[256]; 00365 int total = 0, x = 0, i; 00366 00367 memset(buf, 0, size); 00368 00369 for (; cdr; cdr = recur ? cdr->next : NULL) { 00370 if (++x > 1) 00371 ast_build_string(&buf, &size, "\n"); 00372 00373 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) { 00374 if (variables && 00375 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00376 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00377 if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, var, delim, val, sep)) { 00378 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00379 break; 00380 } else 00381 total++; 00382 } else 00383 break; 00384 } 00385 00386 for (i = 0; cdr_readonly_vars[i]; i++) { 00387 ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0); 00388 if (!tmp) 00389 continue; 00390 00391 if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep)) { 00392 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00393 break; 00394 } else 00395 total++; 00396 } 00397 } 00398 00399 return total; 00400 }
int ast_cdr_setaccount | ( | struct ast_channel * | chan, | |
const char * | account | |||
) |
Definition at line 821 of file cdr.c.
References accountcode, ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_string_field_set, ast_test_flag, ast_channel::cdr, and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), auth_exec(), and cdr_write().
00822 { 00823 struct ast_cdr *cdr = chan->cdr; 00824 00825 ast_string_field_set(chan, accountcode, account); 00826 for ( ; cdr ; cdr = cdr->next) { 00827 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00828 ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode)); 00829 } 00830 } 00831 return 0; 00832 }
int ast_cdr_setamaflags | ( | struct ast_channel * | chan, | |
const char * | flag | |||
) |
Definition at line 834 of file cdr.c.
References ast_cdr::amaflags, ast_cdr_amaflags2int(), ast_channel::cdr, and ast_cdr::next.
Referenced by cdr_write(), and pbx_builtin_setamaflags().
00835 { 00836 struct ast_cdr *cdr; 00837 int newflag = ast_cdr_amaflags2int(flag); 00838 if (newflag) { 00839 for (cdr = chan->cdr; cdr; cdr = cdr->next) 00840 cdr->amaflags = newflag; 00841 } 00842 00843 return 0; 00844 }
void ast_cdr_setapp | ( | struct ast_cdr * | cdr, | |
char * | app, | |||
char * | data | |||
) |
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 707 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), builtin_blindtransfer(), clear_caller(), findmeexec(), and pbx_exec().
00708 { 00709 00710 for (; cdr; cdr = cdr->next) { 00711 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00712 check_post(cdr); 00713 if (!app) 00714 app = ""; 00715 ast_copy_string(cdr->lastapp, app, sizeof(cdr->lastapp)); 00716 if (!data) 00717 data = ""; 00718 ast_copy_string(cdr->lastdata, data, sizeof(cdr->lastdata)); 00719 } 00720 } 00721 }
int ast_cdr_setcid | ( | struct ast_cdr * | cdr, | |
struct ast_channel * | chan | |||
) |
cdr | Call Detail Record to use for channel | |
chan | Channel to bind CDR with Initializes a CDR and associates it with a particular channel Return is negligible. (returns 0 by default) |
Definition at line 743 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_cdr::next, and set_one_cid().
Referenced by ast_set_callerid().
00744 { 00745 for (; cdr; cdr = cdr->next) { 00746 if (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00747 set_one_cid(cdr, c); 00748 } 00749 return 0; 00750 }
void ast_cdr_setdestchan | ( | struct ast_cdr * | cdr, | |
const char * | chan | |||
) |
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 698 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::dstchannel, and ast_cdr::next.
Referenced by ast_bridge_call(), ast_bridge_call_thread(), builtin_blindtransfer(), park_exec(), and try_calling().
00699 { 00700 for (; cdr; cdr = cdr->next) { 00701 check_post(cdr); 00702 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00703 ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel)); 00704 } 00705 }
int ast_cdr_setuserfield | ( | struct ast_channel * | chan, | |
const char * | userfield | |||
) |
Definition at line 846 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, ast_cdr::next, and ast_cdr::userfield.
Referenced by __agent_start_monitoring(), action_setcdruserfield(), ast_bridge_call(), cdr_write(), handle_request_info(), setcdruserfield_exec(), and start_monitor_exec().
00847 { 00848 struct ast_cdr *cdr = chan->cdr; 00849 00850 for ( ; cdr ; cdr = cdr->next) { 00851 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00852 ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield)); 00853 } 00854 00855 return 0; 00856 }
int ast_cdr_setvar | ( | struct ast_cdr * | cdr, | |
const char * | name, | |||
const char * | value, | |||
int | recur | |||
) |
Set a CDR channel variable
Definition at line 291 of file cdr.c.
References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_var_assign(), ast_var_delete(), ast_var_name(), cdr_readonly_vars, LOG_ERROR, ast_cdr::next, and ast_cdr::varshead.
Referenced by cdr_write().
00292 { 00293 struct ast_var_t *newvariable; 00294 struct varshead *headp; 00295 int x; 00296 00297 if (!cdr) /* don't die if the cdr is null */ 00298 return -1; 00299 00300 for(x = 0; cdr_readonly_vars[x]; x++) { 00301 if (!strcasecmp(name, cdr_readonly_vars[x])) { 00302 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name); 00303 return -1; 00304 } 00305 } 00306 00307 if (!cdr) { 00308 ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n"); 00309 return -1; 00310 } 00311 00312 for (; cdr; cdr = recur ? cdr->next : NULL) { 00313 headp = &cdr->varshead; 00314 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 00315 if (!strcasecmp(ast_var_name(newvariable), name)) { 00316 /* there is already such a variable, delete it */ 00317 AST_LIST_REMOVE_CURRENT(headp, entries); 00318 ast_var_delete(newvariable); 00319 break; 00320 } 00321 } 00322 AST_LIST_TRAVERSE_SAFE_END; 00323 00324 if (value) { 00325 newvariable = ast_var_assign(name, value); 00326 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 00327 } 00328 } 00329 00330 return 0; 00331 }
void ast_cdr_start | ( | struct ast_cdr * | cdr | ) |
cdr | the cdr you wish to associate with the call Starts all CDR stuff necessary for monitoring a call Returns nothing |
Definition at line 624 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_cdr::channel, check_post(), check_start(), ast_cdr::next, and S_OR.
Referenced by __ast_pbx_run(), __ast_read(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_reset(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), builtin_blindtransfer(), clear_caller(), and findmeexec().
00625 { 00626 char *chan; 00627 00628 for (; cdr; cdr = cdr->next) { 00629 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00630 chan = S_OR(cdr->channel, "<unknown>"); 00631 check_post(cdr); 00632 check_start(cdr); 00633 cdr->start = ast_tvnow(); 00634 } 00635 } 00636 }
void ast_cdr_submit_batch | ( | int | shutdown | ) |
shutdown | Whether or not we are shutting down Blocks the asterisk shutdown procedures until the CDR data is submitted. Returns nothing |
Definition at line 1020 of file cdr.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, batch, batchscheduleronly, do_batch_backend_process(), ast_cdr_batch::head, LOG_DEBUG, LOG_WARNING, option_debug, and reset_batch().
Referenced by ast_cdr_engine_term(), and submit_scheduled_batch().
01021 { 01022 struct ast_cdr_batch_item *oldbatchitems = NULL; 01023 pthread_attr_t attr; 01024 pthread_t batch_post_thread = AST_PTHREADT_NULL; 01025 01026 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */ 01027 if (!batch || !batch->head) 01028 return; 01029 01030 /* move the old CDRs aside, and prepare a new CDR batch */ 01031 ast_mutex_lock(&cdr_batch_lock); 01032 oldbatchitems = batch->head; 01033 reset_batch(); 01034 ast_mutex_unlock(&cdr_batch_lock); 01035 01036 /* if configured, spawn a new thread to post these CDRs, 01037 also try to save as much as possible if we are shutting down safely */ 01038 if (batchscheduleronly || shutdown) { 01039 if (option_debug) 01040 ast_log(LOG_DEBUG, "CDR single-threaded batch processing begins now\n"); 01041 do_batch_backend_process(oldbatchitems); 01042 } else { 01043 pthread_attr_init(&attr); 01044 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01045 if (ast_pthread_create_background(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) { 01046 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n"); 01047 do_batch_backend_process(oldbatchitems); 01048 } else { 01049 if (option_debug) 01050 ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n"); 01051 } 01052 pthread_attr_destroy(&attr); 01053 } 01054 }
void ast_cdr_unregister | ( | const char * | name | ) |
unregister a CDR driver
Definition at line 146 of file cdr.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), free, ast_cdr_beitem::name, option_verbose, and VERBOSE_PREFIX_2.
Referenced by my_unload_module(), odbc_unload_module(), tds_unload_module(), and unload_module().
00147 { 00148 struct ast_cdr_beitem *i = NULL; 00149 00150 AST_LIST_LOCK(&be_list); 00151 AST_LIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { 00152 if (!strcasecmp(name, i->name)) { 00153 AST_LIST_REMOVE_CURRENT(&be_list, list); 00154 if (option_verbose > 1) 00155 ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s' CDR backend\n", name); 00156 free(i); 00157 break; 00158 } 00159 } 00160 AST_LIST_TRAVERSE_SAFE_END; 00161 AST_LIST_UNLOCK(&be_list); 00162 }
int ast_cdr_update | ( | struct ast_channel * | c | ) |
Definition at line 872 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_check_hangup(), ast_test_flag, ast_channel::cdr, ast_channel::context, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, S_OR, and set_one_cid().
Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), ast_parseable_goto(), cb_events(), clear_caller(), and findmeexec().
00873 { 00874 struct ast_cdr *cdr = c->cdr; 00875 00876 for ( ; cdr ; cdr = cdr->next) { 00877 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00878 set_one_cid(cdr, c); 00879 00880 /* Copy account code et-al */ 00881 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00882 if (!ast_check_hangup(c)) { 00883 /* Destination information */ /* XXX privilege macro* ? */ 00884 ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst)); 00885 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext)); 00886 } 00887 } 00888 } 00889 00890 return 0; 00891 }
static AST_LIST_HEAD_STATIC | ( | be_list | , | |
ast_cdr_beitem | ||||
) | [static] |
AST_MUTEX_DEFINE_STATIC | ( | cdr_pending_lock | ) |
AST_MUTEX_DEFINE_STATIC | ( | cdr_batch_lock | ) |
static void cdr_get_tv | ( | struct timeval | tv, | |
const char * | fmt, | |||
char * | buf, | |||
int | bufsize | |||
) | [static] |
Definition at line 203 of file cdr.c.
References t.
Referenced by ast_cdr_getvar().
00204 { 00205 if (fmt == NULL) { /* raw mode */ 00206 snprintf(buf, bufsize, "%ld.%06ld", (long)tv.tv_sec, (long)tv.tv_usec); 00207 } else { 00208 time_t t = tv.tv_sec; 00209 if (t) { 00210 struct tm tm; 00211 localtime_r(&t, &tm); 00212 strftime(buf, bufsize, fmt, &tm); 00213 } 00214 } 00215 }
Definition at line 472 of file cdr.c.
References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_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().
00473 { 00474 struct ast_var_t *variablesfrom,*variablesto; 00475 struct varshead *headpfrom = &to->varshead; 00476 struct varshead *headpto = &from->varshead; 00477 AST_LIST_TRAVERSE_SAFE_BEGIN(headpfrom, variablesfrom, entries) { 00478 /* for every var in from, stick it in to */ 00479 const char *fromvarname, *fromvarval; 00480 const char *tovarname, *tovarval; 00481 fromvarname = ast_var_name(variablesfrom); 00482 fromvarval = ast_var_value(variablesfrom); 00483 tovarname = 0; 00484 00485 /* now, quick see if that var is in the 'to' cdr already */ 00486 AST_LIST_TRAVERSE(headpto, variablesto, entries) { 00487 00488 /* now, quick see if that var is in the 'to' cdr already */ 00489 if ( strcasecmp(fromvarname, ast_var_name(variablesto)) == 0 ) { 00490 tovarname = ast_var_name(variablesto); 00491 tovarval = ast_var_value(variablesto); 00492 break; 00493 } 00494 } 00495 if (tovarname && strcasecmp(fromvarval,tovarval) != 0) { /* this message here to see how irritating the userbase finds it */ 00496 ast_log(LOG_NOTICE, "Merging CDR's: variable %s value %s dropped in favor of value %s\n", tovarname, fromvarval, tovarval); 00497 continue; 00498 } else if (tovarname && strcasecmp(fromvarval,tovarval) == 0) /* if they are the same, the job is done */ 00499 continue; 00500 00501 /*rip this var out of the from cdr, and stick it in the to cdr */ 00502 AST_LIST_REMOVE_CURRENT(headpfrom, entries); 00503 AST_LIST_INSERT_HEAD(headpto, variablesfrom, entries); 00504 } 00505 AST_LIST_TRAVERSE_SAFE_END; 00506 }
static void check_post | ( | struct ast_cdr * | cdr | ) | [static] |
print a warning if cdr already posted
Definition at line 416 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_setapp(), ast_cdr_setdestchan(), ast_cdr_start(), and post_cdr().
00417 { 00418 if (!cdr) 00419 return; 00420 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00421 ast_log(LOG_NOTICE, "CDR on channel '%s' already posted\n", S_OR(cdr->channel, "<unknown>")); 00422 }
static void check_start | ( | struct ast_cdr * | cdr | ) | [static] |
print a warning if cdr already started
Definition at line 425 of file cdr.c.
References ast_log(), ast_cdr::channel, LOG_NOTICE, S_OR, and ast_cdr::start.
Referenced by ast_cdr_start().
00426 { 00427 if (!cdr) 00428 return; 00429 if (!ast_tvzero(cdr->start)) 00430 ast_log(LOG_NOTICE, "CDR on channel '%s' already started\n", S_OR(cdr->channel, "<unknown>")); 00431 }
static void* do_batch_backend_process | ( | void * | data | ) | [static] |
Definition at line 1003 of file cdr.c.
References ast_cdr_free(), ast_cdr_batch_item::cdr, free, ast_cdr_batch_item::next, and post_cdr().
Referenced by ast_cdr_submit_batch().
01004 { 01005 struct ast_cdr_batch_item *processeditem; 01006 struct ast_cdr_batch_item *batchitem = data; 01007 01008 /* Push each CDR into storage mechanism(s) and free all the memory */ 01009 while (batchitem) { 01010 post_cdr(batchitem->cdr); 01011 ast_cdr_free(batchitem->cdr); 01012 processeditem = batchitem; 01013 batchitem = batchitem->next; 01014 free(processeditem); 01015 } 01016 01017 return NULL; 01018 }
static void* do_cdr | ( | void * | data | ) | [static] |
Definition at line 1134 of file cdr.c.
References ast_cond_timedwait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), cdr_pending_cond, LOG_DEBUG, and option_debug.
Referenced by do_reload().
01135 { 01136 struct timespec timeout; 01137 int schedms; 01138 int numevents = 0; 01139 01140 for(;;) { 01141 struct timeval now; 01142 schedms = ast_sched_wait(sched); 01143 /* this shouldn't happen, but provide a 1 second default just in case */ 01144 if (schedms <= 0) 01145 schedms = 1000; 01146 now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000)); 01147 timeout.tv_sec = now.tv_sec; 01148 timeout.tv_nsec = now.tv_usec * 1000; 01149 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */ 01150 ast_mutex_lock(&cdr_pending_lock); 01151 ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout); 01152 numevents = ast_sched_runq(sched); 01153 ast_mutex_unlock(&cdr_pending_lock); 01154 if (option_debug > 1) 01155 ast_log(LOG_DEBUG, "Processed %d scheduled CDR batches from the run queue\n", numevents); 01156 } 01157 01158 return NULL; 01159 }
static int do_reload | ( | void | ) | [static] |
Definition at line 1220 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_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN, 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_pending_cond, cdr_sched, cdr_thread, cli_submit, config, do_cdr(), enabled, LOG_ERROR, LOG_NOTICE, LOG_WARNING, and submit_scheduled_batch().
Referenced by ast_cdr_engine_init(), ast_cdr_engine_reload(), dnsmgr_init(), dnsmgr_reload(), and handle_cli_reload().
01221 { 01222 struct ast_config *config; 01223 const char *enabled_value; 01224 const char *batched_value; 01225 const char *scheduleronly_value; 01226 const char *batchsafeshutdown_value; 01227 const char *size_value; 01228 const char *time_value; 01229 const char *end_before_h_value; 01230 int cfg_size; 01231 int cfg_time; 01232 int was_enabled; 01233 int was_batchmode; 01234 int res=0; 01235 01236 ast_mutex_lock(&cdr_batch_lock); 01237 01238 batchsize = BATCH_SIZE_DEFAULT; 01239 batchtime = BATCH_TIME_DEFAULT; 01240 batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT; 01241 batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT; 01242 was_enabled = enabled; 01243 was_batchmode = batchmode; 01244 enabled = 1; 01245 batchmode = 0; 01246 01247 /* don't run the next scheduled CDR posting while reloading */ 01248 if (cdr_sched > -1) 01249 ast_sched_del(sched, cdr_sched); 01250 01251 if ((config = ast_config_load("cdr.conf"))) { 01252 if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { 01253 enabled = ast_true(enabled_value); 01254 } 01255 if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) { 01256 batchmode = ast_true(batched_value); 01257 } 01258 if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) { 01259 batchscheduleronly = ast_true(scheduleronly_value); 01260 } 01261 if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) { 01262 batchsafeshutdown = ast_true(batchsafeshutdown_value); 01263 } 01264 if ((size_value = ast_variable_retrieve(config, "general", "size"))) { 01265 if (sscanf(size_value, "%d", &cfg_size) < 1) 01266 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value); 01267 else if (size_value < 0) 01268 ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size); 01269 else 01270 batchsize = cfg_size; 01271 } 01272 if ((time_value = ast_variable_retrieve(config, "general", "time"))) { 01273 if (sscanf(time_value, "%d", &cfg_time) < 1) 01274 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value); 01275 else if (time_value < 0) 01276 ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time); 01277 else 01278 batchtime = cfg_time; 01279 } 01280 if ((end_before_h_value = ast_variable_retrieve(config, "general", "endbeforehexten"))) 01281 ast_set2_flag(&ast_options, ast_true(end_before_h_value), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN); 01282 } 01283 01284 if (enabled && !batchmode) { 01285 ast_log(LOG_NOTICE, "CDR simple logging enabled.\n"); 01286 } else if (enabled && batchmode) { 01287 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); 01288 ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime); 01289 } else { 01290 ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n"); 01291 } 01292 01293 /* if this reload enabled the CDR batch mode, create the background thread 01294 if it does not exist */ 01295 if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) { 01296 ast_cond_init(&cdr_pending_cond, NULL); 01297 if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) { 01298 ast_log(LOG_ERROR, "Unable to start CDR thread.\n"); 01299 ast_sched_del(sched, cdr_sched); 01300 } else { 01301 ast_cli_register(&cli_submit); 01302 ast_register_atexit(ast_cdr_engine_term); 01303 res = 0; 01304 } 01305 /* if this reload disabled the CDR and/or batch mode and there is a background thread, 01306 kill it */ 01307 } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) { 01308 /* wake up the thread so it will exit */ 01309 pthread_cancel(cdr_thread); 01310 pthread_kill(cdr_thread, SIGURG); 01311 pthread_join(cdr_thread, NULL); 01312 cdr_thread = AST_PTHREADT_NULL; 01313 ast_cond_destroy(&cdr_pending_cond); 01314 ast_cli_unregister(&cli_submit); 01315 ast_unregister_atexit(ast_cdr_engine_term); 01316 res = 0; 01317 /* if leaving batch mode, then post the CDRs in the batch, 01318 and don't reschedule, since we are stopping CDR logging */ 01319 if (!batchmode && was_batchmode) { 01320 ast_cdr_engine_term(); 01321 } 01322 } else { 01323 res = 0; 01324 } 01325 01326 ast_mutex_unlock(&cdr_batch_lock); 01327 ast_config_destroy(config); 01328 01329 return res; 01330 }
static int handle_cli_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1161 of file cdr.c.
References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_sched_when(), batch, batchmode, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_sched, enabled, ast_cdr_beitem::name, and RESULT_SHOWUSAGE.
01162 { 01163 struct ast_cdr_beitem *beitem=NULL; 01164 int cnt=0; 01165 long nextbatchtime=0; 01166 01167 if (argc > 2) 01168 return RESULT_SHOWUSAGE; 01169 01170 ast_cli(fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled"); 01171 ast_cli(fd, "CDR mode: %s\n", batchmode ? "batch" : "simple"); 01172 if (enabled) { 01173 if (batchmode) { 01174 if (batch) 01175 cnt = batch->size; 01176 if (cdr_sched > -1) 01177 nextbatchtime = ast_sched_when(sched, cdr_sched); 01178 ast_cli(fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled"); 01179 ast_cli(fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads"); 01180 ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, (cnt != 1) ? "s" : ""); 01181 ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, (batchsize != 1) ? "s" : ""); 01182 ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, (batchtime != 1) ? "s" : ""); 01183 ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, (nextbatchtime != 1) ? "s" : ""); 01184 } 01185 AST_LIST_LOCK(&be_list); 01186 AST_LIST_TRAVERSE(&be_list, beitem, list) { 01187 ast_cli(fd, "CDR registered backend: %s\n", beitem->name); 01188 } 01189 AST_LIST_UNLOCK(&be_list); 01190 } 01191 01192 return 0; 01193 }
static int handle_cli_submit | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1195 of file cdr.c.
References ast_cli(), RESULT_SHOWUSAGE, and submit_unscheduled_batch().
01196 { 01197 if (argc > 2) 01198 return RESULT_SHOWUSAGE; 01199 01200 submit_unscheduled_batch(); 01201 ast_cli(fd, "Submitted CDRs to backend engines for processing. This may take a while.\n"); 01202 01203 return 0; 01204 }
static int init_batch | ( | void | ) | [static] |
Definition at line 992 of file cdr.c.
References ast_malloc, batch, and reset_batch().
Referenced by ast_cdr_detach(), and ast_cdr_engine_init().
00993 { 00994 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */ 00995 if (!(batch = ast_malloc(sizeof(*batch)))) 00996 return -1; 00997 00998 reset_batch(); 00999 01000 return 0; 01001 }
static void post_cdr | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 906 of file cdr.c.
References AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_set_flag, ast_test_flag, ast_cdr_beitem::be, ast_cdr::channel, check_post(), ast_cdr::end, LOG_WARNING, ast_cdr::next, S_OR, and ast_cdr::start.
Referenced by ast_cdr_detach(), and do_batch_backend_process().
00907 { 00908 char *chan; 00909 struct ast_cdr_beitem *i; 00910 00911 for ( ; cdr ; cdr = cdr->next) { 00912 chan = S_OR(cdr->channel, "<unknown>"); 00913 check_post(cdr); 00914 if (ast_tvzero(cdr->end)) 00915 ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan); 00916 if (ast_tvzero(cdr->start)) 00917 ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan); 00918 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 00919 if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) 00920 continue; 00921 AST_LIST_LOCK(&be_list); 00922 AST_LIST_TRAVERSE(&be_list, i, list) { 00923 i->be(cdr); 00924 } 00925 AST_LIST_UNLOCK(&be_list); 00926 } 00927 }
static void reset_batch | ( | void | ) | [static] |
Definition at line 984 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 724 of file cdr.c.
References ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, S_OR, and ast_cdr::src.
Referenced by ast_cdr_init(), ast_cdr_setcid(), and ast_cdr_update().
00725 { 00726 /* Grab source from ANI or normal Caller*ID */ 00727 const char *num = S_OR(c->cid.cid_ani, c->cid.cid_num); 00728 if (!cdr) 00729 return; 00730 if (!ast_strlen_zero(c->cid.cid_name)) { 00731 if (!ast_strlen_zero(num)) /* both name and number */ 00732 snprintf(cdr->clid, sizeof(cdr->clid), "\"%s\" <%s>", c->cid.cid_name, num); 00733 else /* only name */ 00734 ast_copy_string(cdr->clid, c->cid.cid_name, sizeof(cdr->clid)); 00735 } else if (!ast_strlen_zero(num)) { /* only number */ 00736 ast_copy_string(cdr->clid, num, sizeof(cdr->clid)); 00737 } else { /* nothing known */ 00738 cdr->clid[0] = '\0'; 00739 } 00740 ast_copy_string(cdr->src, S_OR(num, ""), sizeof(cdr->src)); 00741 00742 }
static int submit_scheduled_batch | ( | void * | data | ) | [static] |
Definition at line 1056 of file cdr.c.
References ast_cdr_submit_batch(), ast_sched_add(), batchtime, and cdr_sched.
Referenced by do_reload(), and submit_unscheduled_batch().
01057 { 01058 ast_cdr_submit_batch(0); 01059 /* manually reschedule from this point in time */ 01060 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); 01061 /* returning zero so the scheduler does not automatically reschedule */ 01062 return 0; 01063 }
static void submit_unscheduled_batch | ( | void | ) | [static] |
Definition at line 1065 of file cdr.c.
References ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), cdr_pending_cond, cdr_sched, and submit_scheduled_batch().
Referenced by ast_cdr_detach(), and handle_cli_submit().
01066 { 01067 /* this is okay since we are not being called from within the scheduler */ 01068 if (cdr_sched > -1) 01069 ast_sched_del(sched, cdr_sched); 01070 /* schedule the submission to occur ASAP (1 ms) */ 01071 cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL); 01072 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */ 01073 ast_mutex_lock(&cdr_pending_lock); 01074 ast_cond_signal(&cdr_pending_cond); 01075 ast_mutex_unlock(&cdr_pending_lock); 01076 }
char ast_default_accountcode[AST_MAX_ACCOUNT_CODE] |
int ast_default_amaflags = AST_CDR_DOCUMENTATION |
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] |
Is the CDR subsystem enabled ?
Definition at line 92 of file cdr.c.
Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().
int batchsafeshutdown [static] |
Definition at line 96 of file cdr.c.
Referenced by ast_cdr_engine_term(), do_reload(), and handle_cli_status().
int batchscheduleronly [static] |
Definition at line 95 of file cdr.c.
Referenced by ast_cdr_submit_batch(), do_reload(), and handle_cli_status().
int batchsize [static] |
Definition at line 93 of file cdr.c.
Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().
int batchtime [static] |
Definition at line 94 of file cdr.c.
Referenced by do_reload(), handle_cli_status(), and submit_scheduled_batch().
ast_cond_t cdr_pending_cond [static] |
Definition at line 102 of file cdr.c.
Referenced by do_cdr(), do_reload(), and submit_unscheduled_batch().
const char* cdr_readonly_vars[] [static] |
Initial value:
{ "clid", "src", "dst", "dcontext", "channel", "dstchannel", "lastapp", "lastdata", "start", "answer", "end", "duration", "billsec", "disposition", "amaflags", "accountcode", "uniqueid", "userfield", NULL }
Definition at line 284 of file cdr.c.
Referenced by ast_cdr_serialize_variables(), and ast_cdr_setvar().
int cdr_sched = -1 [static] |
Definition at line 83 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 [static] |
struct ast_cli_entry cli_submit [static] |
int enabled [static] |
Definition at line 91 of file cdr.c.
Referenced by __ast_http_load(), ast_cdr_detach(), ast_dnsmgr_lookup(), do_reload(), handle_cli_status(), init_manager(), load_odbc_config(), osp_check_destination(), and reload().
struct sched_context* sched [static] |
Definition at line 82 of file cdr.c.
Referenced by __attempt_transmit(), __iax2_poke_noanswer(), __oh323_destroy(), __oh323_rtp_create(), __oh323_update_info(), __send_lagrq(), __send_ping(), __sip_ack(), __sip_destroy(), __sip_reliable_xmit(), __sip_semi_ack(), __unload_module(), _sip_show_peer(), ast_rtp_new(), ast_rtp_new_with_bindaddr(), ast_udptl_new(), ast_udptl_new_with_bindaddr(), auth_fail(), build_peer(), delete_users(), destroy_peer(), dnsmgr_init(), dnsmgr_start_refresh(), do_refresh(), do_reload(), find_callno(), handle_response_invite(), handle_response_peerpoke(), handle_response_register(), iax2_ack_registry(), iax2_call(), iax2_destroy_helper(), iax2_do_register(), iax2_dprequest(), iax2_frame_free(), iax2_poke_peer(), iax2_provision(), load_module(), make_trunk(), network_thread(), parse_register_contact(), reg_source_db(), sched_thread(), schedule_delivery(), sip_alloc(), sip_call(), sip_cancel_destroy(), sip_destroy_peer(), sip_poke_all_peers(), sip_poke_noanswer(), sip_poke_peer(), sip_registry_destroy(), sip_scheddestroy(), sip_send_all_registers(), socket_process(), transmit_register(), unload_module(), update_jbsched(), and update_registry().