Thu Feb 5 16:26:00 2009

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"

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_ANSLOCKED   (1 << 8)
#define AST_CDR_FLAG_BRIDGED   (1 << 5)
#define AST_CDR_FLAG_CHILD   (1 << 3)
#define AST_CDR_FLAG_DIALED   (1 << 10)
#define AST_CDR_FLAG_DONT_TOUCH   (1 << 9)
#define AST_CDR_FLAG_ENABLE   (1 << 7)
#define AST_CDR_FLAG_KEEP_VARS   (1 << 0)
#define AST_CDR_FLAG_LOCKED   (1 << 2)
#define AST_CDR_FLAG_MAIN   (1 << 6)
#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

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)
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)
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.
int ast_cdr_isset_unanswered (void)
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_specialized_reset (struct ast_cdr *cdr, struct ast_flags *flags)
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)
int check_cdr_enabled (void)
 Return TRUE if CDR subsystem is enabled.

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 46 of file cdr.h.

Referenced by ast_bridge_call(), ast_cdr_answer(), ast_cdr_disp2str(), ast_cdr_end(), ast_cdr_init(), post_cdr(), and wait_for_answer().

#define AST_CDR_BILLING   (2)

Definition at line 50 of file cdr.h.

Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str().

#define AST_CDR_BUSY   (1 << 1)

Definition at line 44 of file cdr.h.

Referenced by ast_cdr_busy(), and ast_cdr_disp2str().

#define AST_CDR_DOCUMENTATION   (3)

Definition at line 51 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 43 of file cdr.h.

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

#define AST_CDR_FLAG_ANSLOCKED   (1 << 8)

Definition at line 37 of file cdr.h.

Referenced by ast_cdr_answer(), and ast_cdr_fork().

#define AST_CDR_FLAG_BRIDGED   (1 << 5)

Definition at line 34 of file cdr.h.

Referenced by ast_bridge_call(), and ast_hangup().

#define AST_CDR_FLAG_CHILD   (1 << 3)

Definition at line 32 of file cdr.h.

Referenced by ast_cdr_fork(), and ast_cdr_merge().

#define AST_CDR_FLAG_DIALED   (1 << 10)

Definition at line 39 of file cdr.h.

Referenced by ast_call(), and ast_hangup().

#define AST_CDR_FLAG_DONT_TOUCH   (1 << 9)

Definition at line 38 of file cdr.h.

Referenced by ast_cdr_answer(), ast_cdr_end(), ast_cdr_fork(), ast_cdr_setvar(), post_cdr(), and try_calling().

#define AST_CDR_FLAG_ENABLE   (1 << 7)

Definition at line 36 of file cdr.h.

#define AST_CDR_FLAG_KEEP_VARS   (1 << 0)

Flags

Definition at line 29 of file cdr.h.

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

#define AST_CDR_FLAG_LOCKED   (1 << 2)

Definition at line 31 of file cdr.h.

Referenced by ast_cdr_answer(), ast_cdr_appenduserfield(), ast_cdr_busy(), ast_cdr_end(), 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_setvar(), ast_cdr_start(), ast_cdr_update(), cdr_read(), pick_unlocked_cdr(), and try_calling().

#define AST_CDR_FLAG_MAIN   (1 << 6)

Definition at line 35 of file cdr.h.

Referenced by ast_bridge_call().

#define AST_CDR_FLAG_POST_DISABLED   (1 << 4)

Definition at line 33 of file cdr.h.

Referenced by ast_bridge_call(), ast_cdr_detach(), ast_cdr_free(), ast_cdr_merge(), ast_cdr_specialized_reset(), ast_hangup(), connect_link(), nocdr_exec(), post_cdr(), rpt(), rpt_call(), and rpt_tele_thread().

#define AST_CDR_FLAG_POSTED   (1 << 1)

Definition at line 30 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 45 of file cdr.h.

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

#define AST_CDR_NULL   0

Disposition

Definition at line 42 of file cdr.h.

Referenced by ast_bridge_call(), ast_cdr_disp2str(), ast_cdr_init(), ast_cdr_reset(), ast_cdr_specialized_reset(), and ast_hangup().

#define AST_CDR_OMIT   (1)

AMA Flags

Definition at line 49 of file cdr.h.

Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str().

#define AST_MAX_ACCOUNT_CODE   20

Definition at line 54 of file cdr.h.

#define AST_MAX_USER_FIELD   256

Definition at line 53 of file cdr.h.

Referenced by tds_log().


Typedef Documentation

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

Definition at line 114 of file cdr.h.


Function Documentation

struct ast_cdr* ast_cdr_alloc ( void   ) 

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

Definition at line 469 of file cdr.c.

References ast_calloc, ast_log(), and LOG_ERROR.

Referenced by __agent_start_monitoring(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_dup(), builtin_blindtransfer(), clear_caller(), findmeexec(), and start_monitor_exec().

00470 {
00471    struct ast_cdr *x = ast_calloc(1, sizeof(struct ast_cdr));
00472    if (!x)
00473       ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n");
00474    return x;
00475 }

int ast_cdr_amaflags2int ( const char *  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 998 of file cdr.c.

References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.

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

00999 {
01000    if (!strcasecmp(flag, "default"))
01001       return 0;
01002    if (!strcasecmp(flag, "omit"))
01003       return AST_CDR_OMIT;
01004    if (!strcasecmp(flag, "billing"))
01005       return AST_CDR_BILLING;
01006    if (!strcasecmp(flag, "documentation"))
01007       return AST_CDR_DOCUMENTATION;
01008    return -1;
01009 }

void ast_cdr_answer ( struct ast_cdr cdr  ) 

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 705 of file cdr.c.

References AST_CDR_ANSWERED, AST_CDR_FLAG_ANSLOCKED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_test_flag, ast_tvnow(), ast_tvzero(), check_post(), and ast_cdr::next.

Referenced by ast_answer(), and ast_bridge_call().

00706 {
00707 
00708    for (; cdr; cdr = cdr->next) {
00709       if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 
00710          continue;
00711       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00712          continue;
00713       check_post(cdr);
00714       if (cdr->disposition < AST_CDR_ANSWERED)
00715          cdr->disposition = AST_CDR_ANSWERED;
00716       if (ast_tvzero(cdr->answer))
00717          cdr->answer = ast_tvnow();
00718    }
00719 }

struct ast_cdr* ast_cdr_append ( struct ast_cdr cdr,
struct ast_cdr newcdr 
)

Definition at line 1101 of file cdr.c.

References ast_cdr::next.

Referenced by ast_cdr_fork(), and ast_cdr_merge().

01102 {
01103    struct ast_cdr *ret;
01104 
01105    if (cdr) {
01106       ret = cdr;
01107 
01108       while (cdr->next)
01109          cdr = cdr->next;
01110       cdr->next = newcdr;
01111    } else {
01112       ret = newcdr;
01113    }
01114 
01115    return ret;
01116 }

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

Definition at line 964 of file cdr.c.

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

Referenced by action_setcdruserfield(), and appendcdruserfield_exec().

00965 {
00966    struct ast_cdr *cdr = chan->cdr;
00967 
00968    for ( ; cdr ; cdr = cdr->next) {
00969       int len = strlen(cdr->userfield);
00970 
00971       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00972          ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len);
00973    }
00974 
00975    return 0;
00976 }

void ast_cdr_busy ( struct ast_cdr cdr  ) 

Parameters:
cdr the cdr you wish to associate with the call Marks the channel disposition as "BUSY" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. Returns nothing

Definition at line 721 of file cdr.c.

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

Referenced by ast_cdr_disposition(), and ring_entry().

00722 {
00723 
00724    for (; cdr; cdr = cdr->next) {
00725       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00726          check_post(cdr);
00727          if (cdr->disposition < AST_CDR_BUSY)
00728             cdr->disposition = AST_CDR_BUSY;
00729       }
00730    }
00731 }

int ast_cdr_copy_vars ( struct ast_cdr to_cdr,
struct ast_cdr from_cdr 
)

Definition at line 346 of file cdr.c.

References AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_assign(), ast_var_name(), ast_var_value(), var, and ast_cdr::varshead.

Referenced by ast_cdr_dup().

00347 {
00348    struct ast_var_t *variables, *newvariable = NULL;
00349    struct varshead *headpa, *headpb;
00350    const char *var, *val;
00351    int x = 0;
00352 
00353    if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */
00354       return 0;
00355 
00356    headpa = &from_cdr->varshead;
00357    headpb = &to_cdr->varshead;
00358 
00359    AST_LIST_TRAVERSE(headpa,variables,entries) {
00360       if (variables &&
00361           (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00362           !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00363          newvariable = ast_var_assign(var, val);
00364          AST_LIST_INSERT_HEAD(headpb, newvariable, entries);
00365          x++;
00366       }
00367    }
00368 
00369    return x;
00370 }

void ast_cdr_detach ( struct ast_cdr cdr  ) 

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 1212 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, cdr_batch_lock, enabled, ast_cdr_batch::head, init_batch(), LOG_DEBUG, ast_cdr_batch_item::next, option_debug, post_cdr(), ast_cdr_batch::size, submit_unscheduled_batch(), and ast_cdr_batch::tail.

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

01213 {
01214    struct ast_cdr_batch_item *newtail;
01215    int curr;
01216 
01217    if (!cdr)
01218       return;
01219 
01220    /* maybe they disabled CDR stuff completely, so just drop it */
01221    if (!enabled) {
01222       if (option_debug)
01223          ast_log(LOG_DEBUG, "Dropping CDR !\n");
01224       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01225       ast_cdr_free(cdr);
01226       return;
01227    }
01228 
01229    /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
01230    if (!batchmode) {
01231       post_cdr(cdr);
01232       ast_cdr_free(cdr);
01233       return;
01234    }
01235 
01236    /* otherwise, each CDR gets put into a batch list (at the end) */
01237    if (option_debug)
01238       ast_log(LOG_DEBUG, "CDR detaching from this thread\n");
01239 
01240    /* we'll need a new tail for every CDR */
01241    if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
01242       post_cdr(cdr);
01243       ast_cdr_free(cdr);
01244       return;
01245    }
01246 
01247    /* don't traverse a whole list (just keep track of the tail) */
01248    ast_mutex_lock(&cdr_batch_lock);
01249    if (!batch)
01250       init_batch();
01251    if (!batch->head) {
01252       /* new batch is empty, so point the head at the new tail */
01253       batch->head = newtail;
01254    } else {
01255       /* already got a batch with something in it, so just append a new tail */
01256       batch->tail->next = newtail;
01257    }
01258    newtail->cdr = cdr;
01259    batch->tail = newtail;
01260    curr = batch->size++;
01261    ast_mutex_unlock(&cdr_batch_lock);
01262 
01263    /* if we have enough stuff to post, then do it */
01264    if (curr >= (batchsize - 1))
01265       submit_unscheduled_batch();
01266 }

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 458 of file cdr.c.

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

Referenced by ast_async_goto(), ast_cdr_merge(), and ast_channel_free().

00459 {
00460    while (cdr) {
00461       struct ast_cdr *next = cdr->next;
00462 
00463       ast_cdr_free_vars(cdr, 0);
00464       free(cdr);
00465       cdr = next;
00466    }
00467 }

char* ast_cdr_disp2str ( int  disposition  ) 

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 893 of file cdr.c.

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

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

00894 {
00895    switch (disposition) {
00896    case AST_CDR_NULL:
00897       return "NO ANSWER"; /* by default, for backward compatibility */
00898    case AST_CDR_NOANSWER:
00899       return "NO ANSWER";
00900    case AST_CDR_FAILED:
00901       return "FAILED";     
00902    case AST_CDR_BUSY:
00903       return "BUSY";    
00904    case AST_CDR_ANSWERED:
00905       return "ANSWERED";
00906    }
00907    return "UNKNOWN";
00908 }

int ast_cdr_disposition ( struct ast_cdr cdr,
int  cause 
)

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

Definition at line 763 of file cdr.c.

References AST_CAUSE_BUSY, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL, ast_cdr_busy(), ast_cdr_noanswer(), and ast_cdr::next.

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

00764 {
00765    int res = 0;
00766 
00767    for (; cdr; cdr = cdr->next) {
00768       switch(cause) {  /* handle all the non failure, busy cases, return 0 not to set disposition,
00769                      return -1 to set disposition to FAILED */
00770       case AST_CAUSE_BUSY:
00771          ast_cdr_busy(cdr);
00772          break;
00773       case AST_CAUSE_NO_ANSWER:
00774          ast_cdr_noanswer(cdr);
00775          break;
00776       case AST_CAUSE_NORMAL:
00777          break;
00778       default:
00779          res = -1;
00780       }
00781    }
00782    return res;
00783 }

struct ast_cdr* ast_cdr_dup ( struct ast_cdr cdr  ) 

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

Duplicate a CDR record

Returns:
Pointer to new CDR record

Definition at line 177 of file cdr.c.

References ast_cdr_alloc(), and ast_cdr_copy_vars().

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

00178 {
00179    struct ast_cdr *newcdr;
00180    
00181    if (!cdr) /* don't die if we get a null cdr pointer */
00182       return NULL;
00183    newcdr = ast_cdr_alloc();
00184    if (!newcdr)
00185       return NULL;
00186 
00187    memcpy(newcdr, cdr, sizeof(*newcdr));
00188    /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */
00189    memset(&newcdr->varshead, 0, sizeof(newcdr->varshead));
00190    ast_cdr_copy_vars(newcdr, cdr);
00191    newcdr->next = NULL;
00192 
00193    return newcdr;
00194 }

void ast_cdr_end ( struct ast_cdr cdr  ) 

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 870 of file cdr.c.

References AST_CDR_ANSWERED, AST_CDR_FAILED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_log(), ast_test_flag, ast_tvnow(), ast_tvzero(), check_post(), LOG_WARNING, ast_cdr::next, and S_OR.

Referenced by __ast_request_and_dial(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_reset(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), clear_caller(), and findmeexec().

00871 {
00872    for ( ; cdr ; cdr = cdr->next) {
00873       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00874          continue;
00875       check_post(cdr);
00876       if (ast_tvzero(cdr->end))
00877          cdr->end = ast_tvnow();
00878       if (ast_tvzero(cdr->start)) {
00879          ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>"));
00880          cdr->disposition = AST_CDR_FAILED;
00881       } else
00882          cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
00883       if (ast_tvzero(cdr->answer)) {
00884          if (cdr->disposition == AST_CDR_ANSWERED) {
00885             ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>"));
00886             cdr->disposition = AST_CDR_FAILED;
00887          }
00888       } else
00889          cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
00890    }
00891 }

int ast_cdr_engine_init ( void   ) 

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

Definition at line 1470 of file cdr.c.

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

Referenced by main().

01471 {
01472    int res;
01473 
01474    sched = sched_context_create();
01475    if (!sched) {
01476       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
01477       return -1;
01478    }
01479 
01480    ast_cli_register(&cli_status);
01481 
01482    res = do_reload();
01483    if (res) {
01484       ast_mutex_lock(&cdr_batch_lock);
01485       res = init_batch();
01486       ast_mutex_unlock(&cdr_batch_lock);
01487    }
01488 
01489    return res;
01490 }

int ast_cdr_engine_reload ( void   ) 

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

Definition at line 1499 of file cdr.c.

References do_reload().

01500 {
01501    return do_reload();
01502 }

void ast_cdr_engine_term ( void   ) 

Submit any remaining CDRs and prepare for shutdown

Definition at line 1494 of file cdr.c.

References ast_cdr_submit_batch(), and batchsafeshutdown.

Referenced by do_reload(), and quit_handler().

01495 {
01496    ast_cdr_submit_batch(batchsafeshutdown);
01497 }

void ast_cdr_failed ( struct ast_cdr cdr  ) 

Parameters:
cdr the cdr you wish to associate with the call Marks the channel disposition as "FAILED" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. Returns nothing

Definition at line 733 of file cdr.c.

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

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

00734 {
00735    for (; cdr; cdr = cdr->next) {
00736       check_post(cdr);
00737       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00738          if (cdr->disposition < AST_CDR_FAILED)
00739             cdr->disposition = AST_CDR_FAILED;
00740       }
00741    }
00742 }

char* ast_cdr_flags2str ( int  flag  ) 

Converts AMA flag to printable string

Definition at line 911 of file cdr.c.

References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.

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

00912 {
00913    switch(flag) {
00914    case AST_CDR_OMIT:
00915       return "OMIT";
00916    case AST_CDR_BILLING:
00917       return "BILLING";
00918    case AST_CDR_DOCUMENTATION:
00919       return "DOCUMENTATION";
00920    }
00921    return "Unknown";
00922 }

void ast_cdr_free ( struct ast_cdr cdr  ) 

Free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing

Definition at line 438 of file cdr.c.

References AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), ast_test_flag, ast_tvzero(), ast_verbose(), ast_cdr::channel, ast_cdr::end, free, ast_cdr::next, ast_cdr_beitem::next, option_verbose, S_OR, ast_cdr::start, and VERBOSE_PREFIX_2.

Referenced by ast_cdr_detach(), and do_batch_backend_process().

00439 {
00440 
00441    while (cdr) {
00442       struct ast_cdr *next = cdr->next;
00443       char *chan = S_OR(cdr->channel, "<unknown>");
00444       if (option_verbose > 1 && !ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
00445          ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' not posted\n", chan);
00446       if (option_verbose > 1 && ast_tvzero(cdr->end))
00447          ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' lacks end\n", chan);
00448       if (option_verbose > 1 && ast_tvzero(cdr->start))
00449          ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' lacks start\n", chan);
00450 
00451       ast_cdr_free_vars(cdr, 0);
00452       free(cdr);
00453       cdr = next;
00454    }
00455 }

void ast_cdr_free_vars ( struct ast_cdr cdr,
int  recur 
)

Definition at line 417 of file cdr.c.

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

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

00418 {
00419 
00420    /* clear variables */
00421    for (; cdr; cdr = recur ? cdr->next : NULL) {
00422       struct ast_var_t *vardata;
00423       struct varshead *headp = &cdr->varshead;
00424       while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
00425          ast_var_delete(vardata);
00426    }
00427 }

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 229 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_copy_string(), 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, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.

Referenced by ast_cdr_serialize_variables(), and cdr_read().

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

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 835 of file cdr.c.

References ast_channel::_state, ast_channel::accountcode, ast_channel::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NULL, ast_copy_string(), AST_STATE_UP, ast_test_flag, ast_cdr::channel, ast_channel::context, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::name, ast_cdr::next, S_OR, set_one_cid(), and ast_channel::uniqueid.

Referenced by __ast_request_and_dial(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().

00836 {
00837    char *chan;
00838 
00839    for ( ; cdr ; cdr = cdr->next) {
00840       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00841          chan = S_OR(cdr->channel, "<unknown>");
00842          ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
00843          set_one_cid(cdr, c);
00844 
00845          cdr->disposition = (c->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
00846          cdr->amaflags = c->amaflags ? c->amaflags :  ast_default_amaflags;
00847          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00848          /* Destination information */
00849          ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst));
00850          ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext));
00851          /* Unique call identifier */
00852          ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid));
00853       }
00854    }
00855    return 0;
00856 }

int ast_cdr_isset_unanswered ( void   ) 

Definition at line 169 of file cdr.c.

References unanswered.

00170 {
00171    return unanswered;
00172 }

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 513 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_copy_string(), ast_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_tv(), ast_tvcmp(), ast_tvzero(), 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.

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

void ast_cdr_noanswer ( struct ast_cdr cdr  ) 

Parameters:
cdr the cdr you wish to associate with the call Marks the channel disposition as "NO ANSWER" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application.

Definition at line 744 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.

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

00745 {
00746    char *chan; 
00747 
00748    while (cdr) {
00749       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00750       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
00751          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00752       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00753          if (cdr->disposition < AST_CDR_NOANSWER)
00754             cdr->disposition = AST_CDR_NOANSWER;
00755       }
00756       cdr = cdr->next;
00757    }
00758 }

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 113 of file cdr.c.

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

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

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

void ast_cdr_reset ( struct ast_cdr cdr,
struct ast_flags flags 
)

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 1040 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_flags::flags, ast_cdr::next, and ast_cdr::start.

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

01041 {
01042    struct ast_cdr *dup;
01043    struct ast_flags flags = { 0 };
01044 
01045    if (_flags)
01046       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
01047 
01048    for ( ; cdr ; cdr = cdr->next) {
01049       /* Detach if post is requested */
01050       if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01051          if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
01052             ast_cdr_end(cdr);
01053             if ((dup = ast_cdr_dup(cdr))) {
01054                ast_cdr_detach(dup);
01055             }
01056             ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
01057          }
01058 
01059          /* clear variables */
01060          if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
01061             ast_cdr_free_vars(cdr, 0);
01062          }
01063 
01064          /* Reset to initial state */
01065          ast_clear_flag(cdr, AST_FLAGS_ALL); 
01066          memset(&cdr->start, 0, sizeof(cdr->start));
01067          memset(&cdr->end, 0, sizeof(cdr->end));
01068          memset(&cdr->answer, 0, sizeof(cdr->answer));
01069          cdr->billsec = 0;
01070          cdr->duration = 0;
01071          ast_cdr_start(cdr);
01072          cdr->disposition = AST_CDR_NULL;
01073       }
01074    }
01075 }

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

Definition at line 372 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, ast_var_t::entries, LOG_ERROR, ast_cdr::next, total, var, and ast_cdr::varshead.

Referenced by handle_showchan(), and handle_showchan_deprecated().

00373 {
00374    struct ast_var_t *variables;
00375    const char *var, *val;
00376    char *tmp;
00377    char workspace[256];
00378    int total = 0, x = 0, i;
00379 
00380    memset(buf, 0, size);
00381 
00382    for (; cdr; cdr = recur ? cdr->next : NULL) {
00383       if (++x > 1)
00384          ast_build_string(&buf, &size, "\n");
00385 
00386       AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
00387          if (variables &&
00388              (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00389              !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00390             if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, var, delim, val, sep)) {
00391                ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00392                break;
00393             } else
00394                total++;
00395          } else 
00396             break;
00397       }
00398 
00399       for (i = 0; cdr_readonly_vars[i]; i++) {
00400          workspace[0] = 0; /* null out the workspace, because the cdr_get_tv() won't write anything if time is NULL, so you get old vals */
00401          ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0);
00402          if (!tmp)
00403             continue;
00404          
00405          if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep)) {
00406             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00407             break;
00408          } else
00409             total++;
00410       }
00411    }
00412 
00413    return total;
00414 }

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

Definition at line 924 of file cdr.c.

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

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

00925 {
00926    struct ast_cdr *cdr = chan->cdr;
00927 
00928    ast_string_field_set(chan, accountcode, account);
00929    for ( ; cdr ; cdr = cdr->next) {
00930       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00931          ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode));
00932       }
00933    }
00934    return 0;
00935 }

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

Definition at line 937 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.

Referenced by cdr_write(), and pbx_builtin_setamaflags().

00938 {
00939    struct ast_cdr *cdr;
00940    int newflag = ast_cdr_amaflags2int(flag);
00941    if (newflag) {
00942       for (cdr = chan->cdr; cdr; cdr = cdr->next) {
00943          if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00944             cdr->amaflags = newflag;
00945          }
00946       }
00947    }
00948 
00949    return 0;
00950 }

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

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 794 of file cdr.c.

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

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

00795 {
00796 
00797    for (; cdr; cdr = cdr->next) {
00798       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00799          check_post(cdr);
00800          ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp));
00801          ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata));
00802       }
00803    }
00804 }

int ast_cdr_setcid ( struct ast_cdr cdr,
struct ast_channel chan 
)

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 826 of file cdr.c.

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

Referenced by ast_bridge_call(), and callerid_write().

00827 {
00828    for (; cdr; cdr = cdr->next) {
00829       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00830          set_one_cid(cdr, c);
00831    }
00832    return 0;
00833 }

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

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 785 of file cdr.c.

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

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

00786 {
00787    for (; cdr; cdr = cdr->next) {
00788       check_post(cdr);
00789       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00790          ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel));
00791    }
00792 }

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

Definition at line 952 of file cdr.c.

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

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

00953 {
00954    struct ast_cdr *cdr = chan->cdr;
00955 
00956    for ( ; cdr ; cdr = cdr->next) {
00957       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 
00958          ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield));
00959    }
00960 
00961    return 0;
00962 }

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 302 of file cdr.c.

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

Referenced by ast_cdr_fork(), and cdr_write().

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

void ast_cdr_specialized_reset ( struct ast_cdr cdr,
struct ast_flags flags 
)

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 1077 of file cdr.c.

References ast_cdr::answer, AST_CDR_FLAG_POST_DISABLED, 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_flags::flags, and ast_cdr::start.

Referenced by ast_bridge_call().

01078 {
01079    struct ast_flags flags = { 0 };
01080 
01081    if (_flags)
01082       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
01083    
01084    /* Reset to initial state */
01085    if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) { /* But do NOT lose the NoCDR() setting */
01086       ast_clear_flag(cdr, AST_FLAGS_ALL); 
01087       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01088    } else {
01089       ast_clear_flag(cdr, AST_FLAGS_ALL); 
01090    }
01091    
01092    memset(&cdr->start, 0, sizeof(cdr->start));
01093    memset(&cdr->end, 0, sizeof(cdr->end));
01094    memset(&cdr->answer, 0, sizeof(cdr->answer));
01095    cdr->billsec = 0;
01096    cdr->duration = 0;
01097    ast_cdr_start(cdr);
01098    cdr->disposition = AST_CDR_NULL;
01099 }

void ast_cdr_start ( struct ast_cdr cdr  ) 

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 692 of file cdr.c.

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

Referenced by __ast_request_and_dial(), ast_bridge_call(), ast_cdr_reset(), ast_cdr_specialized_reset(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().

00693 {
00694    char *chan; 
00695 
00696    for (; cdr; cdr = cdr->next) {
00697       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00698          chan = S_OR(cdr->channel, "<unknown>");
00699          check_post(cdr);
00700          cdr->start = ast_tvnow();
00701       }
00702    }
00703 }

void ast_cdr_submit_batch ( int  shutdown  ) 

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 1155 of file cdr.c.

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

Referenced by ast_cdr_engine_term(), and submit_scheduled_batch().

01156 {
01157    struct ast_cdr_batch_item *oldbatchitems = NULL;
01158    pthread_attr_t attr;
01159    pthread_t batch_post_thread = AST_PTHREADT_NULL;
01160 
01161    /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
01162    if (!batch || !batch->head)
01163       return;
01164 
01165    /* move the old CDRs aside, and prepare a new CDR batch */
01166    ast_mutex_lock(&cdr_batch_lock);
01167    oldbatchitems = batch->head;
01168    reset_batch();
01169    ast_mutex_unlock(&cdr_batch_lock);
01170 
01171    /* if configured, spawn a new thread to post these CDRs,
01172       also try to save as much as possible if we are shutting down safely */
01173    if (batchscheduleronly || shutdown) {
01174       if (option_debug)
01175          ast_log(LOG_DEBUG, "CDR single-threaded batch processing begins now\n");
01176       do_batch_backend_process(oldbatchitems);
01177    } else {
01178       pthread_attr_init(&attr);
01179       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01180       if (ast_pthread_create_background(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) {
01181          ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
01182          do_batch_backend_process(oldbatchitems);
01183       } else {
01184          if (option_debug)
01185             ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n");
01186       }
01187       pthread_attr_destroy(&attr);
01188    }
01189 }

void ast_cdr_unregister ( const char *  name  ) 

unregister a CDR driver

Definition at line 151 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::list, ast_cdr_beitem::name, option_verbose, and VERBOSE_PREFIX_2.

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

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

int ast_cdr_update ( struct ast_channel chan  ) 

Definition at line 978 of file cdr.c.

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

Referenced by __ast_request_and_dial(), ast_bridge_call(), cb_events(), clear_caller(), findmeexec(), and local_call().

00979 {
00980    struct ast_cdr *cdr = c->cdr;
00981 
00982    for ( ; cdr ; cdr = cdr->next) {
00983       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00984          set_one_cid(cdr, c);
00985 
00986          /* Copy account code et-al */ 
00987          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00988          
00989          /* Destination information */ /* XXX privilege macro* ? */
00990          ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst));
00991          ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext));
00992       }
00993    }
00994 
00995    return 0;
00996 }

int check_cdr_enabled ( void   ) 

Return TRUE if CDR subsystem is enabled.

Definition at line 105 of file cdr.c.

References enabled.

Referenced by action_coresettings(), and handle_show_settings().

00106 {
00107    return enabled;
00108 }


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.

Referenced by ast_bridge_call().


Generated on Thu Feb 5 16:26:00 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7