#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"
Include dependency graph for cdr.c:

Go to the source code of this file.
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) |
| static const char * | ast_cdr_getvar_internal (struct ast_cdr *cdr, const char *name, int recur) |
| int | ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *c) |
| Initialize based on a channel. | |
| int | ast_cdr_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) |
| 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 * | 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 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 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 |
Includes code and algorithms from the Zapata library.
Definition in file cdr.c.
|
|
Definition at line 87 of file cdr.c. Referenced by do_reload(). |
|
|
Definition at line 86 of file cdr.c. Referenced by do_reload(). |
|
|
Definition at line 84 of file cdr.c. Referenced by do_reload(). |
|
|
Definition at line 85 of file cdr.c. Referenced by do_reload(). |
|
|
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 788 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(), set_config(), and setup_zap(). 00789 {
00790 if (!strcasecmp(flag, "default"))
00791 return 0;
00792 if (!strcasecmp(flag, "omit"))
00793 return AST_CDR_OMIT;
00794 if (!strcasecmp(flag, "billing"))
00795 return AST_CDR_BILLING;
00796 if (!strcasecmp(flag, "documentation"))
00797 return AST_CDR_DOCUMENTATION;
00798 return -1;
00799 }
|
|
|
Definition at line 483 of file cdr.c. References ast_cdr::answer, AST_CDR_ANSWERED, 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 870 of file cdr.c. References ast_cdr::next. Referenced by ast_cdr_fork(), and attempt_transfer(). 00871 {
00872 struct ast_cdr *ret;
00873
00874 if (cdr) {
00875 ret = cdr;
00876
00877 while (cdr->next)
00878 cdr = cdr->next;
00879 cdr->next = newcdr;
00880 } else {
00881 ret = newcdr;
00882 }
00883
00884 return ret;
00885 }
|
|
||||||||||||
|
Definition at line 741 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(). 00742 {
00743 struct ast_cdr *cdr = chan->cdr;
00744
00745 while (cdr) {
00746 int len = strlen(cdr->userfield);
00747
00748 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00749 strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1);
00750
00751 cdr = cdr->next;
00752 }
00753
00754 return 0;
00755 }
|
|
|
Definition at line 499 of file cdr.c. References AST_CDR_BUSY, 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(), and ring_entry(). 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(), 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 984 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, batchmode, batchsize, ast_cdr_batch_item::cdr, enabled, ast_cdr_batch::head, init_batch(), LOG_DEBUG, LOG_WARNING, malloc, 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(). 00985 {
00986 struct ast_cdr_batch_item *newtail;
00987 int curr;
00988
00989 /* maybe they disabled CDR stuff completely, so just drop it */
00990 if (!enabled) {
00991 if (option_debug)
00992 ast_log(LOG_DEBUG, "Dropping CDR !\n");
00993 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
00994 ast_cdr_free(cdr);
00995 return;
00996 }
00997
00998 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
00999 if (!batchmode) {
01000 post_cdr(cdr);
01001 ast_cdr_free(cdr);
01002 return;
01003 }
01004
01005 /* otherwise, each CDR gets put into a batch list (at the end) */
01006 if (option_debug)
01007 ast_log(LOG_DEBUG, "CDR detaching from this thread\n");
01008
01009 /* we'll need a new tail for every CDR */
01010 newtail = malloc(sizeof(*newtail));
01011 if (!newtail) {
01012 ast_log(LOG_WARNING, "CDR: out of memory while trying to detach, will try in this thread instead\n");
01013 post_cdr(cdr);
01014 ast_cdr_free(cdr);
01015 return;
01016 }
01017 memset(newtail, 0, sizeof(*newtail));
01018
01019 /* don't traverse a whole list (just keep track of the tail) */
01020 ast_mutex_lock(&cdr_batch_lock);
01021 if (!batch)
01022 init_batch();
01023 if (!batch->head) {
01024 /* new batch is empty, so point the head at the new tail */
01025 batch->head = newtail;
01026 } else {
01027 /* already got a batch with something in it, so just append a new tail */
01028 batch->tail->next = newtail;
01029 }
01030 newtail->cdr = cdr;
01031 batch->tail = newtail;
01032 curr = batch->size++;
01033 ast_mutex_unlock(&cdr_batch_lock);
01034
01035 /* if we have enough stuff to post, then do it */
01036 if (curr >= (batchsize - 1))
01037 submit_unscheduled_batch();
01038 }
|
|
|
Definition at line 671 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(). 00672 {
00673 switch (disposition) {
00674 case AST_CDR_NOANSWER:
00675 return "NO ANSWER";
00676 case AST_CDR_FAILED:
00677 return "FAILED";
00678 case AST_CDR_BUSY:
00679 return "BUSY";
00680 case AST_CDR_ANSWERED:
00681 return "ANSWERED";
00682 }
00683 return "UNKNOWN";
00684 }
|
|
||||||||||||
|
Definition at line 531 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(), and LOG_WARNING. Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten(). 00532 {
00533 int res = 0;
00534
00535 while (cdr) {
00536 switch(cause) {
00537 case AST_CAUSE_BUSY:
00538 ast_cdr_busy(cdr);
00539 break;
00540 case AST_CAUSE_FAILURE:
00541 ast_cdr_failed(cdr);
00542 break;
00543 case AST_CAUSE_NORMAL:
00544 break;
00545 case AST_CAUSE_NOTDEFINED:
00546 res = -1;
00547 break;
00548 default:
00549 res = -1;
00550 ast_log(LOG_WARNING, "Cause not handled\n");
00551 }
00552 cdr = cdr->next;
00553 }
00554 return res;
00555 }
|
|
|
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(), and LOG_ERROR. 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 655 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(). 00656 {
00657 char *chan;
00658
00659 while (cdr) {
00660 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00661 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00662 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00663 if (ast_tvzero(cdr->start))
00664 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", chan);
00665 if (ast_tvzero(cdr->end))
00666 cdr->end = ast_tvnow();
00667 cdr = cdr->next;
00668 }
00669 }
|
|
|
Load the configuration file cdr.conf and possibly start the CDR scheduling thread Definition at line 1238 of file cdr.c. References ast_cli_register(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), do_reload(), init_batch(), LOG_ERROR, and sched_context_create(). Referenced by main(). 01239 {
01240 int res;
01241
01242 sched = sched_context_create();
01243 if (!sched) {
01244 ast_log(LOG_ERROR, "Unable to create schedule context.\n");
01245 return -1;
01246 }
01247
01248 ast_cli_register(&cli_status);
01249
01250 res = do_reload();
01251 if (res) {
01252 ast_mutex_lock(&cdr_batch_lock);
01253 res = init_batch();
01254 ast_mutex_unlock(&cdr_batch_lock);
01255 }
01256
01257 return res;
01258 }
|
|
|
Reload the configuration file cdr.conf and start/stop CDR scheduling thread Definition at line 1267 of file cdr.c. References do_reload(). Referenced by ast_module_reload(). 01268 {
01269 do_reload();
01270 }
|
|
|
Submit any remaining CDRs and prepare for shutdown Definition at line 1262 of file cdr.c. References ast_cdr_submit_batch(), and batchsafeshutdown. Referenced by do_reload(), and quit_handler(). 01263 {
01264 ast_cdr_submit_batch(batchsafeshutdown);
01265 }
|
|
|
Definition at line 515 of file cdr.c. References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, and LOG_WARNING. 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 if (cdr->disposition < AST_CDR_FAILED)
00525 cdr->disposition = AST_CDR_FAILED;
00526 }
00527 cdr = cdr->next;
00528 }
00529 }
|
|
|
Converts AMA flag to printable string Definition at line 687 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(). 00688 {
00689 switch(flag) {
00690 case AST_CDR_OMIT:
00691 return "OMIT";
00692 case AST_CDR_BILLING:
00693 return "BILLING";
00694 case AST_CDR_DOCUMENTATION:
00695 return "DOCUMENTATION";
00696 }
00697 return "Unknown";
00698 }
|
|
|
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, free, LOG_WARNING, and ast_cdr::next. 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_disp2str(), ast_cdr_flags2str(), ast_cdr_getvar_internal(), ast_strlen_zero(), fmt, and t. 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(), and ast_var_value(). 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 617 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_CDR_NOANSWER, ast_default_amaflags, ast_log(), AST_MAX_EXTENSION, AST_STATE_UP, 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(). 00618 {
00619 char *chan;
00620 char *num;
00621 char tmp[AST_MAX_EXTENSION] = "";
00622
00623 while (cdr) {
00624 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00625 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00626 if (!ast_strlen_zero(cdr->channel))
00627 ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan);
00628 ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
00629 /* Grab source from ANI or normal Caller*ID */
00630 num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
00631
00632 if (c->cid.cid_name && num)
00633 snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
00634 else if (c->cid.cid_name)
00635 ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
00636 else if (num)
00637 ast_copy_string(tmp, num, sizeof(tmp));
00638 ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
00639 ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
00640
00641 cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER;
00642 cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags;
00643 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00644 /* Destination information */
00645 ast_copy_string(cdr->dst, c->exten, sizeof(cdr->dst));
00646 ast_copy_string(cdr->dcontext, c->context, sizeof(cdr->dcontext));
00647 /* Unique call identifier */
00648 ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid));
00649 }
00650 cdr = cdr->next;
00651 }
00652 return 0;
00653 }
|
|
||||||||||||||||
|
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(), list, LOG_WARNING, malloc, 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 831 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_cdr::next, and ast_cdr::start. Referenced by ast_bridge_call_thread(), ast_cdr_fork(), dial_exec_full(), disa_exec(), and pbx_builtin_resetcdr(). 00832 {
00833 struct ast_cdr *dup;
00834 struct ast_flags flags = { 0 };
00835
00836 if (_flags)
00837 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
00838
00839 while (cdr) {
00840 /* Detach if post is requested */
00841 if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00842 if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
00843 ast_cdr_end(cdr);
00844 if ((dup = ast_cdr_dup(cdr))) {
00845 ast_cdr_detach(dup);
00846 }
00847 ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
00848 }
00849
00850 /* clear variables */
00851 if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
00852 ast_cdr_free_vars(cdr, 0);
00853 }
00854
00855 /* Reset to initial state */
00856 ast_clear_flag(cdr, AST_FLAGS_ALL);
00857 memset(&cdr->start, 0, sizeof(cdr->start));
00858 memset(&cdr->end, 0, sizeof(cdr->end));
00859 memset(&cdr->answer, 0, sizeof(cdr->answer));
00860 cdr->billsec = 0;
00861 cdr->duration = 0;
00862 ast_cdr_start(cdr);
00863 cdr->disposition = AST_CDR_NOANSWER;
00864 }
00865
00866 cdr = cdr->next;
00867 }
00868 }
|
|
||||||||||||||||||||||||||||
|
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, total, 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 700 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(). 00701 {
00702 struct ast_cdr *cdr = chan->cdr;
00703
00704 ast_copy_string(chan->accountcode, account, sizeof(chan->accountcode));
00705 while (cdr) {
00706 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00707 ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode));
00708 cdr = cdr->next;
00709 }
00710 return 0;
00711 }
|
|
||||||||||||
|
Definition at line 713 of file cdr.c. References ast_cdr::amaflags, ast_cdr_amaflags2int(), ast_channel::cdr, and ast_cdr::next. Referenced by pbx_builtin_setamaflags(). 00714 {
00715 struct ast_cdr *cdr;
00716 int newflag;
00717
00718 newflag = ast_cdr_amaflags2int(flag);
00719 if (newflag) {
00720 for (cdr = chan->cdr; cdr; cdr = cdr->next) {
00721 cdr->amaflags = newflag;
00722 }
00723 }
00724
00725 return 0;
00726 }
|
|
||||||||||||||||
|
Definition at line 571 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(). 00572 {
00573 char *chan;
00574
00575 while (cdr) {
00576 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00577 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00578 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00579 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00580 if (!app)
00581 app = "";
00582 ast_copy_string(cdr->lastapp, app, sizeof(cdr->lastapp));
00583 if (!data)
00584 data = "";
00585 ast_copy_string(cdr->lastdata, data, sizeof(cdr->lastdata));
00586 }
00587 cdr = cdr->next;
00588 }
00589 }
|
|
||||||||||||
|
Definition at line 591 of file cdr.c. References AST_CDR_FLAG_LOCKED, AST_MAX_EXTENSION, 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(). 00592 {
00593 char tmp[AST_MAX_EXTENSION] = "";
00594 char *num;
00595
00596 while (cdr) {
00597 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00598 /* Grab source from ANI or normal Caller*ID */
00599 num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
00600
00601 if (c->cid.cid_name && num)
00602 snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
00603 else if (c->cid.cid_name)
00604 ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
00605 else if (num)
00606 ast_copy_string(tmp, num, sizeof(tmp));
00607 ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
00608 ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
00609 }
00610 cdr = cdr->next;
00611 }
00612
00613 return 0;
00614 }
|
|
||||||||||||
|
Definition at line 557 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(). 00558 {
00559 char *chan;
00560
00561 while (cdr) {
00562 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00563 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00564 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00565 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00566 ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel));
00567 cdr = cdr->next;
00568 }
00569 }
|
|
||||||||||||
|
Definition at line 728 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(). 00729 {
00730 struct ast_cdr *cdr = chan->cdr;
00731
00732 while (cdr) {
00733 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00734 ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield));
00735 cdr = cdr->next;
00736 }
00737
00738 return 0;
00739 }
|
|
||||||||||||||||||||
|
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_LIST_TRAVERSE_SAFE_END, ast_log(), ast_var_assign(), ast_var_delete(), ast_var_name(), and LOG_ERROR. 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 927 of file cdr.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, 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(). 00928 {
00929 struct ast_cdr_batch_item *oldbatchitems = NULL;
00930 pthread_attr_t attr;
00931 pthread_t batch_post_thread = AST_PTHREADT_NULL;
00932
00933 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
00934 if (!batch || !batch->head)
00935 return;
00936
00937 /* move the old CDRs aside, and prepare a new CDR batch */
00938 ast_mutex_lock(&cdr_batch_lock);
00939 oldbatchitems = batch->head;
00940 reset_batch();
00941 ast_mutex_unlock(&cdr_batch_lock);
00942
00943 /* if configured, spawn a new thread to post these CDRs,
00944 also try to save as much as possible if we are shutting down safely */
00945 if (batchscheduleronly || shutdown) {
00946 if (option_debug)
00947 ast_log(LOG_DEBUG, "CDR single-threaded batch processing begins now\n");
00948 do_batch_backend_process(oldbatchitems);
00949 } else {
00950 pthread_attr_init(&attr);
00951 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00952 if (ast_pthread_create(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) {
00953 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
00954 do_batch_backend_process(oldbatchitems);
00955 } else {
00956 if (option_debug)
00957 ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n");
00958 }
00959 }
00960 }
|
|
|
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, list, 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 757 of file cdr.c. References ast_cdr::accountcode, ast_channel::accountcode, AST_CDR_FLAG_LOCKED, AST_MAX_EXTENSION, ast_strlen_zero(), 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(). 00758 {
00759 struct ast_cdr *cdr = c->cdr;
00760 char *num;
00761 char tmp[AST_MAX_EXTENSION] = "";
00762
00763 while (cdr) {
00764 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00765 num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
00766
00767 if (c->cid.cid_name && num)
00768 snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
00769 else if (c->cid.cid_name)
00770 ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
00771 else if (num)
00772 ast_copy_string(tmp, num, sizeof(tmp));
00773 ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
00774 ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
00775
00776 /* Copy account code et-al */
00777 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00778 /* Destination information */
00779 ast_copy_string(cdr->dst, (ast_strlen_zero(c->macroexten)) ? c->exten : c->macroexten, sizeof(cdr->dst));
00780 ast_copy_string(cdr->dcontext, (ast_strlen_zero(c->macrocontext)) ? c->context : c->macrocontext, sizeof(cdr->dcontext));
00781 }
00782 cdr = cdr->next;
00783 }
00784
00785 return 0;
00786 }
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
|
Definition at line 910 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(). 00911 {
00912 struct ast_cdr_batch_item *processeditem;
00913 struct ast_cdr_batch_item *batchitem = data;
00914
00915 /* Push each CDR into storage mechanism(s) and free all the memory */
00916 while (batchitem) {
00917 post_cdr(batchitem->cdr);
00918 ast_cdr_free(batchitem->cdr);
00919 processeditem = batchitem;
00920 batchitem = batchitem->next;
00921 free(processeditem);
00922 }
00923
00924 return NULL;
00925 }
|
|
|
Definition at line 1040 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, and option_debug. Referenced by do_reload(). 01041 {
01042 struct timespec timeout;
01043 int schedms;
01044 int numevents = 0;
01045
01046 for(;;) {
01047 struct timeval now = ast_tvnow();
01048 schedms = ast_sched_wait(sched);
01049 /* this shouldn't happen, but provide a 1 second default just in case */
01050 if (schedms <= 0)
01051 schedms = 1000;
01052 timeout.tv_sec = now.tv_sec + (schedms / 1000);
01053 timeout.tv_nsec = (now.tv_usec * 1000) + ((schedms % 1000) * 1000);
01054 /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
01055 ast_mutex_lock(&cdr_pending_lock);
01056 ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
01057 numevents = ast_sched_runq(sched);
01058 ast_mutex_unlock(&cdr_pending_lock);
01059 if (option_debug > 1)
01060 ast_log(LOG_DEBUG, "Processed %d scheduled CDR batches from the run queue\n", numevents);
01061 }
01062
01063 return NULL;
01064 }
|
|
|
Definition at line 1129 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_PTHREADT_NULL, ast_register_atexit(), ast_sched_add(), ast_sched_del(), 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, 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(). 01130 {
01131 struct ast_config *config;
01132 const char *enabled_value;
01133 const char *batched_value;
01134 const char *scheduleronly_value;
01135 const char *batchsafeshutdown_value;
01136 const char *size_value;
01137 const char *time_value;
01138 int cfg_size;
01139 int cfg_time;
01140 int was_enabled;
01141 int was_batchmode;
01142 int res=0;
01143
01144 ast_mutex_lock(&cdr_batch_lock);
01145
01146 batchsize = BATCH_SIZE_DEFAULT;
01147 batchtime = BATCH_TIME_DEFAULT;
01148 batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT;
01149 batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT;
01150 was_enabled = enabled;
01151 was_batchmode = batchmode;
01152 enabled = 1;
01153 batchmode = 0;
01154
01155 /* don't run the next scheduled CDR posting while reloading */
01156 if (cdr_sched > -1)
01157 ast_sched_del(sched, cdr_sched);
01158
01159 if ((config = ast_config_load("cdr.conf"))) {
01160 if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
01161 enabled = ast_true(enabled_value);
01162 }
01163 if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) {
01164 batchmode = ast_true(batched_value);
01165 }
01166 if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) {
01167 batchscheduleronly = ast_true(scheduleronly_value);
01168 }
01169 if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) {
01170 batchsafeshutdown = ast_true(batchsafeshutdown_value);
01171 }
01172 if ((size_value = ast_variable_retrieve(config, "general", "size"))) {
01173 if (sscanf(size_value, "%d", &cfg_size) < 1)
01174 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value);
01175 else if (size_value < 0)
01176 ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size);
01177 else
01178 batchsize = cfg_size;
01179 }
01180 if ((time_value = ast_variable_retrieve(config, "general", "time"))) {
01181 if (sscanf(time_value, "%d", &cfg_time) < 1)
01182 ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value);
01183 else if (time_value < 0)
01184 ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time);
01185 else
01186 batchtime = cfg_time;
01187 }
01188 }
01189
01190 if (enabled && !batchmode) {
01191 ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
01192 } else if (enabled && batchmode) {
01193 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
01194 ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime);
01195 } else {
01196 ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n");
01197 }
01198
01199 /* if this reload enabled the CDR batch mode, create the background thread
01200 if it does not exist */
01201 if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) {
01202 ast_cond_init(&cdr_pending_cond, NULL);
01203 if (ast_pthread_create(&cdr_thread, NULL, do_cdr, NULL) < 0) {
01204 ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
01205 ast_sched_del(sched, cdr_sched);
01206 } else {
01207 ast_cli_register(&cli_submit);
01208 ast_register_atexit(ast_cdr_engine_term);
01209 res = 0;
01210 }
01211 /* if this reload disabled the CDR and/or batch mode and there is a background thread,
01212 kill it */
01213 } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) {
01214 /* wake up the thread so it will exit */
01215 pthread_cancel(cdr_thread);
01216 pthread_kill(cdr_thread, SIGURG);
01217 pthread_join(cdr_thread, NULL);
01218 cdr_thread = AST_PTHREADT_NULL;
01219 ast_cond_destroy(&cdr_pending_cond);
01220 ast_cli_unregister(&cli_submit);
01221 ast_unregister_atexit(ast_cdr_engine_term);
01222 res = 0;
01223 /* if leaving batch mode, then post the CDRs in the batch,
01224 and don't reschedule, since we are stopping CDR logging */
01225 if (!batchmode && was_batchmode) {
01226 ast_cdr_engine_term();
01227 }
01228 } else {
01229 res = 0;
01230 }
01231
01232 ast_mutex_unlock(&cdr_batch_lock);
01233 ast_config_destroy(config);
01234
01235 return res;
01236 }
|
|
||||||||||||||||
|
Definition at line 1066 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, list, ast_cdr_beitem::name, and RESULT_SHOWUSAGE. 01067 {
01068 struct ast_cdr_beitem *beitem=NULL;
01069 int cnt=0;
01070 long nextbatchtime=0;
01071
01072 if (argc > 2)
01073 return RESULT_SHOWUSAGE;
01074
01075 ast_cli(fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled");
01076 ast_cli(fd, "CDR mode: %s\n", batchmode ? "batch" : "simple");
01077 if (enabled) {
01078 if (batchmode) {
01079 if (batch)
01080 cnt = batch->size;
01081 if (cdr_sched > -1)
01082 nextbatchtime = ast_sched_when(sched, cdr_sched);
01083 ast_cli(fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled");
01084 ast_cli(fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads");
01085 ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, (cnt != 1) ? "s" : "");
01086 ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, (batchsize != 1) ? "s" : "");
01087 ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, (batchtime != 1) ? "s" : "");
01088 ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, (nextbatchtime != 1) ? "s" : "");
01089 }
01090 AST_LIST_LOCK(&be_list);
01091 AST_LIST_TRAVERSE(&be_list, beitem, list) {
01092 ast_cli(fd, "CDR registered backend: %s\n", beitem->name);
01093 }
01094 AST_LIST_UNLOCK(&be_list);
01095 }
01096
01097 return 0;
01098 }
|
|
||||||||||||||||
|
Definition at line 1100 of file cdr.c. References ast_cli(), RESULT_SHOWUSAGE, and submit_unscheduled_batch(). 01101 {
01102 if (argc > 2)
01103 return RESULT_SHOWUSAGE;
01104
01105 submit_unscheduled_batch();
01106 ast_cli(fd, "Submitted CDRs to backend engines for processing. This may take a while.\n");
01107
01108 return 0;
01109 }
|
|
|
Definition at line 896 of file cdr.c. References ast_log(), batch, LOG_WARNING, malloc, and reset_batch(). Referenced by ast_cdr_detach(), and ast_cdr_engine_init(). 00897 {
00898 /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
00899 batch = malloc(sizeof(*batch));
00900 if (!batch) {
00901 ast_log(LOG_WARNING, "CDR: out of memory while trying to handle batched records, data will most likely be lost\n");
00902 return -1;
00903 }
00904
00905 reset_batch();
00906
00907 return 0;
00908 }
|
|
|
Definition at line 801 of file cdr.c. References ast_cdr::answer, AST_CDR_FAILED, 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::disposition, ast_cdr::duration, ast_cdr::end, list, LOG_WARNING, ast_cdr::next, and ast_cdr::start. Referenced by ast_cdr_detach(), and do_batch_backend_process(). 00802 {
00803 char *chan;
00804 struct ast_cdr_beitem *i;
00805
00806 while (cdr) {
00807 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00808 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00809 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00810 if (ast_tvzero(cdr->end))
00811 ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
00812 if (ast_tvzero(cdr->start)) {
00813 ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
00814 cdr->disposition = AST_CDR_FAILED;
00815 } else
00816 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
00817 if (!ast_tvzero(cdr->answer))
00818 cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
00819 else
00820 cdr->billsec = 0;
00821 ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
00822 AST_LIST_LOCK(&be_list);
00823 AST_LIST_TRAVERSE(&be_list, i, list) {
00824 i->be(cdr);
00825 }
00826 AST_LIST_UNLOCK(&be_list);
00827 cdr = cdr->next;
00828 }
00829 }
|
|
|
Definition at line 888 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 962 of file cdr.c. References ast_cdr_submit_batch(), ast_sched_add(), batchtime, and cdr_sched. Referenced by do_reload(), and submit_unscheduled_batch(). 00963 {
00964 ast_cdr_submit_batch(0);
00965 /* manually reschedule from this point in time */
00966 cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
00967 /* returning zero so the scheduler does not automatically reschedule */
00968 return 0;
00969 }
|
|
|
Definition at line 971 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(). 00972 {
00973 /* this is okay since we are not being called from within the scheduler */
00974 if (cdr_sched > -1)
00975 ast_sched_del(sched, cdr_sched);
00976 /* schedule the submission to occur ASAP (1 ms) */
00977 cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
00978 /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
00979 ast_mutex_lock(&cdr_pending_lock);
00980 ast_cond_signal(&cdr_pending_cond);
00981 ast_mutex_unlock(&cdr_pending_lock);
00982 }
|
|
|
Definition at line 58 of file cdr.c. Referenced by ast_channel_alloc(). |
|
|
Default AMA flag for billing records (CDR's) Definition at line 57 of file cdr.c. Referenced by ast_cdr_init(), and ast_channel_alloc(). |
|
|
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 ast_cdr_detach(), 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 89 of file cdr.c. Referenced by ast_cdr_detach(), ast_dnsmgr_lookup(), do_reload(), handle_cli_status(), init_manager(), and load_odbc_config(). |
|
|
|
1.4.2