#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include "asterisk.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/module.h"
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) |
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) |
void | 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) |
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_register (char *name, 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, 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 (char *name) |
int | ast_cdr_update (struct ast_channel *c) |
AST_LIST_HEAD_STATIC (be_list, ast_cdr_beitem) | |
AST_MUTEX_DEFINE_STATIC (cdr_pending_lock) | |
AST_MUTEX_DEFINE_STATIC (cdr_batch_lock) | |
void * | do_batch_backend_process (void *data) |
void * | do_cdr (void *data) |
int | do_reload (void) |
int | handle_cli_status (int fd, int argc, char *argv[]) |
int | handle_cli_submit (int fd, int argc, char *argv[]) |
int | init_batch (void) |
void | post_cdr (struct ast_cdr *cdr) |
void | reset_batch (void) |
int | submit_scheduled_batch (void *data) |
void | submit_unscheduled_batch (void) |
Variables | |
char | ast_default_accountcode [AST_MAX_ACCOUNT_CODE] = "" |
int | ast_default_amaflags = AST_CDR_DOCUMENTATION |
ast_cdr_batch * | batch |
int | batchmode |
int | batchsafeshutdown |
int | batchscheduleronly |
int | batchsize |
int | batchtime |
ast_cond_t | cdr_pending_cond |
int | cdr_sched = -1 |
pthread_t | cdr_thread = AST_PTHREADT_NULL |
ast_cli_entry | cli_status |
ast_cli_entry | cli_submit |
int | enabled |
sched_context * | sched |
Includes code and algorithms from the Zapata library.
Definition in file cdr.c.
|
|
|
|
|
|
|
|
|
Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
Definition at line 455 of file cdr.c. References malloc. Referenced by __agent_start_monitoring(), __ast_pbx_run(), __ast_request_and_dial(), ast_cdr_dup(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), and start_monitor_exec(). 00456 { 00457 struct ast_cdr *cdr; 00458 00459 cdr = malloc(sizeof(*cdr)); 00460 if (cdr) 00461 memset(cdr, 0, sizeof(*cdr)); 00462 00463 return cdr; 00464 }
|
|
Definition at line 786 of file cdr.c. Referenced by ast_cdr_setamaflags(), build_device(), build_gateway(), build_peer(), build_user(), set_config(), and setup_zap(). 00787 { 00788 if (!strcasecmp(flag, "default")) 00789 return 0; 00790 if (!strcasecmp(flag, "omit")) 00791 return AST_CDR_OMIT; 00792 if (!strcasecmp(flag, "billing")) 00793 return AST_CDR_BILLING; 00794 if (!strcasecmp(flag, "documentation")) 00795 return AST_CDR_DOCUMENTATION; 00796 return -1; 00797 }
|
|
Definition at line 483 of file cdr.c. References ast_cdr::answer, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::next. Referenced by ast_answer(), and ast_read(). 00484 { 00485 char *chan; 00486 00487 while (cdr) { 00488 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00489 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00490 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00491 if (cdr->disposition < AST_CDR_ANSWERED) 00492 cdr->disposition = AST_CDR_ANSWERED; 00493 if (ast_tvzero(cdr->answer)) 00494 cdr->answer = ast_tvnow(); 00495 cdr = cdr->next; 00496 } 00497 }
|
|
Definition at line 866 of file cdr.c. References ast_cdr::next. Referenced by ast_cdr_fork(), and attempt_transfer(). 00867 { 00868 struct ast_cdr *ret; 00869 00870 if (cdr) { 00871 ret = cdr; 00872 00873 while (cdr->next) 00874 cdr = cdr->next; 00875 cdr->next = newcdr; 00876 } else { 00877 ret = newcdr; 00878 } 00879 00880 return ret; 00881 }
|
|
Definition at line 739 of file cdr.c. References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, ast_cdr::next, and ast_cdr::userfield. Referenced by action_setcdruserfield(), appendcdruserfield_exec(), and ast_bridge_call(). 00740 { 00741 struct ast_cdr *cdr = chan->cdr; 00742 00743 while (cdr) { 00744 int len = strlen(cdr->userfield); 00745 00746 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00747 strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1); 00748 00749 cdr = cdr->next; 00750 } 00751 00752 return 0; 00753 }
|
|
Definition at line 499 of file cdr.c. References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::next. Referenced by ast_cdr_disposition(), ring_entry(), and wait_for_answer(). 00500 { 00501 char *chan; 00502 00503 while (cdr) { 00504 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00505 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00506 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00507 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00508 if (cdr->disposition < AST_CDR_BUSY) 00509 cdr->disposition = AST_CDR_BUSY; 00510 } 00511 cdr = cdr->next; 00512 } 00513 }
|
|
Definition at line 326 of file cdr.c. References AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_assign(), ast_var_name(), ast_var_value(), val, var, and ast_cdr::varshead. Referenced by ast_cdr_dup(). 00327 { 00328 struct ast_var_t *variables, *newvariable = NULL; 00329 struct varshead *headpa, *headpb; 00330 char *var, *val; 00331 int x = 0; 00332 00333 headpa = &from_cdr->varshead; 00334 headpb = &to_cdr->varshead; 00335 00336 AST_LIST_TRAVERSE(headpa,variables,entries) { 00337 if (variables && 00338 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00339 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00340 newvariable = ast_var_assign(var, val); 00341 AST_LIST_INSERT_HEAD(headpb, newvariable, entries); 00342 x++; 00343 } 00344 } 00345 00346 return x; 00347 }
|
|
Definition at line 980 of file cdr.c. References AST_CDR_FLAG_POST_DISABLED, ast_cdr_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, batch, batchsize, ast_cdr_batch_item::cdr, ast_cdr_batch::head, init_batch(), LOG_DEBUG, LOG_WARNING, malloc, ast_cdr_batch_item::next, 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(). 00981 { 00982 struct ast_cdr_batch_item *newtail; 00983 int curr; 00984 00985 /* maybe they disabled CDR stuff completely, so just drop it */ 00986 if (!enabled) { 00987 if (option_debug) 00988 ast_log(LOG_DEBUG, "Dropping CDR !\n"); 00989 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 00990 ast_cdr_free(cdr); 00991 return; 00992 } 00993 00994 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */ 00995 if (!batchmode) { 00996 post_cdr(cdr); 00997 ast_cdr_free(cdr); 00998 return; 00999 } 01000 01001 /* otherwise, each CDR gets put into a batch list (at the end) */ 01002 if (option_debug) 01003 ast_log(LOG_DEBUG, "CDR detaching from this thread\n"); 01004 01005 /* we'll need a new tail for every CDR */ 01006 newtail = malloc(sizeof(*newtail)); 01007 if (!newtail) { 01008 ast_log(LOG_WARNING, "CDR: out of memory while trying to detach, will try in this thread instead\n"); 01009 post_cdr(cdr); 01010 ast_cdr_free(cdr); 01011 return; 01012 } 01013 memset(newtail, 0, sizeof(*newtail)); 01014 01015 /* don't traverse a whole list (just keep track of the tail) */ 01016 ast_mutex_lock(&cdr_batch_lock); 01017 if (!batch) 01018 init_batch(); 01019 if (!batch->head) { 01020 /* new batch is empty, so point the head at the new tail */ 01021 batch->head = newtail; 01022 } else { 01023 /* already got a batch with something in it, so just append a new tail */ 01024 batch->tail->next = newtail; 01025 } 01026 newtail->cdr = cdr; 01027 batch->tail = newtail; 01028 curr = batch->size++; 01029 ast_mutex_unlock(&cdr_batch_lock); 01030 01031 /* if we have enough stuff to post, then do it */ 01032 if (curr >= (batchsize - 1)) 01033 submit_unscheduled_batch(); 01034 }
|
|
Definition at line 669 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(), csv_log(), manager_log(), odbc_log(), pgsql_log(), and tds_log(). 00670 { 00671 switch (disposition) { 00672 case AST_CDR_NOANSWER: 00673 return "NO ANSWER"; 00674 case AST_CDR_FAILED: 00675 return "FAILED"; 00676 case AST_CDR_BUSY: 00677 return "BUSY"; 00678 case AST_CDR_ANSWERED: 00679 return "ANSWERED"; 00680 } 00681 return "UNKNOWN"; 00682 }
|
|
Definition at line 529 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(), and ast_pbx_outgoing_exten(). 00530 { 00531 int res = 0; 00532 00533 while (cdr) { 00534 switch(cause) { 00535 case AST_CAUSE_BUSY: 00536 ast_cdr_busy(cdr); 00537 break; 00538 case AST_CAUSE_FAILURE: 00539 ast_cdr_failed(cdr); 00540 break; 00541 case AST_CAUSE_NORMAL: 00542 break; 00543 case AST_CAUSE_NOTDEFINED: 00544 res = -1; 00545 break; 00546 default: 00547 res = -1; 00548 ast_log(LOG_WARNING, "Cause not handled\n"); 00549 } 00550 cdr = cdr->next; 00551 } 00552 return res; 00553 }
|
|
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(), ast_cdr_copy_vars(), ast_log(), LOG_ERROR, and ast_cdr::next. Referenced by ast_cdr_fork(), and ast_cdr_reset(). 00168 { 00169 struct ast_cdr *newcdr; 00170 00171 if (!(newcdr = ast_cdr_alloc())) { 00172 ast_log(LOG_ERROR, "Memory Error!\n"); 00173 return NULL; 00174 } 00175 00176 memcpy(newcdr, cdr, sizeof(*newcdr)); 00177 /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */ 00178 memset(&newcdr->varshead, 0, sizeof(newcdr->varshead)); 00179 ast_cdr_copy_vars(newcdr, cdr); 00180 newcdr->next = NULL; 00181 00182 return newcdr; 00183 }
|
|
Definition at line 653 of file cdr.c. References AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::end, LOG_WARNING, ast_cdr::next, and ast_cdr::start. Referenced by __ast_request_and_dial(), ast_cdr_reset(), ast_feature_request_and_dial(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), and ast_read(). 00654 { 00655 char *chan; 00656 00657 while (cdr) { 00658 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00659 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00660 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00661 if (ast_tvzero(cdr->start)) 00662 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", chan); 00663 if (ast_tvzero(cdr->end)) 00664 cdr->end = ast_tvnow(); 00665 cdr = cdr->next; 00666 } 00667 }
|
|
Load the configuration file cdr.conf and possibly start the CDR scheduling thread Definition at line 1234 of file cdr.c. References ast_cli_register(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cli_status, do_reload(), init_batch(), LOG_ERROR, sched, and sched_context_create(). Referenced by main(). 01235 { 01236 int res; 01237 01238 sched = sched_context_create(); 01239 if (!sched) { 01240 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 01241 return -1; 01242 } 01243 01244 ast_cli_register(&cli_status); 01245 01246 res = do_reload(); 01247 if (res) { 01248 ast_mutex_lock(&cdr_batch_lock); 01249 res = init_batch(); 01250 ast_mutex_unlock(&cdr_batch_lock); 01251 } 01252 01253 return res; 01254 }
|
|
Reload the configuration file cdr.conf and start/stop CDR scheduling thread Definition at line 1263 of file cdr.c. References do_reload(). Referenced by ast_module_reload(). 01264 { 01265 do_reload(); 01266 }
|
|
Submit any remaining CDRs and prepare for shutdown Definition at line 1258 of file cdr.c. References ast_cdr_submit_batch(), and batchsafeshutdown. Referenced by do_reload(), and quit_handler(). 01259 { 01260 ast_cdr_submit_batch(batchsafeshutdown); 01261 }
|
|
Definition at line 515 of file cdr.c. References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, 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(), and ast_pbx_outgoing_exten(). 00516 { 00517 char *chan; 00518 00519 while (cdr) { 00520 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00521 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00522 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00523 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00524 cdr->disposition = AST_CDR_FAILED; 00525 cdr = cdr->next; 00526 } 00527 }
|
|
Converts AMA flag to printable string Definition at line 685 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(), csv_log(), manager_log(), sip_show_user(), and tds_log(). 00686 { 00687 switch(flag) { 00688 case AST_CDR_OMIT: 00689 return "OMIT"; 00690 case AST_CDR_BILLING: 00691 return "BILLING"; 00692 case AST_CDR_DOCUMENTATION: 00693 return "DOCUMENTATION"; 00694 } 00695 return "Unknown"; 00696 }
|
|
Free a CDR record.
Definition at line 434 of file cdr.c. References AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::end, free, LOG_WARNING, ast_cdr::next, and ast_cdr::start. Referenced by ast_cdr_detach(), do_batch_backend_process(), and nocdr_exec(). 00435 { 00436 char *chan; 00437 struct ast_cdr *next; 00438 00439 while (cdr) { 00440 next = cdr->next; 00441 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00442 if (!ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) 00443 ast_log(LOG_WARNING, "CDR on channel '%s' not posted\n", chan); 00444 if (ast_tvzero(cdr->end)) 00445 ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan); 00446 if (ast_tvzero(cdr->start)) 00447 ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan); 00448 00449 ast_cdr_free_vars(cdr, 0); 00450 free(cdr); 00451 cdr = next; 00452 } 00453 }
|
|
Definition at line 413 of file cdr.c. References AST_LIST_EMPTY, AST_LIST_REMOVE_HEAD, ast_var_delete(), ast_cdr::next, and ast_cdr::varshead. Referenced by ast_cdr_fork(), ast_cdr_free(), and ast_cdr_reset(). 00414 { 00415 struct varshead *headp; 00416 struct ast_var_t *vardata; 00417 00418 /* clear variables */ 00419 while (cdr) { 00420 headp = &cdr->varshead; 00421 while (!AST_LIST_EMPTY(headp)) { 00422 vardata = AST_LIST_REMOVE_HEAD(headp, entries); 00423 ast_var_delete(vardata); 00424 } 00425 00426 if (!recur) { 00427 break; 00428 } 00429 00430 cdr = cdr->next; 00431 } 00432 }
|
|
CDR channel variable retrieval Definition at line 208 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, 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, name, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield. Referenced by ast_cdr_serialize_variables(), builtin_function_cdr_read(), and pickup_exec(). 00209 { 00210 struct tm tm; 00211 time_t t; 00212 const char *fmt = "%Y-%m-%d %T"; 00213 const char *varbuf; 00214 00215 *ret = NULL; 00216 /* special vars (the ones from the struct ast_cdr when requested by name) 00217 I'd almost say we should convert all the stringed vals to vars */ 00218 00219 if (!strcasecmp(name, "clid")) 00220 ast_copy_string(workspace, cdr->clid, workspacelen); 00221 else if (!strcasecmp(name, "src")) 00222 ast_copy_string(workspace, cdr->src, workspacelen); 00223 else if (!strcasecmp(name, "dst")) 00224 ast_copy_string(workspace, cdr->dst, workspacelen); 00225 else if (!strcasecmp(name, "dcontext")) 00226 ast_copy_string(workspace, cdr->dcontext, workspacelen); 00227 else if (!strcasecmp(name, "channel")) 00228 ast_copy_string(workspace, cdr->channel, workspacelen); 00229 else if (!strcasecmp(name, "dstchannel")) 00230 ast_copy_string(workspace, cdr->dstchannel, workspacelen); 00231 else if (!strcasecmp(name, "lastapp")) 00232 ast_copy_string(workspace, cdr->lastapp, workspacelen); 00233 else if (!strcasecmp(name, "lastdata")) 00234 ast_copy_string(workspace, cdr->lastdata, workspacelen); 00235 else if (!strcasecmp(name, "start")) { 00236 t = cdr->start.tv_sec; 00237 if (t) { 00238 localtime_r(&t, &tm); 00239 strftime(workspace, workspacelen, fmt, &tm); 00240 } 00241 } else if (!strcasecmp(name, "answer")) { 00242 t = cdr->answer.tv_sec; 00243 if (t) { 00244 localtime_r(&t, &tm); 00245 strftime(workspace, workspacelen, fmt, &tm); 00246 } 00247 } else if (!strcasecmp(name, "end")) { 00248 t = cdr->end.tv_sec; 00249 if (t) { 00250 localtime_r(&t, &tm); 00251 strftime(workspace, workspacelen, fmt, &tm); 00252 } 00253 } else if (!strcasecmp(name, "duration")) 00254 snprintf(workspace, workspacelen, "%ld", cdr->duration); 00255 else if (!strcasecmp(name, "billsec")) 00256 snprintf(workspace, workspacelen, "%ld", cdr->billsec); 00257 else if (!strcasecmp(name, "disposition")) 00258 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); 00259 else if (!strcasecmp(name, "amaflags")) 00260 ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); 00261 else if (!strcasecmp(name, "accountcode")) 00262 ast_copy_string(workspace, cdr->accountcode, workspacelen); 00263 else if (!strcasecmp(name, "uniqueid")) 00264 ast_copy_string(workspace, cdr->uniqueid, workspacelen); 00265 else if (!strcasecmp(name, "userfield")) 00266 ast_copy_string(workspace, cdr->userfield, workspacelen); 00267 else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) 00268 ast_copy_string(workspace, varbuf, workspacelen); 00269 00270 if (!ast_strlen_zero(workspace)) 00271 *ret = workspace; 00272 }
|
|
Definition at line 185 of file cdr.c. References AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_name(), ast_var_value(), name, ast_cdr::next, and ast_cdr::varshead. Referenced by ast_cdr_getvar(). 00186 { 00187 struct ast_var_t *variables; 00188 struct varshead *headp; 00189 00190 if (ast_strlen_zero(name)) 00191 return NULL; 00192 00193 while (cdr) { 00194 headp = &cdr->varshead; 00195 AST_LIST_TRAVERSE(headp, variables, entries) { 00196 if (!strcasecmp(name, ast_var_name(variables))) 00197 return ast_var_value(variables); 00198 } 00199 if (!recur) 00200 break; 00201 cdr = cdr->next; 00202 } 00203 00204 return NULL; 00205 }
|
|
Initialize based on a channel.
Definition at line 615 of file cdr.c. References ast_channel::_state, ast_cdr::accountcode, ast_channel::accountcode, ast_cdr::amaflags, ast_channel::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_cdr::next, ast_cdr::src, ast_cdr::uniqueid, and ast_channel::uniqueid. Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), and ast_pbx_outgoing_exten(). 00616 { 00617 char *chan; 00618 char *num; 00619 char tmp[AST_MAX_EXTENSION] = ""; 00620 00621 while (cdr) { 00622 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00623 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00624 if (!ast_strlen_zero(cdr->channel)) 00625 ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan); 00626 ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); 00627 /* Grab source from ANI or normal Caller*ID */ 00628 num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num; 00629 00630 if (c->cid.cid_name && num) 00631 snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num); 00632 else if (c->cid.cid_name) 00633 ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp)); 00634 else if (num) 00635 ast_copy_string(tmp, num, sizeof(tmp)); 00636 ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid)); 00637 ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src)); 00638 00639 cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 00640 cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; 00641 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00642 /* Destination information */ 00643 ast_copy_string(cdr->dst, c->exten, sizeof(cdr->dst)); 00644 ast_copy_string(cdr->dcontext, c->context, sizeof(cdr->dcontext)); 00645 /* Unique call identifier */ 00646 ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid)); 00647 } 00648 cdr = cdr->next; 00649 } 00650 return 0; 00651 }
|
|
Register a CDR driver. Each registered CDR driver generates a CDR
Definition at line 106 of file cdr.c. References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_cdr_beitem::be, LOG_WARNING, malloc, name, and ast_cdr_beitem::name. Referenced by load_module(), odbc_load_module(), process_my_load_module(), and tds_load_module(). 00107 { 00108 struct ast_cdr_beitem *i; 00109 00110 if (!name) 00111 return -1; 00112 if (!be) { 00113 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name); 00114 return -1; 00115 } 00116 00117 AST_LIST_LOCK(&be_list); 00118 AST_LIST_TRAVERSE(&be_list, i, list) { 00119 if (!strcasecmp(name, i->name)) 00120 break; 00121 } 00122 AST_LIST_UNLOCK(&be_list); 00123 00124 if (i) { 00125 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name); 00126 return -1; 00127 } 00128 00129 i = malloc(sizeof(*i)); 00130 if (!i) 00131 return -1; 00132 00133 memset(i, 0, sizeof(*i)); 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 }
|
|
Definition at line 827 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_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_bridge_call_thread(), ast_cdr_fork(), dial_exec_full(), disa_exec(), and pbx_builtin_resetcdr(). 00828 { 00829 struct ast_cdr *dup; 00830 struct ast_flags flags = { 0 }; 00831 00832 if (_flags) 00833 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); 00834 00835 while (cdr) { 00836 /* Detach if post is requested */ 00837 if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00838 if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) { 00839 ast_cdr_end(cdr); 00840 if ((dup = ast_cdr_dup(cdr))) { 00841 ast_cdr_detach(dup); 00842 } 00843 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 00844 } 00845 00846 /* clear variables */ 00847 if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) { 00848 ast_cdr_free_vars(cdr, 0); 00849 } 00850 00851 /* Reset to initial state */ 00852 ast_clear_flag(cdr, AST_FLAGS_ALL); 00853 memset(&cdr->start, 0, sizeof(cdr->start)); 00854 memset(&cdr->end, 0, sizeof(cdr->end)); 00855 memset(&cdr->answer, 0, sizeof(cdr->answer)); 00856 cdr->billsec = 0; 00857 cdr->duration = 0; 00858 ast_cdr_start(cdr); 00859 cdr->disposition = AST_CDR_NOANSWER; 00860 } 00861 00862 cdr = cdr->next; 00863 } 00864 }
|
|
Definition at line 349 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(), LOG_ERROR, ast_cdr::next, val, var, and ast_cdr::varshead. Referenced by handle_showchan(). 00350 { 00351 struct ast_var_t *variables; 00352 char *var, *val; 00353 char *tmp; 00354 char workspace[256]; 00355 int total = 0, x = 0, i; 00356 const char *cdrcols[] = { 00357 "clid", 00358 "src", 00359 "dst", 00360 "dcontext", 00361 "channel", 00362 "dstchannel", 00363 "lastapp", 00364 "lastdata", 00365 "start", 00366 "answer", 00367 "end", 00368 "duration", 00369 "billsec", 00370 "disposition", 00371 "amaflags", 00372 "accountcode", 00373 "uniqueid", 00374 "userfield" 00375 }; 00376 00377 memset(buf, 0, size); 00378 00379 for (; cdr; cdr = recur ? cdr->next : NULL) { 00380 if (++x > 1) 00381 ast_build_string(&buf, &size, "\n"); 00382 00383 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) { 00384 if (variables && 00385 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00386 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00387 if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, var, delim, val, sep)) { 00388 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00389 break; 00390 } else 00391 total++; 00392 } else 00393 break; 00394 } 00395 00396 for (i = 0; i < (sizeof(cdrcols) / sizeof(cdrcols[0])); i++) { 00397 ast_cdr_getvar(cdr, cdrcols[i], &tmp, workspace, sizeof(workspace), 0); 00398 if (!tmp) 00399 continue; 00400 00401 if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, cdrcols[i], delim, tmp, sep)) { 00402 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00403 break; 00404 } else 00405 total++; 00406 } 00407 } 00408 00409 return total; 00410 }
|
|
Definition at line 698 of file cdr.c. References ast_channel::accountcode, ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, 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(), builtin_function_cdr_write(), and pbx_builtin_setaccount(). 00699 { 00700 struct ast_cdr *cdr = chan->cdr; 00701 00702 ast_copy_string(chan->accountcode, account, sizeof(chan->accountcode)); 00703 while (cdr) { 00704 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00705 ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode)); 00706 cdr = cdr->next; 00707 } 00708 return 0; 00709 }
|
|
Definition at line 711 of file cdr.c. References ast_cdr::amaflags, ast_cdr_amaflags2int(), ast_channel::cdr, and ast_cdr::next. Referenced by pbx_builtin_setamaflags(). 00712 { 00713 struct ast_cdr *cdr; 00714 int newflag; 00715 00716 newflag = ast_cdr_amaflags2int(flag); 00717 if (newflag) { 00718 for (cdr = chan->cdr; cdr; cdr = cdr->next) { 00719 cdr->amaflags = newflag; 00720 } 00721 } 00722 00723 return 0; 00724 }
|
|
Definition at line 569 of file cdr.c. References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::lastapp, ast_cdr::lastdata, LOG_WARNING, and ast_cdr::next. Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), and pbx_exec(). 00570 { 00571 char *chan; 00572 00573 while (cdr) { 00574 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00575 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00576 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00577 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00578 if (!app) 00579 app = ""; 00580 ast_copy_string(cdr->lastapp, app, sizeof(cdr->lastapp)); 00581 if (!data) 00582 data = ""; 00583 ast_copy_string(cdr->lastdata, data, sizeof(cdr->lastdata)); 00584 } 00585 cdr = cdr->next; 00586 } 00587 }
|
|
Definition at line 589 of file cdr.c. References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, ast_cdr::next, and ast_cdr::src. Referenced by ast_set_callerid(). 00590 { 00591 char tmp[AST_MAX_EXTENSION] = ""; 00592 char *num; 00593 00594 while (cdr) { 00595 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00596 /* Grab source from ANI or normal Caller*ID */ 00597 num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num; 00598 00599 if (c->cid.cid_name && num) 00600 snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num); 00601 else if (c->cid.cid_name) 00602 ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp)); 00603 else if (num) 00604 ast_copy_string(tmp, num, sizeof(tmp)); 00605 ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid)); 00606 ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src)); 00607 } 00608 cdr = cdr->next; 00609 } 00610 00611 return 0; 00612 }
|
|
Definition at line 555 of file cdr.c. References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::dstchannel, LOG_WARNING, and ast_cdr::next. Referenced by ast_bridge_call_thread(), dial_exec_full(), and try_calling(). 00556 { 00557 char *chan; 00558 00559 while (cdr) { 00560 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00561 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00562 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00563 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00564 ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel)); 00565 cdr = cdr->next; 00566 } 00567 }
|
|
Definition at line 726 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(), builtin_function_cdr_write(), handle_request_info(), setcdruserfield_exec(), and start_monitor_exec(). 00727 { 00728 struct ast_cdr *cdr = chan->cdr; 00729 00730 while (cdr) { 00731 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00732 ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield)); 00733 cdr = cdr->next; 00734 } 00735 00736 return 0; 00737 }
|
|
Set a CDR channel variable
Definition at line 277 of file cdr.c. References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, ast_log(), ast_var_assign(), ast_var_delete(), ast_var_name(), LOG_ERROR, name, ast_cdr::next, and ast_cdr::varshead. Referenced by builtin_function_cdr_write(). 00278 { 00279 struct ast_var_t *newvariable; 00280 struct varshead *headp; 00281 const char *read_only[] = { "clid", "src", "dst", "dcontext", "channel", "dstchannel", 00282 "lastapp", "lastdata", "start", "answer", "end", "duration", 00283 "billsec", "disposition", "amaflags", "accountcode", "uniqueid", 00284 "userfield", NULL }; 00285 int x; 00286 00287 for(x = 0; read_only[x]; x++) { 00288 if (!strcasecmp(name, read_only[x])) { 00289 ast_log(LOG_ERROR, "Attempt to set a read-only variable!.\n"); 00290 return -1; 00291 } 00292 } 00293 00294 if (!cdr) { 00295 ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n"); 00296 return -1; 00297 } 00298 00299 while (cdr) { 00300 headp = &cdr->varshead; 00301 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 00302 if (!strcasecmp(ast_var_name(newvariable), name)) { 00303 /* there is already such a variable, delete it */ 00304 AST_LIST_REMOVE_CURRENT(headp, entries); 00305 ast_var_delete(newvariable); 00306 break; 00307 } 00308 } 00309 AST_LIST_TRAVERSE_SAFE_END; 00310 00311 if (value) { 00312 newvariable = ast_var_assign(name, value); 00313 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 00314 } 00315 00316 if (!recur) { 00317 break; 00318 } 00319 00320 cdr = cdr->next; 00321 } 00322 00323 return 0; 00324 }
|
|
Definition at line 466 of file cdr.c. References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, LOG_WARNING, ast_cdr::next, and ast_cdr::start. Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_cdr_reset(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), and ast_pbx_outgoing_exten(). 00467 { 00468 char *chan; 00469 00470 while (cdr) { 00471 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00472 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00473 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00474 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00475 if (!ast_tvzero(cdr->start)) 00476 ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan); 00477 cdr->start = ast_tvnow(); 00478 } 00479 cdr = cdr->next; 00480 } 00481 }
|
|
Definition at line 923 of file cdr.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, batch, batchscheduleronly, do_batch_backend_process(), ast_cdr_batch::head, LOG_DEBUG, LOG_WARNING, and reset_batch(). Referenced by ast_cdr_engine_term(), and submit_scheduled_batch(). 00924 { 00925 struct ast_cdr_batch_item *oldbatchitems = NULL; 00926 pthread_attr_t attr; 00927 pthread_t batch_post_thread = AST_PTHREADT_NULL; 00928 00929 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */ 00930 if (!batch || !batch->head) 00931 return; 00932 00933 /* move the old CDRs aside, and prepare a new CDR batch */ 00934 ast_mutex_lock(&cdr_batch_lock); 00935 oldbatchitems = batch->head; 00936 reset_batch(); 00937 ast_mutex_unlock(&cdr_batch_lock); 00938 00939 /* if configured, spawn a new thread to post these CDRs, 00940 also try to save as much as possible if we are shutting down safely */ 00941 if (batchscheduleronly || shutdown) { 00942 if (option_debug) 00943 ast_log(LOG_DEBUG, "CDR single-threaded batch processing begins now\n"); 00944 do_batch_backend_process(oldbatchitems); 00945 } else { 00946 pthread_attr_init(&attr); 00947 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00948 if (ast_pthread_create(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) { 00949 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n"); 00950 do_batch_backend_process(oldbatchitems); 00951 } else { 00952 if (option_debug) 00953 ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n"); 00954 } 00955 } 00956 }
|
|
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_UNLOCK, ast_verbose(), free, name, 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 }
|
|
Definition at line 755 of file cdr.c. References ast_cdr::accountcode, ast_channel::accountcode, AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, ast_channel::context, ast_cdr::dcontext, ast_cdr::dst, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, and ast_cdr::src. Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_feature_request_and_dial(), ast_parseable_goto(), and cb_events(). 00756 { 00757 struct ast_cdr *cdr = c->cdr; 00758 char *num; 00759 char tmp[AST_MAX_EXTENSION] = ""; 00760 00761 while (cdr) { 00762 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00763 num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num; 00764 00765 if (c->cid.cid_name && num) 00766 snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num); 00767 else if (c->cid.cid_name) 00768 ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp)); 00769 else if (num) 00770 ast_copy_string(tmp, num, sizeof(tmp)); 00771 ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid)); 00772 ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src)); 00773 00774 /* Copy account code et-al */ 00775 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00776 /* Destination information */ 00777 ast_copy_string(cdr->dst, (ast_strlen_zero(c->macroexten)) ? c->exten : c->macroexten, sizeof(cdr->dst)); 00778 ast_copy_string(cdr->dcontext, (ast_strlen_zero(c->macrocontext)) ? c->context : c->macrocontext, sizeof(cdr->dcontext)); 00779 } 00780 cdr = cdr->next; 00781 } 00782 00783 return 0; 00784 }
|
|
|
|
|
|
|
|
Definition at line 906 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(). 00907 { 00908 struct ast_cdr_batch_item *processeditem; 00909 struct ast_cdr_batch_item *batchitem = data; 00910 00911 /* Push each CDR into storage mechanism(s) and free all the memory */ 00912 while (batchitem) { 00913 post_cdr(batchitem->cdr); 00914 ast_cdr_free(batchitem->cdr); 00915 processeditem = batchitem; 00916 batchitem = batchitem->next; 00917 free(processeditem); 00918 } 00919 00920 return NULL; 00921 }
|
|
Definition at line 1036 of file cdr.c. References ast_cond_timedwait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), cdr_pending_cond, LOG_DEBUG, option_debug, and sched. Referenced by do_reload(). 01037 { 01038 struct timespec timeout; 01039 int schedms; 01040 int numevents = 0; 01041 01042 for(;;) { 01043 struct timeval now = ast_tvnow(); 01044 schedms = ast_sched_wait(sched); 01045 /* this shouldn't happen, but provide a 1 second default just in case */ 01046 if (schedms <= 0) 01047 schedms = 1000; 01048 timeout.tv_sec = now.tv_sec + (schedms / 1000); 01049 timeout.tv_nsec = (now.tv_usec * 1000) + ((schedms % 1000) * 1000); 01050 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */ 01051 ast_mutex_lock(&cdr_pending_lock); 01052 ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout); 01053 numevents = ast_sched_runq(sched); 01054 ast_mutex_unlock(&cdr_pending_lock); 01055 if (option_debug > 1) 01056 ast_log(LOG_DEBUG, "Processed %d scheduled CDR batches from the run queue\n", numevents); 01057 } 01058 01059 return NULL; 01060 }
|
|
Definition at line 1125 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_pthread_create, ast_register_atexit(), ast_sched_add(), ast_sched_del(), ast_true(), ast_unregister_atexit(), ast_variable_retrieve(), batchmode, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_pending_cond, cdr_sched, cdr_thread, cli_submit, do_cdr(), enabled, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sched, and submit_scheduled_batch(). Referenced by ast_cdr_engine_init(), ast_cdr_engine_reload(), dnsmgr_init(), dnsmgr_reload(), and handle_cli_reload(). 01126 { 01127 struct ast_config *config; 01128 const char *enabled_value; 01129 const char *batched_value; 01130 const char *scheduleronly_value; 01131 const char *batchsafeshutdown_value; 01132 const char *size_value; 01133 const char *time_value; 01134 int cfg_size; 01135 int cfg_time; 01136 int was_enabled; 01137 int was_batchmode; 01138 int res=0; 01139 01140 ast_mutex_lock(&cdr_batch_lock); 01141 01142 batchsize = BATCH_SIZE_DEFAULT; 01143 batchtime = BATCH_TIME_DEFAULT; 01144 batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT; 01145 batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT; 01146 was_enabled = enabled; 01147 was_batchmode = batchmode; 01148 enabled = 1; 01149 batchmode = 0; 01150 01151 /* don't run the next scheduled CDR posting while reloading */ 01152 if (cdr_sched > -1) 01153 ast_sched_del(sched, cdr_sched); 01154 01155 if ((config = ast_config_load("cdr.conf"))) { 01156 if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) { 01157 enabled = ast_true(enabled_value); 01158 } 01159 if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) { 01160 batchmode = ast_true(batched_value); 01161 } 01162 if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) { 01163 batchscheduleronly = ast_true(scheduleronly_value); 01164 } 01165 if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) { 01166 batchsafeshutdown = ast_true(batchsafeshutdown_value); 01167 } 01168 if ((size_value = ast_variable_retrieve(config, "general", "size"))) { 01169 if (sscanf(size_value, "%d", &cfg_size) < 1) 01170 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value); 01171 else if (size_value < 0) 01172 ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size); 01173 else 01174 batchsize = cfg_size; 01175 } 01176 if ((time_value = ast_variable_retrieve(config, "general", "time"))) { 01177 if (sscanf(time_value, "%d", &cfg_time) < 1) 01178 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value); 01179 else if (time_value < 0) 01180 ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time); 01181 else 01182 batchtime = cfg_time; 01183 } 01184 } 01185 01186 if (enabled && !batchmode) { 01187 ast_log(LOG_NOTICE, "CDR simple logging enabled.\n"); 01188 } else if (enabled && batchmode) { 01189 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); 01190 ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime); 01191 } else { 01192 ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n"); 01193 } 01194 01195 /* if this reload enabled the CDR batch mode, create the background thread 01196 if it does not exist */ 01197 if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) { 01198 ast_cond_init(&cdr_pending_cond, NULL); 01199 if (ast_pthread_create(&cdr_thread, NULL, do_cdr, NULL) < 0) { 01200 ast_log(LOG_ERROR, "Unable to start CDR thread.\n"); 01201 ast_sched_del(sched, cdr_sched); 01202 } else { 01203 ast_cli_register(&cli_submit); 01204 ast_register_atexit(ast_cdr_engine_term); 01205 res = 0; 01206 } 01207 /* if this reload disabled the CDR and/or batch mode and there is a background thread, 01208 kill it */ 01209 } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) { 01210 /* wake up the thread so it will exit */ 01211 pthread_cancel(cdr_thread); 01212 pthread_kill(cdr_thread, SIGURG); 01213 pthread_join(cdr_thread, NULL); 01214 cdr_thread = AST_PTHREADT_NULL; 01215 ast_cond_destroy(&cdr_pending_cond); 01216 ast_cli_unregister(&cli_submit); 01217 ast_unregister_atexit(ast_cdr_engine_term); 01218 res = 0; 01219 /* if leaving batch mode, then post the CDRs in the batch, 01220 and don't reschedule, since we are stopping CDR logging */ 01221 if (!batchmode && was_batchmode) { 01222 ast_cdr_engine_term(); 01223 } 01224 } else { 01225 res = 0; 01226 } 01227 01228 ast_mutex_unlock(&cdr_batch_lock); 01229 ast_config_destroy(config); 01230 01231 return res; 01232 }
|
|
Definition at line 1062 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, sched, and ast_cdr_batch::size. 01063 { 01064 struct ast_cdr_beitem *beitem=NULL; 01065 int cnt=0; 01066 long nextbatchtime=0; 01067 01068 if (argc > 2) 01069 return RESULT_SHOWUSAGE; 01070 01071 ast_cli(fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled"); 01072 ast_cli(fd, "CDR mode: %s\n", batchmode ? "batch" : "simple"); 01073 if (enabled) { 01074 if (batchmode) { 01075 if (batch) 01076 cnt = batch->size; 01077 if (cdr_sched > -1) 01078 nextbatchtime = ast_sched_when(sched, cdr_sched); 01079 ast_cli(fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled"); 01080 ast_cli(fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads"); 01081 ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, (cnt != 1) ? "s" : ""); 01082 ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, (batchsize != 1) ? "s" : ""); 01083 ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, (batchtime != 1) ? "s" : ""); 01084 ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, (nextbatchtime != 1) ? "s" : ""); 01085 } 01086 AST_LIST_LOCK(&be_list); 01087 AST_LIST_TRAVERSE(&be_list, beitem, list) { 01088 ast_cli(fd, "CDR registered backend: %s\n", beitem->name); 01089 } 01090 AST_LIST_UNLOCK(&be_list); 01091 } 01092 01093 return 0; 01094 }
|
|
Definition at line 1096 of file cdr.c. References ast_cli(), and submit_unscheduled_batch(). 01097 { 01098 if (argc > 2) 01099 return RESULT_SHOWUSAGE; 01100 01101 submit_unscheduled_batch(); 01102 ast_cli(fd, "Submitted CDRs to backend engines for processing. This may take a while.\n"); 01103 01104 return 0; 01105 }
|
|
Definition at line 892 of file cdr.c. References ast_log(), batch, LOG_WARNING, malloc, and reset_batch(). Referenced by ast_cdr_detach(), and ast_cdr_engine_init(). 00893 { 00894 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */ 00895 batch = malloc(sizeof(*batch)); 00896 if (!batch) { 00897 ast_log(LOG_WARNING, "CDR: out of memory while trying to handle batched records, data will most likely be lost\n"); 00898 return -1; 00899 } 00900 00901 reset_batch(); 00902 00903 return 0; 00904 }
|
|
Definition at line 799 of file cdr.c. References ast_cdr::answer, AST_CDR_FLAG_POSTED, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_cdr_beitem::be, ast_cdr::billsec, ast_cdr::channel, ast_cdr::duration, ast_cdr::end, LOG_WARNING, ast_cdr::next, and ast_cdr::start. Referenced by ast_cdr_detach(), and do_batch_backend_process(). 00800 { 00801 char *chan; 00802 struct ast_cdr_beitem *i; 00803 00804 while (cdr) { 00805 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00806 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00807 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00808 if (ast_tvzero(cdr->end)) 00809 ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan); 00810 if (ast_tvzero(cdr->start)) 00811 ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan); 00812 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec + (cdr->end.tv_usec - cdr->start.tv_usec) / 1000000; 00813 if (!ast_tvzero(cdr->answer)) 00814 cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec + (cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000; 00815 else 00816 cdr->billsec = 0; 00817 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 00818 AST_LIST_LOCK(&be_list); 00819 AST_LIST_TRAVERSE(&be_list, i, list) { 00820 i->be(cdr); 00821 } 00822 AST_LIST_UNLOCK(&be_list); 00823 cdr = cdr->next; 00824 } 00825 }
|
|
Definition at line 884 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().
|
|
Definition at line 958 of file cdr.c. References ast_cdr_submit_batch(), ast_sched_add(), batchtime, cdr_sched, sched, and submit_scheduled_batch(). Referenced by do_reload(), submit_scheduled_batch(), and submit_unscheduled_batch(). 00959 { 00960 ast_cdr_submit_batch(0); 00961 /* manually reschedule from this point in time */ 00962 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL); 00963 /* returning zero so the scheduler does not automatically reschedule */ 00964 return 0; 00965 }
|
|
Definition at line 967 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, sched, and submit_scheduled_batch(). Referenced by ast_cdr_detach(), and handle_cli_submit(). 00968 { 00969 /* this is okay since we are not being called from within the scheduler */ 00970 if (cdr_sched > -1) 00971 ast_sched_del(sched, cdr_sched); 00972 /* schedule the submission to occur ASAP (1 ms) */ 00973 cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL); 00974 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */ 00975 ast_mutex_lock(&cdr_pending_lock); 00976 ast_cond_signal(&cdr_pending_cond); 00977 ast_mutex_unlock(&cdr_pending_lock); 00978 }
|
|
Definition at line 58 of file cdr.c. Referenced by ast_channel_alloc(). |
|
Default AMA flag for billing records (CDR's) |
|
Referenced by ast_cdr_detach(), ast_cdr_submit_batch(), handle_cli_status(), init_batch(), and reset_batch(). |
|
Definition at line 90 of file cdr.c. Referenced by do_reload(), and handle_cli_status(). |
|
Definition at line 94 of file cdr.c. Referenced by ast_cdr_engine_term(), do_reload(), and handle_cli_status(). |
|
Definition at line 93 of file cdr.c. Referenced by ast_cdr_submit_batch(), do_reload(), and handle_cli_status(). |
|
Definition at line 91 of file cdr.c. Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status(). |
|
Definition at line 92 of file cdr.c. Referenced by do_reload(), handle_cli_status(), and submit_scheduled_batch(). |
|
Definition at line 100 of file cdr.c. Referenced by do_cdr(), do_reload(), and submit_unscheduled_batch(). |
|
Definition at line 81 of file cdr.c. Referenced by do_reload(), handle_cli_status(), submit_scheduled_batch(), and submit_unscheduled_batch(). |
|
Definition at line 82 of file cdr.c. Referenced by do_reload(). |
|
Definition at line 1116 of file cdr.c. Referenced by ast_cdr_engine_init(). |
|
Definition at line 1107 of file cdr.c. Referenced by do_reload(). |
|
Definition at line 89 of file cdr.c. Referenced by do_reload(), and handle_cli_status(). |
|
Definition at line 80 of file cdr.c. Referenced by ast_cdr_engine_init(), do_cdr(), do_reload(), handle_cli_status(), submit_scheduled_batch(), and submit_unscheduled_batch(). |