Wed Aug 15 01:24:46 2007

Asterisk developer's documentation


cdr.c File Reference

Call Detail Record API. More...

#include "asterisk.h"
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/logger.h"
#include "asterisk/callerid.h"
#include "asterisk/causes.h"
#include "asterisk/options.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/stringfields.h"

Include dependency graph for cdr.c:

Go to the source code of this file.

Data Structures

struct  ast_cdr_batch
struct  ast_cdr_batch_item
struct  ast_cdr_beitem

Defines

#define BATCH_SAFE_SHUTDOWN_DEFAULT   1
#define BATCH_SCHEDULER_ONLY_DEFAULT   0
#define BATCH_SIZE_DEFAULT   100
#define BATCH_TIME_DEFAULT   300

Functions

struct ast_cdrast_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)
struct ast_cdrast_cdr_append (struct ast_cdr *cdr, struct ast_cdr *newcdr)
int ast_cdr_appenduserfield (struct ast_channel *chan, const char *userfield)
void ast_cdr_busy (struct ast_cdr *cdr)
int ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
void ast_cdr_detach (struct ast_cdr *cdr)
void ast_cdr_discard (struct ast_cdr *cdr)
 the same as a cdr_free call, only with no checks; just get rid of it
char * ast_cdr_disp2str (int disposition)
int ast_cdr_disposition (struct ast_cdr *cdr, int cause)
struct ast_cdrast_cdr_dup (struct ast_cdr *cdr)
 Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
void ast_cdr_end (struct ast_cdr *cdr)
int ast_cdr_engine_init (void)
int ast_cdr_engine_reload (void)
void ast_cdr_engine_term (void)
void ast_cdr_failed (struct ast_cdr *cdr)
char * ast_cdr_flags2str (int flag)
void ast_cdr_free (struct ast_cdr *cdr)
 Free a CDR record.
void ast_cdr_free_vars (struct ast_cdr *cdr, int recur)
void ast_cdr_getvar (struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw)
static const char * ast_cdr_getvar_internal (struct ast_cdr *cdr, const char *name, int recur)
int ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *c)
 Initialize based on a channel.
void ast_cdr_merge (struct ast_cdr *to, struct ast_cdr *from)
void ast_cdr_noanswer (struct ast_cdr *cdr)
int ast_cdr_register (const char *name, const char *desc, ast_cdrbe be)
void ast_cdr_reset (struct ast_cdr *cdr, struct ast_flags *_flags)
int ast_cdr_serialize_variables (struct ast_cdr *cdr, char *buf, size_t size, char delim, char sep, int recur)
int ast_cdr_setaccount (struct ast_channel *chan, const char *account)
int ast_cdr_setamaflags (struct ast_channel *chan, const char *flag)
void ast_cdr_setapp (struct ast_cdr *cdr, char *app, char *data)
int ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *c)
void ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chann)
int ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield)
int ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur)
void ast_cdr_start (struct ast_cdr *cdr)
void ast_cdr_submit_batch (int shutdown)
void ast_cdr_unregister (const char *name)
int ast_cdr_update (struct ast_channel *c)
static AST_LIST_HEAD_STATIC (be_list, ast_cdr_beitem)
 AST_MUTEX_DEFINE_STATIC (cdr_pending_lock)
 AST_MUTEX_DEFINE_STATIC (cdr_batch_lock)
static void cdr_get_tv (struct timeval tv, const char *fmt, char *buf, int bufsize)
static void cdr_merge_vars (struct ast_cdr *to, struct ast_cdr *from)
static void check_post (struct ast_cdr *cdr)
 print a warning if cdr already posted
static void * do_batch_backend_process (void *data)
static void * do_cdr (void *data)
static int do_reload (void)
static int handle_cli_status (int fd, int argc, char *argv[])
static int handle_cli_submit (int fd, int argc, char *argv[])
static int init_batch (void)
static void post_cdr (struct ast_cdr *cdr)
static void reset_batch (void)
static void set_one_cid (struct ast_cdr *cdr, struct ast_channel *c)
static int submit_scheduled_batch (void *data)
static void submit_unscheduled_batch (void)

Variables

char ast_default_accountcode [AST_MAX_ACCOUNT_CODE]
int ast_default_amaflags = AST_CDR_DOCUMENTATION
static struct
ast_cdr_batch
batch
static int batchmode
static int batchsafeshutdown
static int batchscheduleronly
static int batchsize
static int batchtime
static ast_cond_t cdr_pending_cond
static const char * cdr_readonly_vars []
static int cdr_sched = -1
static pthread_t cdr_thread = AST_PTHREADT_NULL
static struct
ast_cli_entry 
cli_status
static struct
ast_cli_entry 
cli_submit
static int enabled
static struct
sched_context
sched


Detailed Description

Call Detail Record API.

Author:
Mark Spencer <markster@digium.com>
Note:
Includes code and algorithms from the Zapata library.

We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip through our fingers somehow. If someone allocates a CDR, it must be completely handled normally or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR isn't properly generated and posted.

Definition in file cdr.c.


Define Documentation

#define BATCH_SAFE_SHUTDOWN_DEFAULT   1

Definition at line 89 of file cdr.c.

Referenced by do_reload().

#define BATCH_SCHEDULER_ONLY_DEFAULT   0

Definition at line 88 of file cdr.c.

Referenced by do_reload().

#define BATCH_SIZE_DEFAULT   100

Definition at line 86 of file cdr.c.

Referenced by do_reload().

#define BATCH_TIME_DEFAULT   300

Definition at line 87 of file cdr.c.

Referenced by do_reload().


Function Documentation

struct ast_cdr* ast_cdr_alloc ( void   )  [read]

Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).

Definition at line 456 of file cdr.c.

Referenced by __agent_start_monitoring(), __ast_pbx_run(), __ast_read(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_dup(), ast_channel_alloc(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), builtin_blindtransfer(), clear_caller(), findmeexec(), and start_monitor_exec().

00457 {
00458    struct ast_cdr *x = ast_calloc(1, sizeof(struct ast_cdr));
00459    if (!x)
00460       ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n");
00461    return x;
00462 }

int ast_cdr_amaflags2int ( const char *  flag  ) 

Convert a string to a detail record AMA flag

Parameters:
flag string form of flag Converts the string form of the flag to the binary form. Returns the binary form of the flag

Definition at line 967 of file cdr.c.

Referenced by ast_cdr_setamaflags(), build_device(), build_gateway(), build_peer(), build_user(), process_zap(), and set_config().

00968 {
00969    if (!strcasecmp(flag, "default"))
00970       return 0;
00971    if (!strcasecmp(flag, "omit"))
00972       return AST_CDR_OMIT;
00973    if (!strcasecmp(flag, "billing"))
00974       return AST_CDR_BILLING;
00975    if (!strcasecmp(flag, "documentation"))
00976       return AST_CDR_DOCUMENTATION;
00977    return -1;
00978 }

void ast_cdr_answer ( struct ast_cdr cdr  ) 

Answer a call

Parameters:
cdr the cdr you wish to associate with the call Starts all CDR stuff necessary for doing CDR when answering a call NULL argument is just fine.

Definition at line 692 of file cdr.c.

Referenced by __ast_read(), and ast_answer().

00693 {
00694 
00695    for (; cdr; cdr = cdr->next) {
00696       check_post(cdr);
00697       if (cdr->disposition < AST_CDR_ANSWERED)
00698          cdr->disposition = AST_CDR_ANSWERED;
00699       if (ast_tvzero(cdr->answer))
00700          cdr->answer = ast_tvnow();
00701    }
00702 }

struct ast_cdr* ast_cdr_append ( struct ast_cdr cdr,
struct ast_cdr newcdr 
) [read]

Definition at line 1040 of file cdr.c.

Referenced by ast_cdr_fork(), ast_cdr_merge(), and attempt_transfer().

01041 {
01042    struct ast_cdr *ret;
01043 
01044    if (cdr) {
01045       ret = cdr;
01046 
01047       while (cdr->next)
01048          cdr = cdr->next;
01049       cdr->next = newcdr;
01050    } else {
01051       ret = newcdr;
01052    }
01053 
01054    return ret;
01055 }

int ast_cdr_appenduserfield ( struct ast_channel chan,
const char *  userfield 
)

Definition at line 933 of file cdr.c.

Referenced by action_setcdruserfield(), appendcdruserfield_exec(), and ast_bridge_call().

00934 {
00935    struct ast_cdr *cdr = chan->cdr;
00936 
00937    for ( ; cdr ; cdr = cdr->next) {
00938       int len = strlen(cdr->userfield);
00939 
00940       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00941          ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len);
00942    }
00943 
00944    return 0;
00945 }

void ast_cdr_busy ( struct ast_cdr cdr  ) 

Busy a call

Parameters:
cdr the cdr you wish to associate with the call Returns nothing

Definition at line 704 of file cdr.c.

Referenced by ast_cdr_disposition(), ring_entry(), and wait_for_answer().

00705 {
00706 
00707    for (; cdr; cdr = cdr->next) {
00708       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00709          check_post(cdr);
00710          if (cdr->disposition < AST_CDR_BUSY)
00711             cdr->disposition = AST_CDR_BUSY;
00712       }
00713    }
00714 }

int ast_cdr_copy_vars ( struct ast_cdr to_cdr,
struct ast_cdr from_cdr 
)

Definition at line 334 of file cdr.c.

Referenced by ast_cdr_dup().

00335 {
00336    struct ast_var_t *variables, *newvariable = NULL;
00337    struct varshead *headpa, *headpb;
00338    const char *var, *val;
00339    int x = 0;
00340 
00341    if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */
00342       return 0;
00343 
00344    headpa = &from_cdr->varshead;
00345    headpb = &to_cdr->varshead;
00346 
00347    AST_LIST_TRAVERSE(headpa,variables,entries) {
00348       if (variables &&
00349           (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00350           !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00351          newvariable = ast_var_assign(var, val);
00352          AST_LIST_INSERT_HEAD(headpb, newvariable, entries);
00353          x++;
00354       }
00355    }
00356 
00357    return x;
00358 }

void ast_cdr_detach ( struct ast_cdr cdr  ) 

Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other records during batch mode operation

Parameters:
cdr Which CDR to detach from the channel thread Prevents the channel thread from blocking on the CDR handling Returns nothing

Definition at line 1152 of file cdr.c.

Referenced by ast_cdr_reset(), ast_hangup(), and ast_pbx_outgoing_cdr_failed().

01153 {
01154    struct ast_cdr_batch_item *newtail;
01155    int curr;
01156 
01157    if (!cdr)
01158       return;
01159 
01160    /* maybe they disabled CDR stuff completely, so just drop it */
01161    if (!enabled) {
01162       if (option_debug)
01163          ast_log(LOG_DEBUG, "Dropping CDR !\n");
01164       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01165       ast_cdr_free(cdr);
01166       return;
01167    }
01168 
01169    /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
01170    if (!batchmode) {
01171       post_cdr(cdr);
01172       ast_cdr_free(cdr);
01173       return;
01174    }
01175 
01176    /* otherwise, each CDR gets put into a batch list (at the end) */
01177    if (option_debug)
01178       ast_log(LOG_DEBUG, "CDR detaching from this thread\n");
01179 
01180    /* we'll need a new tail for every CDR */
01181    if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
01182       post_cdr(cdr);
01183       ast_cdr_free(cdr);
01184       return;
01185    }
01186 
01187    /* don't traverse a whole list (just keep track of the tail) */
01188    ast_mutex_lock(&cdr_batch_lock);
01189    if (!batch)
01190       init_batch();
01191    if (!batch->head) {
01192       /* new batch is empty, so point the head at the new tail */
01193       batch->head = newtail;
01194    } else {
01195       /* already got a batch with something in it, so just append a new tail */
01196       batch->tail->next = newtail;
01197    }
01198    newtail->cdr = cdr;
01199    batch->tail = newtail;
01200    curr = batch->size++;
01201    ast_mutex_unlock(&cdr_batch_lock);
01202 
01203    /* if we have enough stuff to post, then do it */
01204    if (curr >= (batchsize - 1))
01205       submit_unscheduled_batch();
01206 }

void ast_cdr_discard ( struct ast_cdr cdr  ) 

the same as a cdr_free call, only with no checks; just get rid of it

Discard and free a CDR record.

Definition at line 445 of file cdr.c.

Referenced by ast_bridge_call(), and ast_cdr_merge().

00446 {
00447    while (cdr) {
00448       struct ast_cdr *next = cdr->next;
00449 
00450       ast_cdr_free_vars(cdr, 0);
00451       free(cdr);
00452       cdr = next;
00453    }
00454 }

char* ast_cdr_disp2str ( int  disposition  ) 

Disposition to a string

Parameters:
disposition input binary form Converts the binary form of a disposition to string form. Returns a pointer to the string form

Definition at line 862 of file cdr.c.

Referenced by ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), manager_log(), odbc_log(), pgsql_log(), and tds_log().

00863 {
00864    switch (disposition) {
00865    case AST_CDR_NULL:
00866       return "NO ANSWER"; /* by default, for backward compatibility */
00867    case AST_CDR_NOANSWER:
00868       return "NO ANSWER";
00869    case AST_CDR_FAILED:
00870       return "FAILED";     
00871    case AST_CDR_BUSY:
00872       return "BUSY";    
00873    case AST_CDR_ANSWERED:
00874       return "ANSWERED";
00875    }
00876    return "UNKNOWN";
00877 }

int ast_cdr_disposition ( struct ast_cdr cdr,
int  cause 
)

Save the result of the call based on the AST_CAUSE_*

Parameters:
cdr the cdr you wish to associate with the call Returns nothing
cause the AST_CAUSE_*

Definition at line 743 of file cdr.c.

Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), clear_caller(), and findmeexec().

00744 {
00745    int res = 0;
00746 
00747    for (; cdr; cdr = cdr->next) {
00748       switch(cause) {
00749       case AST_CAUSE_BUSY:
00750          ast_cdr_busy(cdr);
00751          break;
00752       case AST_CAUSE_FAILURE:
00753          ast_cdr_failed(cdr);
00754          break;
00755       case AST_CAUSE_NORMAL:
00756          break;
00757       case AST_CAUSE_NOTDEFINED:
00758          res = -1;
00759          break;
00760       default:
00761          res = -1;
00762          ast_log(LOG_WARNING, "Cause not handled\n");
00763       }
00764    }
00765    return res;
00766 }

struct ast_cdr* ast_cdr_dup ( struct ast_cdr cdr  )  [read]

Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).

Duplicate a CDR record

Returns:
Pointer to new CDR record

Definition at line 167 of file cdr.c.

Referenced by ast_async_goto(), ast_cdr_fork(), ast_cdr_merge(), and ast_cdr_reset().

00168 {
00169    struct ast_cdr *newcdr;
00170    
00171    if (!cdr) /* don't die if we get a null cdr pointer */
00172       return NULL;
00173    newcdr = ast_cdr_alloc();
00174    if (!newcdr)
00175       return NULL;
00176 
00177    memcpy(newcdr, cdr, sizeof(*newcdr));
00178    /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */
00179    memset(&newcdr->varshead, 0, sizeof(newcdr->varshead));
00180    ast_cdr_copy_vars(newcdr, cdr);
00181    newcdr->next = NULL;
00182 
00183    return newcdr;
00184 }

void ast_cdr_end ( struct ast_cdr cdr  ) 

End a call

Parameters:
cdr the cdr you have associated the call with Registers the end of call time in the cdr structure. Returns nothing

Definition at line 847 of file cdr.c.

Referenced by __ast_pbx_run(), __ast_read(), __ast_request_and_dial(), ast_cdr_reset(), ast_feature_request_and_dial(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), clear_caller(), and findmeexec().

00848 {
00849    for ( ; cdr ; cdr = cdr->next) {
00850       check_post(cdr);
00851       if (ast_tvzero(cdr->end))
00852          cdr->end = ast_tvnow();
00853       if (ast_tvzero(cdr->start)) {
00854          ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>"));
00855          cdr->disposition = AST_CDR_FAILED;
00856       } else
00857          cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
00858       cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec;
00859    }
00860 }

int ast_cdr_engine_init ( void   ) 

Load the configuration file cdr.conf and possibly start the CDR scheduling thread

Definition at line 1406 of file cdr.c.

Referenced by main().

01407 {
01408    int res;
01409 
01410    sched = sched_context_create();
01411    if (!sched) {
01412       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
01413       return -1;
01414    }
01415 
01416    ast_cli_register(&cli_status);
01417 
01418    res = do_reload();
01419    if (res) {
01420       ast_mutex_lock(&cdr_batch_lock);
01421       res = init_batch();
01422       ast_mutex_unlock(&cdr_batch_lock);
01423    }
01424 
01425    return res;
01426 }

int ast_cdr_engine_reload ( void   ) 

Reload the configuration file cdr.conf and start/stop CDR scheduling thread

Definition at line 1435 of file cdr.c.

01436 {
01437    return do_reload();
01438 }

void ast_cdr_engine_term ( void   ) 

Submit any remaining CDRs and prepare for shutdown

Definition at line 1430 of file cdr.c.

Referenced by do_reload(), and quit_handler().

01431 {
01432    ast_cdr_submit_batch(batchsafeshutdown);
01433 }

void ast_cdr_failed ( struct ast_cdr cdr  ) 

Fail a call

Parameters:
cdr the cdr you wish to associate with the call Returns nothing

Definition at line 716 of file cdr.c.

Referenced by __ast_request_and_dial(), ast_cdr_disposition(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), clear_caller(), and findmeexec().

00717 {
00718    for (; cdr; cdr = cdr->next) {
00719       check_post(cdr);
00720       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00721          if (cdr->disposition < AST_CDR_FAILED)
00722             cdr->disposition = AST_CDR_FAILED;
00723       }
00724    }
00725 }

char* ast_cdr_flags2str ( int  flag  ) 

Converts AMA flag to printable string

Definition at line 880 of file cdr.c.

Referenced by _sip_show_peer(), ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), manager_log(), sip_show_user(), and tds_log().

00881 {
00882    switch(flag) {
00883    case AST_CDR_OMIT:
00884       return "OMIT";
00885    case AST_CDR_BILLING:
00886       return "BILLING";
00887    case AST_CDR_DOCUMENTATION:
00888       return "DOCUMENTATION";
00889    }
00890    return "Unknown";
00891 }

void ast_cdr_free ( struct ast_cdr cdr  ) 

Free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing

Definition at line 425 of file cdr.c.

Referenced by ast_cdr_detach(), and do_batch_backend_process().

00426 {
00427 
00428    while (cdr) {
00429       struct ast_cdr *next = cdr->next;
00430       char *chan = S_OR(cdr->channel, "<unknown>");
00431       if (!ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
00432          ast_log(LOG_NOTICE, "CDR on channel '%s' not posted\n", chan);
00433       if (ast_tvzero(cdr->end))
00434          ast_log(LOG_NOTICE, "CDR on channel '%s' lacks end\n", chan);
00435       if (ast_tvzero(cdr->start))
00436          ast_log(LOG_NOTICE, "CDR on channel '%s' lacks start\n", chan);
00437 
00438       ast_cdr_free_vars(cdr, 0);
00439       free(cdr);
00440       cdr = next;
00441    }
00442 }

void ast_cdr_free_vars ( struct ast_cdr cdr,
int  recur 
)

Definition at line 404 of file cdr.c.

Referenced by ast_cdr_discard(), ast_cdr_fork(), ast_cdr_free(), and ast_cdr_reset().

00405 {
00406 
00407    /* clear variables */
00408    for (; cdr; cdr = recur ? cdr->next : NULL) {
00409       struct ast_var_t *vardata;
00410       struct varshead *headp = &cdr->varshead;
00411       while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
00412          ast_var_delete(vardata);
00413    }
00414 }

void ast_cdr_getvar ( struct ast_cdr cdr,
const char *  name,
char **  ret,
char *  workspace,
int  workspacelen,
int  recur,
int  raw 
)

CDR channel variable retrieval

Definition at line 219 of file cdr.c.

Referenced by ast_cdr_serialize_variables(), and cdr_read().

00220 {
00221    const char *fmt = "%Y-%m-%d %T";
00222    const char *varbuf;
00223 
00224    if (!cdr)  /* don't die if the cdr is null */
00225       return;
00226 
00227    *ret = NULL;
00228    /* special vars (the ones from the struct ast_cdr when requested by name) 
00229       I'd almost say we should convert all the stringed vals to vars */
00230 
00231    if (!strcasecmp(name, "clid"))
00232       ast_copy_string(workspace, cdr->clid, workspacelen);
00233    else if (!strcasecmp(name, "src"))
00234       ast_copy_string(workspace, cdr->src, workspacelen);
00235    else if (!strcasecmp(name, "dst"))
00236       ast_copy_string(workspace, cdr->dst, workspacelen);
00237    else if (!strcasecmp(name, "dcontext"))
00238       ast_copy_string(workspace, cdr->dcontext, workspacelen);
00239    else if (!strcasecmp(name, "channel"))
00240       ast_copy_string(workspace, cdr->channel, workspacelen);
00241    else if (!strcasecmp(name, "dstchannel"))
00242       ast_copy_string(workspace, cdr->dstchannel, workspacelen);
00243    else if (!strcasecmp(name, "lastapp"))
00244       ast_copy_string(workspace, cdr->lastapp, workspacelen);
00245    else if (!strcasecmp(name, "lastdata"))
00246       ast_copy_string(workspace, cdr->lastdata, workspacelen);
00247    else if (!strcasecmp(name, "start"))
00248       cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
00249    else if (!strcasecmp(name, "answer"))
00250       cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
00251    else if (!strcasecmp(name, "end"))
00252       cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
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       if (raw) {
00259          snprintf(workspace, workspacelen, "%ld", cdr->disposition);
00260       } else {
00261          ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
00262       }
00263    } else if (!strcasecmp(name, "amaflags")) {
00264       if (raw) {
00265          snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
00266       } else {
00267          ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen);
00268       }
00269    } else if (!strcasecmp(name, "accountcode"))
00270       ast_copy_string(workspace, cdr->accountcode, workspacelen);
00271    else if (!strcasecmp(name, "uniqueid"))
00272       ast_copy_string(workspace, cdr->uniqueid, workspacelen);
00273    else if (!strcasecmp(name, "userfield"))
00274       ast_copy_string(workspace, cdr->userfield, workspacelen);
00275    else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur)))
00276       ast_copy_string(workspace, varbuf, workspacelen);
00277    else
00278       workspace[0] = '\0';
00279 
00280    if (!ast_strlen_zero(workspace))
00281       *ret = workspace;
00282 }

static const char* ast_cdr_getvar_internal ( struct ast_cdr cdr,
const char *  name,
int  recur 
) [static]

Definition at line 186 of file cdr.c.

References AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_name(), ast_var_value(), ast_cdr::next, and ast_cdr::varshead.

Referenced by ast_cdr_getvar().

00187 {
00188    if (ast_strlen_zero(name))
00189       return NULL;
00190 
00191    for (; cdr; cdr = recur ? cdr->next : NULL) {
00192       struct ast_var_t *variables;
00193       struct varshead *headp = &cdr->varshead;
00194       AST_LIST_TRAVERSE(headp, variables, entries) {
00195          if (!strcasecmp(name, ast_var_name(variables)))
00196             return ast_var_value(variables);
00197       }
00198    }
00199 
00200    return NULL;
00201 }

int ast_cdr_init ( struct ast_cdr cdr,
struct ast_channel chan 
)

Initialize based on a channel.

Parameters:
cdr Call Detail Record to use for channel
chan Channel to bind CDR with Initializes a CDR and associates it with a particular channel Return is negligible. (returns 0 by default)

Definition at line 822 of file cdr.c.

Referenced by __ast_pbx_run(), __ast_read(), __ast_request_and_dial(), ast_bridge_call(), ast_channel_alloc(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().

00823 {
00824    char *chan;
00825 
00826    for ( ; cdr ; cdr = cdr->next) {
00827       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00828          chan = S_OR(cdr->channel, "<unknown>");
00829          if (!ast_strlen_zero(cdr->channel)) 
00830             ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan); 
00831          ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
00832          set_one_cid(cdr, c);
00833 
00834          cdr->disposition = (c->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
00835          cdr->amaflags = c->amaflags ? c->amaflags :  ast_default_amaflags;
00836          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00837          /* Destination information */
00838          ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst));
00839          ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext));
00840          /* Unique call identifier */
00841          ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid));
00842       }
00843    }
00844    return 0;
00845 }

void ast_cdr_merge ( struct ast_cdr to,
struct ast_cdr from 
)

Move the non-null data from the "from" cdr to the "to" cdr

Parameters:
to the cdr to get the goodies
from the cdr to give the goodies

Definition at line 500 of file cdr.c.

Referenced by ast_bridge_call().

00501 {
00502    struct ast_cdr *zcdr;
00503    struct ast_cdr *lto = NULL;
00504    struct ast_cdr *lfrom = NULL;
00505    int discard_from = 0;
00506    
00507    if (!to || !from)
00508       return;
00509 
00510    /* don't merge into locked CDR's -- it's bad business */
00511    if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) {
00512       zcdr = to; /* safety valve? */
00513       while (to->next) {
00514          lto = to;
00515          to = to->next;
00516       }
00517       
00518       if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) {
00519          ast_log(LOG_WARNING, "Merging into locked CDR... no choice.");
00520          to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */
00521          lto = NULL;
00522       }
00523    }
00524 
00525    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) {
00526       discard_from = 1;
00527       if (lto) {
00528          struct ast_cdr *llfrom = NULL;
00529          /* insert the from stuff after lto */
00530          lto->next = from;
00531          lfrom = from;
00532          while (lfrom && lfrom->next) {
00533             if (!lfrom->next->next)
00534                llfrom = lfrom;
00535             lfrom = lfrom->next; 
00536          }
00537          /* rip off the last entry and put a copy of the to at the end */
00538          llfrom->next = to;
00539          from = lfrom;
00540       } else {
00541          /* save copy of the current *to cdr */
00542          struct ast_cdr tcdr;
00543          struct ast_cdr *llfrom = NULL;
00544          memcpy(&tcdr, to, sizeof(tcdr));
00545          /* copy in the locked from cdr */
00546          memcpy(to, from, sizeof(*to));
00547          lfrom = from;
00548          while (lfrom && lfrom->next) {
00549             if (!lfrom->next->next)
00550                llfrom = lfrom;
00551             lfrom = lfrom->next; 
00552          }
00553          from->next = NULL;
00554          /* rip off the last entry and put a copy of the to at the end */
00555          if (llfrom == from)
00556             to = to->next = ast_cdr_dup(&tcdr);
00557          else
00558             to = llfrom->next = ast_cdr_dup(&tcdr);
00559          from = lfrom;
00560       }
00561    }
00562    
00563    if (!ast_tvzero(from->start)) {
00564       if (!ast_tvzero(to->start)) {
00565          if (ast_tvcmp(to->start, from->start) > 0 ) {
00566             to->start = from->start; /* use the earliest time */
00567             from->start = ast_tv(0,0); /* we actively "steal" these values */
00568          }
00569          /* else nothing to do */
00570       } else {
00571          to->start = from->start;
00572          from->start = ast_tv(0,0); /* we actively "steal" these values */
00573       }
00574    }
00575    if (!ast_tvzero(from->answer)) {
00576       if (!ast_tvzero(to->answer)) {
00577          if (ast_tvcmp(to->answer, from->answer) > 0 ) {
00578             to->answer = from->answer; /* use the earliest time */
00579             from->answer = ast_tv(0,0); /* we actively "steal" these values */
00580          }
00581          /* we got the earliest answer time, so we'll settle for that? */
00582       } else {
00583          to->answer = from->answer;
00584          from->answer = ast_tv(0,0); /* we actively "steal" these values */
00585       }
00586    }
00587    if (!ast_tvzero(from->end)) {
00588       if (!ast_tvzero(to->end)) {
00589          if (ast_tvcmp(to->end, from->end) < 0 ) {
00590             to->end = from->end; /* use the latest time */
00591             from->end = ast_tv(0,0); /* we actively "steal" these values */
00592             to->duration = to->end.tv_sec - to->start.tv_sec;  /* don't forget to update the duration, billsec, when we set end */
00593             to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec;
00594          }
00595          /* else, nothing to do */
00596       } else {
00597          to->end = from->end;
00598          from->end = ast_tv(0,0); /* we actively "steal" these values */
00599          to->duration = to->end.tv_sec - to->start.tv_sec;
00600          to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec;
00601       }
00602    }
00603    if (to->disposition < from->disposition) {
00604       to->disposition = from->disposition;
00605       from->disposition = AST_CDR_NOANSWER;
00606    }
00607    if (ast_strlen_zero(to->lastapp) && !ast_strlen_zero(from->lastapp)) {
00608       ast_copy_string(to->lastapp, from->lastapp, sizeof(to->lastapp));
00609       from->lastapp[0] = 0; /* theft */
00610    }
00611    if (ast_strlen_zero(to->lastdata) && !ast_strlen_zero(from->lastdata)) {
00612       ast_copy_string(to->lastdata, from->lastdata, sizeof(to->lastdata));
00613       from->lastdata[0] = 0; /* theft */
00614    }
00615    if (ast_strlen_zero(to->dcontext) && !ast_strlen_zero(from->dcontext)) {
00616       ast_copy_string(to->dcontext, from->dcontext, sizeof(to->dcontext));
00617       from->dcontext[0] = 0; /* theft */
00618    }
00619    if (ast_strlen_zero(to->dstchannel) && !ast_strlen_zero(from->dstchannel)) {
00620       ast_copy_string(to->dstchannel, from->dstchannel, sizeof(to->dstchannel));
00621       from->dstchannel[0] = 0; /* theft */
00622    }
00623    if (!ast_strlen_zero(from->channel) && (ast_strlen_zero(to->channel) || !strncasecmp(from->channel, "Agent/", 6))) {
00624       ast_copy_string(to->channel, from->channel, sizeof(to->channel));
00625       from->channel[0] = 0; /* theft */
00626    }
00627    if (ast_strlen_zero(to->src) && !ast_strlen_zero(from->src)) {
00628       ast_copy_string(to->src, from->src, sizeof(to->src));
00629       from->src[0] = 0; /* theft */
00630    }
00631    if (ast_strlen_zero(to->clid) && !ast_strlen_zero(from->clid)) {
00632       ast_copy_string(to->clid, from->clid, sizeof(to->clid));
00633       from->clid[0] = 0; /* theft */
00634    }
00635    if (ast_strlen_zero(to->dst) && !ast_strlen_zero(from->dst)) {
00636       ast_copy_string(to->dst, from->dst, sizeof(to->dst));
00637       from->dst[0] = 0; /* theft */
00638    }
00639    if (!to->amaflags)
00640       to->amaflags = AST_CDR_DOCUMENTATION;
00641    if (!from->amaflags)
00642       from->amaflags = AST_CDR_DOCUMENTATION; /* make sure both amaflags are set to something (DOC is default) */
00643    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) {
00644       to->amaflags = from->amaflags;
00645    }
00646    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) {
00647       ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode));
00648    }
00649    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) {
00650       ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield));
00651    }
00652    /* flags, varsead, ? */
00653    cdr_merge_vars(from, to);
00654 
00655    if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS))
00656       ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS);
00657    if (ast_test_flag(from, AST_CDR_FLAG_POSTED))
00658       ast_set_flag(to, AST_CDR_FLAG_POSTED);
00659    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED))
00660       ast_set_flag(to, AST_CDR_FLAG_LOCKED);
00661    if (ast_test_flag(from, AST_CDR_FLAG_CHILD))
00662       ast_set_flag(to, AST_CDR_FLAG_CHILD);
00663    if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED))
00664       ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED);
00665 
00666    /* last, but not least, we need to merge any forked CDRs to the 'to' cdr */
00667    while (from->next) {
00668       /* just rip 'em off the 'from' and insert them on the 'to' */
00669       zcdr = from->next;
00670       from->next = zcdr->next;
00671       zcdr->next = NULL;
00672       /* zcdr is now ripped from the current list; */
00673       ast_cdr_append(to, zcdr);
00674    }
00675    if (discard_from)
00676       ast_cdr_discard(from);
00677 }

void ast_cdr_noanswer ( struct ast_cdr cdr  ) 

A call wasn't answered

Parameters:
cdr the cdr you wish to associate with the call Marks the channel disposition as "NO ANSWER"

Definition at line 727 of file cdr.c.

Referenced by wait_for_answer().

00728 {
00729    char *chan; 
00730 
00731    while (cdr) {
00732       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00733       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00734          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00735       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00736          if (cdr->disposition < AST_CDR_NOANSWER)
00737             cdr->disposition = AST_CDR_NOANSWER;
00738       }
00739       cdr = cdr->next;
00740    }
00741 }

int ast_cdr_register ( const char *  name,
const char *  desc,
ast_cdrbe  be 
)

Register a CDR driver. Each registered CDR driver generates a CDR

Returns:
0 on success, -1 on failure

Definition at line 108 of file cdr.c.

Referenced by load_module(), odbc_load_module(), process_my_load_module(), and tds_load_module().

00109 {
00110    struct ast_cdr_beitem *i;
00111 
00112    if (!name)
00113       return -1;
00114    if (!be) {
00115       ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
00116       return -1;
00117    }
00118 
00119    AST_LIST_LOCK(&be_list);
00120    AST_LIST_TRAVERSE(&be_list, i, list) {
00121       if (!strcasecmp(name, i->name))
00122          break;
00123    }
00124    AST_LIST_UNLOCK(&be_list);
00125 
00126    if (i) {
00127       ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
00128       return -1;
00129    }
00130 
00131    if (!(i = ast_calloc(1, sizeof(*i))))  
00132       return -1;
00133 
00134    i->be = be;
00135    ast_copy_string(i->name, name, sizeof(i->name));
00136    ast_copy_string(i->desc, desc, sizeof(i->desc));
00137 
00138    AST_LIST_LOCK(&be_list);
00139    AST_LIST_INSERT_HEAD(&be_list, i, list);
00140    AST_LIST_UNLOCK(&be_list);
00141 
00142    return 0;
00143 }

void ast_cdr_reset ( struct ast_cdr cdr,
struct ast_flags flags 
)

Reset the detail record, optionally posting it first

Parameters:
cdr which cdr to act upon
flags |AST_CDR_FLAG_POSTED whether or not to post the cdr first before resetting it |AST_CDR_FLAG_LOCKED whether or not to reset locked CDR's

Definition at line 1003 of file cdr.c.

Referenced by ast_bridge_call_thread(), ast_cdr_fork(), disa_exec(), and pbx_builtin_resetcdr().

01004 {
01005    struct ast_cdr *dup;
01006    struct ast_flags flags = { 0 };
01007 
01008    if (_flags)
01009       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
01010 
01011    for ( ; cdr ; cdr = cdr->next) {
01012       /* Detach if post is requested */
01013       if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01014          if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
01015             ast_cdr_end(cdr);
01016             if ((dup = ast_cdr_dup(cdr))) {
01017                ast_cdr_detach(dup);
01018             }
01019             ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
01020          }
01021 
01022          /* clear variables */
01023          if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
01024             ast_cdr_free_vars(cdr, 0);
01025          }
01026 
01027          /* Reset to initial state */
01028          ast_clear_flag(cdr, AST_FLAGS_ALL); 
01029          memset(&cdr->start, 0, sizeof(cdr->start));
01030          memset(&cdr->end, 0, sizeof(cdr->end));
01031          memset(&cdr->answer, 0, sizeof(cdr->answer));
01032          cdr->billsec = 0;
01033          cdr->duration = 0;
01034          ast_cdr_start(cdr);
01035          cdr->disposition = AST_CDR_NULL;
01036       }
01037    }
01038 }

int ast_cdr_serialize_variables ( struct ast_cdr cdr,
char *  buf,
size_t  size,
char  delim,
char  sep,
int  recur 
)

Definition at line 360 of file cdr.c.

Referenced by handle_showchan(), and handle_showchan_deprecated().

00361 {
00362    struct ast_var_t *variables;
00363    const char *var, *val;
00364    char *tmp;
00365    char workspace[256];
00366    int total = 0, x = 0, i;
00367 
00368    memset(buf, 0, size);
00369 
00370    for (; cdr; cdr = recur ? cdr->next : NULL) {
00371       if (++x > 1)
00372          ast_build_string(&buf, &size, "\n");
00373 
00374       AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
00375          if (variables &&
00376              (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00377              !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00378             if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, var, delim, val, sep)) {
00379                ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00380                break;
00381             } else
00382                total++;
00383          } else 
00384             break;
00385       }
00386 
00387       for (i = 0; cdr_readonly_vars[i]; i++) {
00388          ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0);
00389          if (!tmp)
00390             continue;
00391          
00392          if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep)) {
00393             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00394             break;
00395          } else
00396             total++;
00397       }
00398    }
00399 
00400    return total;
00401 }

int ast_cdr_setaccount ( struct ast_channel chan,
const char *  account 
)

Definition at line 893 of file cdr.c.

Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), auth_exec(), cdr_write(), and rpt_call().

00894 {
00895    struct ast_cdr *cdr = chan->cdr;
00896 
00897    ast_string_field_set(chan, accountcode, account);
00898    for ( ; cdr ; cdr = cdr->next) {
00899       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00900          ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode));
00901       }
00902    }
00903    return 0;
00904 }

int ast_cdr_setamaflags ( struct ast_channel chan,
const char *  flag 
)

Definition at line 906 of file cdr.c.

Referenced by cdr_write(), and pbx_builtin_setamaflags().

00907 {
00908    struct ast_cdr *cdr;
00909    int newflag = ast_cdr_amaflags2int(flag);
00910    if (newflag) {
00911       for (cdr = chan->cdr; cdr; cdr = cdr->next) {
00912          if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00913             cdr->amaflags = newflag;
00914          }
00915       }
00916    }
00917 
00918    return 0;
00919 }

void ast_cdr_setapp ( struct ast_cdr cdr,
char *  app,
char *  data 
)

Set the last executed application

Parameters:
cdr which cdr to act upon
app the name of the app you wish to change it to
data the data you want in the data field of app you set it to Changes the value of the last executed app Returns nothing

Definition at line 777 of file cdr.c.

Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), builtin_blindtransfer(), clear_caller(), findmeexec(), and pbx_exec().

00778 {
00779 
00780    for (; cdr; cdr = cdr->next) {
00781       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00782          check_post(cdr);
00783          if (!app)
00784             app = "";
00785          ast_copy_string(cdr->lastapp, app, sizeof(cdr->lastapp));
00786          if (!data)
00787             data = "";
00788          ast_copy_string(cdr->lastdata, data, sizeof(cdr->lastdata));
00789       }
00790    }
00791 }

int ast_cdr_setcid ( struct ast_cdr cdr,
struct ast_channel chan 
)

Initialize based on a channel

Parameters:
cdr Call Detail Record to use for channel
chan Channel to bind CDR with Initializes a CDR and associates it with a particular channel Return is negligible. (returns 0 by default)

Definition at line 813 of file cdr.c.

Referenced by ast_set_callerid().

00814 {
00815    for (; cdr; cdr = cdr->next) {
00816       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00817          set_one_cid(cdr, c);
00818    }
00819    return 0;
00820 }

void ast_cdr_setdestchan ( struct ast_cdr cdr,
const char *  chan 
)

Set the destination channel, if there was one

Parameters:
cdr Which cdr it's applied to
chan Channel to which dest will be Sets the destination channel the CDR is applied to Returns nothing

Definition at line 768 of file cdr.c.

Referenced by ast_bridge_call(), ast_bridge_call_thread(), builtin_blindtransfer(), park_exec(), and try_calling().

00769 {
00770    for (; cdr; cdr = cdr->next) {
00771       check_post(cdr);
00772       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00773          ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel));
00774    }
00775 }

int ast_cdr_setuserfield ( struct ast_channel chan,
const char *  userfield 
)

Definition at line 921 of file cdr.c.

Referenced by __agent_start_monitoring(), action_setcdruserfield(), ast_bridge_call(), cdr_write(), handle_request_info(), setcdruserfield_exec(), and start_monitor_exec().

00922 {
00923    struct ast_cdr *cdr = chan->cdr;
00924 
00925    for ( ; cdr ; cdr = cdr->next) {
00926       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 
00927          ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield));
00928    }
00929 
00930    return 0;
00931 }

int ast_cdr_setvar ( struct ast_cdr cdr,
const char *  name,
const char *  value,
int  recur 
)

Set a CDR channel variable

Note:
You can't set the CDR variables that belong to the actual CDR record, like "billsec".

Definition at line 292 of file cdr.c.

Referenced by cdr_write().

00293 {
00294    struct ast_var_t *newvariable;
00295    struct varshead *headp;
00296    int x;
00297    
00298    if (!cdr)  /* don't die if the cdr is null */
00299       return -1;
00300    
00301    for(x = 0; cdr_readonly_vars[x]; x++) {
00302       if (!strcasecmp(name, cdr_readonly_vars[x])) {
00303          ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name);
00304          return -1;
00305       }
00306    }
00307 
00308    if (!cdr) {
00309       ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n");
00310       return -1;
00311    }
00312 
00313    for (; cdr; cdr = recur ? cdr->next : NULL) {
00314       headp = &cdr->varshead;
00315       AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
00316          if (!strcasecmp(ast_var_name(newvariable), name)) {
00317             /* there is already such a variable, delete it */
00318             AST_LIST_REMOVE_CURRENT(headp, entries);
00319             ast_var_delete(newvariable);
00320             break;
00321          }
00322       }
00323       AST_LIST_TRAVERSE_SAFE_END;
00324 
00325       if (value) {
00326          newvariable = ast_var_assign(name, value);
00327          AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00328       }
00329    }
00330 
00331    return 0;
00332 }

void ast_cdr_start ( struct ast_cdr cdr  ) 

Start a call

Parameters:
cdr the cdr you wish to associate with the call Starts all CDR stuff necessary for monitoring a call Returns nothing

Definition at line 679 of file cdr.c.

Referenced by __ast_pbx_run(), __ast_read(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_reset(), ast_channel_alloc(), ast_feature_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().

00680 {
00681    char *chan; 
00682 
00683    for (; cdr; cdr = cdr->next) {
00684       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00685          chan = S_OR(cdr->channel, "<unknown>");
00686          check_post(cdr);
00687          cdr->start = ast_tvnow();
00688       }
00689    }
00690 }

void ast_cdr_submit_batch ( int  shutdown  ) 

Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines

Parameters:
shutdown Whether or not we are shutting down Blocks the asterisk shutdown procedures until the CDR data is submitted. Returns nothing

Definition at line 1094 of file cdr.c.

Referenced by ast_cdr_engine_term(), and submit_scheduled_batch().

01095 {
01096    struct ast_cdr_batch_item *oldbatchitems = NULL;
01097    pthread_attr_t attr;
01098    pthread_t batch_post_thread = AST_PTHREADT_NULL;
01099 
01100    /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
01101    if (!batch || !batch->head)
01102       return;
01103 
01104    /* move the old CDRs aside, and prepare a new CDR batch */
01105    ast_mutex_lock(&cdr_batch_lock);
01106    oldbatchitems = batch->head;
01107    reset_batch();
01108    ast_mutex_unlock(&cdr_batch_lock);
01109 
01110    /* if configured, spawn a new thread to post these CDRs,
01111       also try to save as much as possible if we are shutting down safely */
01112    if (batchscheduleronly || shutdown) {
01113       if (option_debug)
01114          ast_log(LOG_DEBUG, "CDR single-threaded batch processing begins now\n");
01115       do_batch_backend_process(oldbatchitems);
01116    } else {
01117       pthread_attr_init(&attr);
01118       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01119       if (ast_pthread_create_background(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) {
01120          ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
01121          do_batch_backend_process(oldbatchitems);
01122       } else {
01123          if (option_debug)
01124             ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n");
01125       }
01126       pthread_attr_destroy(&attr);
01127    }
01128 }

void ast_cdr_unregister ( const char *  name  ) 

unregister a CDR driver

Definition at line 146 of file cdr.c.

Referenced by my_unload_module(), odbc_unload_module(), tds_unload_module(), and unload_module().

00147 {
00148    struct ast_cdr_beitem *i = NULL;
00149 
00150    AST_LIST_LOCK(&be_list);
00151    AST_LIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) {
00152       if (!strcasecmp(name, i->name)) {
00153          AST_LIST_REMOVE_CURRENT(&be_list, list);
00154          if (option_verbose > 1)
00155             ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s' CDR backend\n", name);
00156          free(i);
00157          break;
00158       }
00159    }
00160    AST_LIST_TRAVERSE_SAFE_END;
00161    AST_LIST_UNLOCK(&be_list);
00162 }

int ast_cdr_update ( struct ast_channel c  ) 

Definition at line 947 of file cdr.c.

Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_feature_request_and_dial(), ast_parseable_goto(), cb_events(), clear_caller(), and findmeexec().

00948 {
00949    struct ast_cdr *cdr = c->cdr;
00950 
00951    for ( ; cdr ; cdr = cdr->next) {
00952       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00953          set_one_cid(cdr, c);
00954 
00955          /* Copy account code et-al */ 
00956          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00957          
00958          /* Destination information */ /* XXX privilege macro* ? */
00959          ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst));
00960          ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext));
00961       }
00962    }
00963 
00964    return 0;
00965 }

static AST_LIST_HEAD_STATIC ( be_list  ,
ast_cdr_beitem   
) [static]

AST_MUTEX_DEFINE_STATIC ( cdr_pending_lock   ) 

AST_MUTEX_DEFINE_STATIC ( cdr_batch_lock   ) 

static void cdr_get_tv ( struct timeval  tv,
const char *  fmt,
char *  buf,
int  bufsize 
) [static]

Definition at line 203 of file cdr.c.

References ast_localtime(), and t.

Referenced by ast_cdr_getvar().

00204 {
00205    if (fmt == NULL) {   /* raw mode */
00206       snprintf(buf, bufsize, "%ld.%06ld", (long)tv.tv_sec, (long)tv.tv_usec);
00207    } else {  
00208       time_t t = tv.tv_sec;
00209       if (t) {
00210          struct tm tm;
00211 
00212          ast_localtime(&t, &tm, NULL);
00213          strftime(buf, bufsize, fmt, &tm);
00214       }
00215    }
00216 }

static void cdr_merge_vars ( struct ast_cdr to,
struct ast_cdr from 
) [static]

Definition at line 464 of file cdr.c.

References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_var_name(), ast_var_value(), LOG_NOTICE, and ast_cdr::varshead.

Referenced by ast_cdr_merge().

00465 {
00466    struct ast_var_t *variablesfrom,*variablesto;
00467    struct varshead *headpfrom = &to->varshead;
00468    struct varshead *headpto = &from->varshead;
00469    AST_LIST_TRAVERSE_SAFE_BEGIN(headpfrom, variablesfrom, entries) {
00470       /* for every var in from, stick it in to */
00471       const char *fromvarname = NULL, *fromvarval = NULL;
00472       const char *tovarname = NULL, *tovarval = NULL;
00473       fromvarname = ast_var_name(variablesfrom);
00474       fromvarval = ast_var_value(variablesfrom);
00475       tovarname = 0;
00476 
00477       /* now, quick see if that var is in the 'to' cdr already */
00478       AST_LIST_TRAVERSE(headpto, variablesto, entries) {
00479 
00480          /* now, quick see if that var is in the 'to' cdr already */
00481          if ( strcasecmp(fromvarname, ast_var_name(variablesto)) == 0 ) {
00482             tovarname = ast_var_name(variablesto);
00483             tovarval = ast_var_value(variablesto);
00484             break;
00485          }
00486       }
00487       if (tovarname && strcasecmp(fromvarval,tovarval) != 0) {  /* this message here to see how irritating the userbase finds it */
00488          ast_log(LOG_NOTICE, "Merging CDR's: variable %s value %s dropped in favor of value %s\n", tovarname, fromvarval, tovarval);
00489          continue;
00490       } else if (tovarname && strcasecmp(fromvarval,tovarval) == 0) /* if they are the same, the job is done */
00491          continue;
00492 
00493       /*rip this var out of the from cdr, and stick it in the to cdr */
00494       AST_LIST_REMOVE_CURRENT(headpfrom, entries);
00495       AST_LIST_INSERT_HEAD(headpto, variablesfrom, entries);
00496    }
00497    AST_LIST_TRAVERSE_SAFE_END;
00498 }

static void check_post ( struct ast_cdr cdr  )  [static]

print a warning if cdr already posted

Definition at line 417 of file cdr.c.

References AST_CDR_FLAG_POSTED, ast_log(), ast_test_flag, ast_cdr::channel, LOG_NOTICE, and S_OR.

Referenced by ast_cdr_answer(), ast_cdr_busy(), ast_cdr_end(), ast_cdr_failed(), ast_cdr_setapp(), ast_cdr_setdestchan(), ast_cdr_start(), and post_cdr().

00418 {
00419    if (!cdr)
00420       return;
00421    if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00422       ast_log(LOG_NOTICE, "CDR on channel '%s' already posted\n", S_OR(cdr->channel, "<unknown>"));
00423 }

static void* do_batch_backend_process ( void *  data  )  [static]

Definition at line 1077 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().

01078 {
01079    struct ast_cdr_batch_item *processeditem;
01080    struct ast_cdr_batch_item *batchitem = data;
01081 
01082    /* Push each CDR into storage mechanism(s) and free all the memory */
01083    while (batchitem) {
01084       post_cdr(batchitem->cdr);
01085       ast_cdr_free(batchitem->cdr);
01086       processeditem = batchitem;
01087       batchitem = batchitem->next;
01088       free(processeditem);
01089    }
01090 
01091    return NULL;
01092 }

static void* do_cdr ( void *  data  )  [static]

Definition at line 1208 of file cdr.c.

References ast_cond_timedwait(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_runq(), ast_sched_wait(), ast_tvadd(), cdr_pending_cond, LOG_DEBUG, and option_debug.

Referenced by do_reload().

01209 {
01210    struct timespec timeout;
01211    int schedms;
01212    int numevents = 0;
01213 
01214    for(;;) {
01215       struct timeval now;
01216       schedms = ast_sched_wait(sched);
01217       /* this shouldn't happen, but provide a 1 second default just in case */
01218       if (schedms <= 0)
01219          schedms = 1000;
01220       now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
01221       timeout.tv_sec = now.tv_sec;
01222       timeout.tv_nsec = now.tv_usec * 1000;
01223       /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
01224       ast_mutex_lock(&cdr_pending_lock);
01225       ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
01226       numevents = ast_sched_runq(sched);
01227       ast_mutex_unlock(&cdr_pending_lock);
01228       if (option_debug > 1)
01229          ast_log(LOG_DEBUG, "Processed %d scheduled CDR batches from the run queue\n", numevents);
01230    }
01231 
01232    return NULL;
01233 }

static int do_reload ( void   )  [static]

Definition at line 1294 of file cdr.c.

References ast_cdr_engine_term(), ast_cli_register(), ast_cli_unregister(), ast_cond_destroy(), ast_cond_init(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN, ast_options, ast_pthread_create_background, AST_PTHREADT_NULL, ast_register_atexit(), ast_sched_add(), ast_sched_del(), ast_set2_flag, ast_true(), ast_unregister_atexit(), ast_variable_retrieve(), BATCH_SAFE_SHUTDOWN_DEFAULT, BATCH_SCHEDULER_ONLY_DEFAULT, BATCH_SIZE_DEFAULT, BATCH_TIME_DEFAULT, batchmode, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_pending_cond, cdr_sched, cdr_thread, cli_submit, config, do_cdr(), enabled, LOG_ERROR, LOG_NOTICE, LOG_WARNING, and submit_scheduled_batch().

Referenced by ast_cdr_engine_init(), ast_cdr_engine_reload(), dnsmgr_init(), dnsmgr_reload(), and handle_cli_reload().

01295 {
01296    struct ast_config *config;
01297    const char *enabled_value;
01298    const char *batched_value;
01299    const char *scheduleronly_value;
01300    const char *batchsafeshutdown_value;
01301    const char *size_value;
01302    const char *time_value;
01303    const char *end_before_h_value;
01304    int cfg_size;
01305    int cfg_time;
01306    int was_enabled;
01307    int was_batchmode;
01308    int res=0;
01309 
01310    ast_mutex_lock(&cdr_batch_lock);
01311 
01312    batchsize = BATCH_SIZE_DEFAULT;
01313    batchtime = BATCH_TIME_DEFAULT;
01314    batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT;
01315    batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT;
01316    was_enabled = enabled;
01317    was_batchmode = batchmode;
01318    enabled = 1;
01319    batchmode = 0;
01320 
01321    /* don't run the next scheduled CDR posting while reloading */
01322    if (cdr_sched > -1)
01323       ast_sched_del(sched, cdr_sched);
01324 
01325    if ((config = ast_config_load("cdr.conf"))) {
01326       if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
01327          enabled = ast_true(enabled_value);
01328       }
01329       if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) {
01330          batchmode = ast_true(batched_value);
01331       }
01332       if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) {
01333          batchscheduleronly = ast_true(scheduleronly_value);
01334       }
01335       if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) {
01336          batchsafeshutdown = ast_true(batchsafeshutdown_value);
01337       }
01338       if ((size_value = ast_variable_retrieve(config, "general", "size"))) {
01339          if (sscanf(size_value, "%d", &cfg_size) < 1)
01340             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value);
01341          else if (size_value < 0)
01342             ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size);
01343          else
01344             batchsize = cfg_size;
01345       }
01346       if ((time_value = ast_variable_retrieve(config, "general", "time"))) {
01347          if (sscanf(time_value, "%d", &cfg_time) < 1)
01348             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value);
01349          else if (time_value < 0)
01350             ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time);
01351          else
01352             batchtime = cfg_time;
01353       }
01354       if ((end_before_h_value = ast_variable_retrieve(config, "general", "endbeforehexten")))
01355          ast_set2_flag(&ast_options, ast_true(end_before_h_value), AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN);
01356    }
01357 
01358    if (enabled && !batchmode) {
01359       ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
01360    } else if (enabled && batchmode) {
01361       cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
01362       ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime);
01363    } else {
01364       ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n");
01365    }
01366 
01367    /* if this reload enabled the CDR batch mode, create the background thread
01368       if it does not exist */
01369    if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) {
01370       ast_cond_init(&cdr_pending_cond, NULL);
01371       if (ast_pthread_create_background(&cdr_thread, NULL, do_cdr, NULL) < 0) {
01372          ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
01373          ast_sched_del(sched, cdr_sched);
01374       } else {
01375          ast_cli_register(&cli_submit);
01376          ast_register_atexit(ast_cdr_engine_term);
01377          res = 0;
01378       }
01379    /* if this reload disabled the CDR and/or batch mode and there is a background thread,
01380       kill it */
01381    } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) {
01382       /* wake up the thread so it will exit */
01383       pthread_cancel(cdr_thread);
01384       pthread_kill(cdr_thread, SIGURG);
01385       pthread_join(cdr_thread, NULL);
01386       cdr_thread = AST_PTHREADT_NULL;
01387       ast_cond_destroy(&cdr_pending_cond);
01388       ast_cli_unregister(&cli_submit);
01389       ast_unregister_atexit(ast_cdr_engine_term);
01390       res = 0;
01391       /* if leaving batch mode, then post the CDRs in the batch,
01392          and don't reschedule, since we are stopping CDR logging */
01393       if (!batchmode && was_batchmode) {
01394          ast_cdr_engine_term();
01395       }
01396    } else {
01397       res = 0;
01398    }
01399 
01400    ast_mutex_unlock(&cdr_batch_lock);
01401    ast_config_destroy(config);
01402 
01403    return res;
01404 }

static int handle_cli_status ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1235 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, RESULT_SHOWUSAGE, and ast_cdr_batch::size.

01236 {
01237    struct ast_cdr_beitem *beitem=NULL;
01238    int cnt=0;
01239    long nextbatchtime=0;
01240 
01241    if (argc > 2)
01242       return RESULT_SHOWUSAGE;
01243 
01244    ast_cli(fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled");
01245    ast_cli(fd, "CDR mode: %s\n", batchmode ? "batch" : "simple");
01246    if (enabled) {
01247       if (batchmode) {
01248          if (batch)
01249             cnt = batch->size;
01250          if (cdr_sched > -1)
01251             nextbatchtime = ast_sched_when(sched, cdr_sched);
01252          ast_cli(fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled");
01253          ast_cli(fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads");
01254          ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, (cnt != 1) ? "s" : "");
01255          ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, (batchsize != 1) ? "s" : "");
01256          ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, (batchtime != 1) ? "s" : "");
01257          ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, (nextbatchtime != 1) ? "s" : "");
01258       }
01259       AST_LIST_LOCK(&be_list);
01260       AST_LIST_TRAVERSE(&be_list, beitem, list) {
01261          ast_cli(fd, "CDR registered backend: %s\n", beitem->name);
01262       }
01263       AST_LIST_UNLOCK(&be_list);
01264    }
01265 
01266    return 0;
01267 }

static int handle_cli_submit ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1269 of file cdr.c.

References ast_cli(), RESULT_SHOWUSAGE, and submit_unscheduled_batch().

01270 {
01271    if (argc > 2)
01272       return RESULT_SHOWUSAGE;
01273 
01274    submit_unscheduled_batch();
01275    ast_cli(fd, "Submitted CDRs to backend engines for processing.  This may take a while.\n");
01276 
01277    return 0;
01278 }

static int init_batch ( void   )  [static]

Note:
Don't call without cdr_batch_lock

Definition at line 1066 of file cdr.c.

References ast_malloc, batch, and reset_batch().

Referenced by ast_cdr_detach(), and ast_cdr_engine_init().

01067 {
01068    /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
01069    if (!(batch = ast_malloc(sizeof(*batch))))
01070       return -1;
01071 
01072    reset_batch();
01073 
01074    return 0;
01075 }

static void post_cdr ( struct ast_cdr cdr  )  [static]

Definition at line 980 of file cdr.c.

References AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_set_flag, ast_test_flag, ast_cdr_beitem::be, ast_cdr::channel, check_post(), ast_cdr::end, LOG_WARNING, ast_cdr::next, S_OR, and ast_cdr::start.

Referenced by ast_cdr_detach(), and do_batch_backend_process().

00981 {
00982    char *chan;
00983    struct ast_cdr_beitem *i;
00984 
00985    for ( ; cdr ; cdr = cdr->next) {
00986       chan = S_OR(cdr->channel, "<unknown>");
00987       check_post(cdr);
00988       if (ast_tvzero(cdr->end))
00989          ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
00990       if (ast_tvzero(cdr->start))
00991          ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
00992       ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
00993       if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
00994          continue;
00995       AST_LIST_LOCK(&be_list);
00996       AST_LIST_TRAVERSE(&be_list, i, list) {
00997          i->be(cdr);
00998       }
00999       AST_LIST_UNLOCK(&be_list);
01000    }
01001 }

static void reset_batch ( void   )  [static]

Note:
Don't call without cdr_batch_lock

Definition at line 1058 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().

01059 {
01060    batch->size = 0;
01061    batch->head = NULL;
01062    batch->tail = NULL;
01063 }

static void set_one_cid ( struct ast_cdr cdr,
struct ast_channel c 
) [static]

Definition at line 794 of file cdr.c.

References ast_strlen_zero(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, S_OR, and ast_cdr::src.

Referenced by ast_cdr_init(), ast_cdr_setcid(), and ast_cdr_update().

00795 {
00796    /* Grab source from ANI or normal Caller*ID */
00797    const char *num = S_OR(c->cid.cid_ani, c->cid.cid_num);
00798    if (!cdr)
00799       return;
00800    if (!ast_strlen_zero(c->cid.cid_name)) {
00801       if (!ast_strlen_zero(num)) /* both name and number */
00802          snprintf(cdr->clid, sizeof(cdr->clid), "\"%s\" <%s>", c->cid.cid_name, num);
00803       else           /* only name */
00804          ast_copy_string(cdr->clid, c->cid.cid_name, sizeof(cdr->clid));
00805    } else if (!ast_strlen_zero(num)) { /* only number */
00806       ast_copy_string(cdr->clid, num, sizeof(cdr->clid));
00807    } else {          /* nothing known */
00808       cdr->clid[0] = '\0';
00809    }
00810    ast_copy_string(cdr->src, S_OR(num, ""), sizeof(cdr->src));
00811 
00812 }

static int submit_scheduled_batch ( void *  data  )  [static]

Definition at line 1130 of file cdr.c.

References ast_cdr_submit_batch(), ast_sched_add(), batchtime, and cdr_sched.

Referenced by do_reload(), and submit_unscheduled_batch().

01131 {
01132    ast_cdr_submit_batch(0);
01133    /* manually reschedule from this point in time */
01134    cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
01135    /* returning zero so the scheduler does not automatically reschedule */
01136    return 0;
01137 }

static void submit_unscheduled_batch ( void   )  [static]

Definition at line 1139 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().

01140 {
01141    /* this is okay since we are not being called from within the scheduler */
01142    if (cdr_sched > -1)
01143       ast_sched_del(sched, cdr_sched);
01144    /* schedule the submission to occur ASAP (1 ms) */
01145    cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
01146    /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
01147    ast_mutex_lock(&cdr_pending_lock);
01148    ast_cond_signal(&cdr_pending_cond);
01149    ast_mutex_unlock(&cdr_pending_lock);
01150 }


Variable Documentation

char ast_default_accountcode[AST_MAX_ACCOUNT_CODE]

Definition at line 60 of file cdr.c.

Referenced by ast_channel_alloc().

int ast_default_amaflags = AST_CDR_DOCUMENTATION

Default AMA flag for billing records (CDR's)

Definition at line 59 of file cdr.c.

Referenced by ast_channel_alloc().

struct ast_cdr_batch * batch [static]

Referenced by ast_cdr_detach(), ast_cdr_submit_batch(), handle_cli_status(), init_batch(), and reset_batch().

int batchmode [static]

Is the CDR subsystem enabled ?

Definition at line 92 of file cdr.c.

Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().

int batchsafeshutdown [static]

Definition at line 96 of file cdr.c.

Referenced by ast_cdr_engine_term(), do_reload(), and handle_cli_status().

int batchscheduleronly [static]

Definition at line 95 of file cdr.c.

Referenced by ast_cdr_submit_batch(), do_reload(), and handle_cli_status().

int batchsize [static]

Definition at line 93 of file cdr.c.

Referenced by ast_cdr_detach(), do_reload(), and handle_cli_status().

int batchtime [static]

Definition at line 94 of file cdr.c.

Referenced by do_reload(), handle_cli_status(), and submit_scheduled_batch().

ast_cond_t cdr_pending_cond [static]

Definition at line 102 of file cdr.c.

Referenced by do_cdr(), do_reload(), and submit_unscheduled_batch().

const char* cdr_readonly_vars[] [static]

Initial value:

 { "clid", "src", "dst", "dcontext", "channel", "dstchannel",
                "lastapp", "lastdata", "start", "answer", "end", "duration",
                "billsec", "disposition", "amaflags", "accountcode", "uniqueid",
                "userfield", NULL }

Definition at line 285 of file cdr.c.

Referenced by ast_cdr_serialize_variables(), and ast_cdr_setvar().

int cdr_sched = -1 [static]

Definition at line 83 of file cdr.c.

Referenced by do_reload(), handle_cli_status(), submit_scheduled_batch(), and submit_unscheduled_batch().

pthread_t cdr_thread = AST_PTHREADT_NULL [static]

Definition at line 84 of file cdr.c.

Referenced by do_reload().

struct ast_cli_entry cli_status [static]

Definition at line 1287 of file cdr.c.

Referenced by ast_cdr_engine_init(), and dnsmgr_init().

struct ast_cli_entry cli_submit [static]

Definition at line 1280 of file cdr.c.

Referenced by do_reload().

int enabled [static]

Definition at line 91 of file cdr.c.

Referenced by __ast_http_load(), ast_cdr_detach(), ast_dnsmgr_lookup(), do_reload(), handle_cli_status(), load_odbc_config(), osp_check_destination(), and reload().

struct sched_context* sched [static]

Definition at line 82 of file cdr.c.


Generated on Wed Aug 15 01:24:46 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.3