Wed Aug 15 01:24:46 2007

Asterisk developer's documentation


cdr.h File Reference

Call Detail Record API. More...

#include <sys/time.h>
#include "asterisk/channel.h"
#include "asterisk/utils.h"

Include dependency graph for cdr.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_cdr

Defines

#define AST_CDR_ANSWERED   (1 << 3)
#define AST_CDR_BILLING   (2)
#define AST_CDR_BUSY   (1 << 1)
#define AST_CDR_DOCUMENTATION   (3)
#define AST_CDR_FAILED   (1 << 0)
#define AST_CDR_FLAG_CHILD   (1 << 3)
#define AST_CDR_FLAG_KEEP_VARS   (1 << 0)
#define AST_CDR_FLAG_LOCKED   (1 << 2)
#define AST_CDR_FLAG_POST_DISABLED   (1 << 4)
#define AST_CDR_FLAG_POSTED   (1 << 1)
#define AST_CDR_NOANSWER   (1 << 2)
#define AST_CDR_NULL   0
#define AST_CDR_OMIT   (1)
#define AST_MAX_ACCOUNT_CODE   20
#define AST_MAX_USER_FIELD   256

Typedefs

typedef int(* ast_cdrbe )(struct ast_cdr *cdr)

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)
 Discard and free a CDR record.
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 flags)
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)
int ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *chan)
 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 *amaflags)
void ast_cdr_setapp (struct ast_cdr *cdr, char *app, char *data)
int ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *chan)
void ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chan)
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 *chan)

Variables

char ast_default_accountcode [AST_MAX_ACCOUNT_CODE]
int ast_default_amaflags


Detailed Description

Call Detail Record API.

Definition in file cdr.h.


Define Documentation

#define AST_CDR_ANSWERED   (1 << 3)

Definition at line 37 of file cdr.h.

Referenced by ast_cdr_answer(), ast_cdr_disp2str(), and ast_cdr_init().

#define AST_CDR_BILLING   (2)

Definition at line 41 of file cdr.h.

Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str().

#define AST_CDR_BUSY   (1 << 1)

Definition at line 35 of file cdr.h.

Referenced by ast_cdr_busy(), and ast_cdr_disp2str().

#define AST_CDR_DOCUMENTATION   (3)

Definition at line 42 of file cdr.h.

Referenced by ast_cdr_amaflags2int(), ast_cdr_flags2str(), and ast_cdr_merge().

#define AST_CDR_FAILED   (1 << 0)

Definition at line 34 of file cdr.h.

Referenced by ast_cdr_disp2str(), ast_cdr_end(), and ast_cdr_failed().

#define AST_CDR_FLAG_CHILD   (1 << 3)

Definition at line 30 of file cdr.h.

Referenced by ast_cdr_fork(), and ast_cdr_merge().

#define AST_CDR_FLAG_KEEP_VARS   (1 << 0)

Definition at line 27 of file cdr.h.

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

#define AST_CDR_FLAG_LOCKED   (1 << 2)

Definition at line 29 of file cdr.h.

Referenced by ast_bridge_call(), ast_cdr_appenduserfield(), ast_cdr_busy(), ast_cdr_failed(), ast_cdr_fork(), ast_cdr_init(), ast_cdr_merge(), ast_cdr_noanswer(), ast_cdr_reset(), ast_cdr_setaccount(), ast_cdr_setamaflags(), ast_cdr_setapp(), ast_cdr_setcid(), ast_cdr_setdestchan(), ast_cdr_setuserfield(), ast_cdr_start(), and ast_cdr_update().

#define AST_CDR_FLAG_POST_DISABLED   (1 << 4)

Definition at line 31 of file cdr.h.

Referenced by ast_cdr_detach(), ast_cdr_free(), ast_cdr_merge(), nocdr_exec(), and post_cdr().

#define AST_CDR_FLAG_POSTED   (1 << 1)

Definition at line 28 of file cdr.h.

Referenced by ast_cdr_free(), ast_cdr_merge(), ast_cdr_noanswer(), ast_cdr_reset(), check_post(), disa_exec(), and post_cdr().

#define AST_CDR_NOANSWER   (1 << 2)

Definition at line 36 of file cdr.h.

Referenced by ast_cdr_disp2str(), ast_cdr_merge(), and ast_cdr_noanswer().

#define AST_CDR_NULL   0

Definition at line 33 of file cdr.h.

Referenced by ast_cdr_disp2str(), ast_cdr_init(), and ast_cdr_reset().

#define AST_CDR_OMIT   (1)

AMA Flags

Definition at line 40 of file cdr.h.

Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str().

#define AST_MAX_ACCOUNT_CODE   20

Definition at line 45 of file cdr.h.

#define AST_MAX_USER_FIELD   256

Definition at line 44 of file cdr.h.


Typedef Documentation

typedef int(* ast_cdrbe)(struct ast_cdr *cdr)

Definition at line 104 of file cdr.h.


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.

References ast_calloc, ast_log(), and LOG_ERROR.

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.

References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.

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.

References ast_cdr::answer, AST_CDR_ANSWERED, check_post(), ast_cdr::disposition, and ast_cdr::next.

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.

References ast_cdr::next.

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.

References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, len, ast_cdr::next, and ast_cdr::userfield.

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.

References AST_CDR_BUSY, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.

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.

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.

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.

References ast_calloc, AST_CDR_FLAG_POST_DISABLED, ast_cdr_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, batch, batchmode, batchsize, ast_cdr_batch_item::cdr, enabled, ast_cdr_batch::head, init_batch(), LOG_DEBUG, ast_cdr_batch_item::next, option_debug, post_cdr(), ast_cdr_batch::size, submit_unscheduled_batch(), and ast_cdr_batch::tail.

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  ) 

Discard and free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing -- same as free, but no checks or complaints

Definition at line 445 of file cdr.c.

References ast_cdr_free_vars(), free, and ast_cdr::next.

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.

References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, AST_CDR_NOANSWER, and AST_CDR_NULL.

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.

References AST_CAUSE_BUSY, AST_CAUSE_FAILURE, AST_CAUSE_NORMAL, AST_CAUSE_NOTDEFINED, ast_cdr_busy(), ast_cdr_failed(), ast_log(), LOG_WARNING, and ast_cdr::next.

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.

References ast_cdr_alloc(), ast_cdr_copy_vars(), ast_cdr::next, and ast_cdr::varshead.

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.

References ast_cdr::answer, AST_CDR_FAILED, ast_log(), ast_cdr::billsec, ast_cdr::channel, check_post(), ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, LOG_WARNING, ast_cdr::next, S_OR, and ast_cdr::start.

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.

References ast_cli_register(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cli_status, do_reload(), init_batch(), LOG_ERROR, and sched_context_create().

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.

References do_reload().

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.

References ast_cdr_submit_batch(), and batchsafeshutdown.

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.

References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.

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  ) 

Flags to a string

Parameters:
flags binary flag Converts binary flags to string flags Returns string with flag name
Converts AMA flag to printable string

Definition at line 880 of file cdr.c.

References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.

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.

References AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), ast_log(), ast_test_flag, ast_cdr::channel, ast_cdr::end, free, LOG_NOTICE, ast_cdr::next, S_OR, and ast_cdr::start.

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.

References AST_LIST_REMOVE_HEAD, ast_var_delete(), ast_cdr::next, and ast_cdr::varshead.

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.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_disp2str(), ast_cdr_flags2str(), ast_cdr_getvar_internal(), ast_strlen_zero(), ast_cdr::billsec, cdr_get_tv(), ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, fmt, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.

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 }

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.

References ast_channel::_state, ast_cdr::accountcode, ast_channel::amaflags, ast_cdr::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NULL, ast_log(), AST_STATE_UP, ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, LOG_WARNING, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, S_OR, set_one_cid(), and ast_cdr::uniqueid.

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.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_append(), ast_cdr_discard(), AST_CDR_DOCUMENTATION, ast_cdr_dup(), AST_CDR_FLAG_CHILD, AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, AST_CDR_NOANSWER, ast_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_cdr::billsec, cdr_merge_vars(), ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, ast_cdr::lastapp, ast_cdr::lastdata, LOG_WARNING, ast_cdr::next, ast_cdr::src, ast_cdr::start, and ast_cdr::userfield.

00501 {
00502    struct ast_cdr *zcdr;
00503    struct ast_cdr *lto = NULL;
00504    struct ast_cdr *lfrom = NULL;
00505    int discard_from = 0;
00506    
00507    if (!to || !from)
00508       return;
00509 
00510    /* don't merge into locked CDR's -- it's bad business */
00511    if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) {
00512       zcdr = to; /* safety valve? */
00513       while (to->next) {
00514          lto = to;
00515          to = to->next;
00516       }
00517       
00518       if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) {
00519          ast_log(LOG_WARNING, "Merging into locked CDR... no choice.");
00520          to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */
00521          lto = NULL;
00522       }
00523    }
00524 
00525    if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) {
00526       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.

References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, AST_CDR_NOANSWER, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::next.

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 handling engine

Parameters:
name name associated with the particular CDR handler
desc description of the CDR handler
be function pointer to a CDR handler Used to register a Call Detail Record handler. Returns -1 on error, 0 on success.
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.

References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_cdr_beitem::be, ast_cdr_beitem::desc, LOG_WARNING, and ast_cdr_beitem::name.

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.

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_NULL, ast_cdr_start(), ast_clear_flag, ast_copy_flags, AST_FLAGS_ALL, ast_set_flag, ast_test_flag, ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, ast_cdr::next, and ast_cdr::start.

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.

References ast_build_string(), ast_cdr_getvar(), AST_LIST_TRAVERSE, ast_log(), ast_strlen_zero(), ast_var_name(), ast_var_value(), cdr_readonly_vars, LOG_ERROR, ast_cdr::next, total, var, and ast_cdr::varshead.

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.

References ast_cdr::accountcode, accountcode, AST_CDR_FLAG_LOCKED, ast_string_field_set, ast_test_flag, ast_channel::cdr, and ast_cdr::next.

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 *  amaflags 
)

Definition at line 906 of file cdr.c.

References ast_cdr::amaflags, ast_cdr_amaflags2int(), AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, and ast_cdr::next.

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.

References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::lastapp, ast_cdr::lastdata, and ast_cdr::next.

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.

References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_cdr::next, and set_one_cid().

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.

References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::dstchannel, and ast_cdr::next.

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.

References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, ast_cdr::next, and ast_cdr::userfield.

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.

References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_var_assign(), ast_var_delete(), ast_var_name(), cdr_readonly_vars, LOG_ERROR, ast_cdr::next, and ast_cdr::varshead.

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.

References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_cdr::channel, check_post(), ast_cdr::next, S_OR, and ast_cdr::start.

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.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, batch, batchscheduleronly, do_batch_backend_process(), ast_cdr_batch::head, LOG_DEBUG, LOG_WARNING, option_debug, and reset_batch().

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 handling engine

Parameters:
name name of CDR handler to unregister Unregisters a CDR by it's name
unregister a CDR driver

Definition at line 146 of file cdr.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), free, ast_cdr_beitem::name, option_verbose, and VERBOSE_PREFIX_2.

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 chan  ) 

Definition at line 947 of file cdr.c.

References ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, ast_channel::context, ast_cdr::dcontext, ast_cdr::dst, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, S_OR, and set_one_cid().

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 }


Variable Documentation

char ast_default_accountcode[AST_MAX_ACCOUNT_CODE]

Definition at line 60 of file cdr.c.

int ast_default_amaflags

Default AMA flag for billing records (CDR's)

Definition at line 59 of file cdr.c.


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