Sat Nov 1 06:28:50 2008

Asterisk developer's documentation


cdr.c File Reference

Call Detail Record API. More...

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

Include dependency graph for cdr.c:

Go to the source code of this file.

Data Structures

struct  ast_cdr_batch
struct  ast_cdr_batch_item
struct  ast_cdr_beitem

Defines

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

Functions

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 flag)
void ast_cdr_free (struct ast_cdr *cdr)
 Free a CDR record.
void ast_cdr_free_vars (struct ast_cdr *cdr, int recur)
void ast_cdr_getvar (struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw)
static const char * ast_cdr_getvar_internal (struct ast_cdr *cdr, const char *name, int recur)
int ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *c)
 Initialize based on a channel.
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 *flag)
void ast_cdr_setapp (struct ast_cdr *cdr, char *app, char *data)
int ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *c)
void ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chann)
int ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield)
int ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur)
void ast_cdr_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 *c)
static AST_LIST_HEAD_STATIC (be_list, ast_cdr_beitem)
 AST_MUTEX_DEFINE_STATIC (cdr_pending_lock)
 AST_MUTEX_DEFINE_STATIC (cdr_batch_lock)
static void cdr_get_tv (struct timeval tv, const char *fmt, char *buf, int bufsize)
static void cdr_merge_vars (struct ast_cdr *to, struct ast_cdr *from)
static void check_post (struct ast_cdr *cdr)
 print a warning if cdr already posted
static void * do_batch_backend_process (void *data)
static void * do_cdr (void *data)
static int do_reload (void)
static int handle_cli_status (int fd, int argc, char *argv[])
static int handle_cli_submit (int fd, int argc, char *argv[])
static int init_batch (void)
static void post_cdr (struct ast_cdr *cdr)
static void reset_batch (void)
static void set_one_cid (struct ast_cdr *cdr, struct ast_channel *c)
static int submit_scheduled_batch (const void *data)
static void submit_unscheduled_batch (void)

Variables

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


Detailed Description

Call Detail Record API.

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

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

Definition in file cdr.c.


Define Documentation

#define BATCH_SAFE_SHUTDOWN_DEFAULT   1

Definition at line 89 of file cdr.c.

Referenced by do_reload().

#define BATCH_SCHEDULER_ONLY_DEFAULT   0

Definition at line 88 of file cdr.c.

Referenced by do_reload().

#define BATCH_SIZE_DEFAULT   100

Definition at line 86 of file cdr.c.

Referenced by do_reload().

#define BATCH_TIME_DEFAULT   300

Definition at line 87 of file cdr.c.

Referenced by do_reload().


Function Documentation

struct ast_cdr* ast_cdr_alloc ( void   ) 

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

Definition at line 465 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(), ast_channel_alloc(), builtin_blindtransfer(), clear_caller(), findmeexec(), and start_monitor_exec().

00466 {
00467    struct ast_cdr *x = ast_calloc(1, sizeof(struct ast_cdr));
00468    if (!x)
00469       ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n");
00470    return x;
00471 }

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 991 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().

00992 {
00993    if (!strcasecmp(flag, "default"))
00994       return 0;
00995    if (!strcasecmp(flag, "omit"))
00996       return AST_CDR_OMIT;
00997    if (!strcasecmp(flag, "billing"))
00998       return AST_CDR_BILLING;
00999    if (!strcasecmp(flag, "documentation"))
01000       return AST_CDR_DOCUMENTATION;
01001    return -1;
01002 }

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

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

Referenced by ast_answer(), and ast_bridge_call().

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

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

Definition at line 1094 of file cdr.c.

References ast_cdr::next.

Referenced by ast_cdr_fork(), and ast_cdr_merge().

01095 {
01096    struct ast_cdr *ret;
01097 
01098    if (cdr) {
01099       ret = cdr;
01100 
01101       while (cdr->next)
01102          cdr = cdr->next;
01103       cdr->next = newcdr;
01104    } else {
01105       ret = newcdr;
01106    }
01107 
01108    return ret;
01109 }

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

Definition at line 957 of file cdr.c.

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

Referenced by action_setcdruserfield(), and appendcdruserfield_exec().

00958 {
00959    struct ast_cdr *cdr = chan->cdr;
00960 
00961    for ( ; cdr ; cdr = cdr->next) {
00962       int len = strlen(cdr->userfield);
00963 
00964       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00965          ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len);
00966    }
00967 
00968    return 0;
00969 }

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 717 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().

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

int ast_cdr_copy_vars ( struct ast_cdr to_cdr,
struct ast_cdr from_cdr 
)

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

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

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 1205 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.

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

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

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

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

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

00455 {
00456    while (cdr) {
00457       struct ast_cdr *next = cdr->next;
00458 
00459       ast_cdr_free_vars(cdr, 0);
00460       free(cdr);
00461       cdr = next;
00462    }
00463 }

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 886 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().

00887 {
00888    switch (disposition) {
00889    case AST_CDR_NULL:
00890       return "NO ANSWER"; /* by default, for backward compatibility */
00891    case AST_CDR_NOANSWER:
00892       return "NO ANSWER";
00893    case AST_CDR_FAILED:
00894       return "FAILED";     
00895    case AST_CDR_BUSY:
00896       return "BUSY";    
00897    case AST_CDR_ANSWERED:
00898       return "ANSWERED";
00899    }
00900    return "UNKNOWN";
00901 }

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

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

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

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

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 173 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().

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

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 863 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, 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().

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

int ast_cdr_engine_init ( void   ) 

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

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

Referenced by main().

01464 {
01465    int res;
01466 
01467    sched = sched_context_create();
01468    if (!sched) {
01469       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
01470       return -1;
01471    }
01472 
01473    ast_cli_register(&cli_status);
01474 
01475    res = do_reload();
01476    if (res) {
01477       ast_mutex_lock(&cdr_batch_lock);
01478       res = init_batch();
01479       ast_mutex_unlock(&cdr_batch_lock);
01480    }
01481 
01482    return res;
01483 }

int ast_cdr_engine_reload ( void   ) 

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

Definition at line 1492 of file cdr.c.

References do_reload().

01493 {
01494    return do_reload();
01495 }

void ast_cdr_engine_term ( void   ) 

Submit any remaining CDRs and prepare for shutdown

Definition at line 1487 of file cdr.c.

References ast_cdr_submit_batch(), and batchsafeshutdown.

Referenced by do_reload(), and quit_handler().

01488 {
01489    ast_cdr_submit_batch(batchsafeshutdown);
01490 }

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 729 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().

00730 {
00731    for (; cdr; cdr = cdr->next) {
00732       check_post(cdr);
00733       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00734          if (cdr->disposition < AST_CDR_FAILED)
00735             cdr->disposition = AST_CDR_FAILED;
00736       }
00737    }
00738 }

char* ast_cdr_flags2str ( int  flag  ) 

Converts AMA flag to printable string

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

00905 {
00906    switch(flag) {
00907    case AST_CDR_OMIT:
00908       return "OMIT";
00909    case AST_CDR_BILLING:
00910       return "BILLING";
00911    case AST_CDR_DOCUMENTATION:
00912       return "DOCUMENTATION";
00913    }
00914    return "Unknown";
00915 }

void ast_cdr_free ( struct ast_cdr cdr  ) 

Free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing

Definition at line 434 of file cdr.c.

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

Referenced by ast_cdr_detach(), and do_batch_backend_process().

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

void ast_cdr_free_vars ( struct ast_cdr cdr,
int  recur 
)

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

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

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 225 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.

Referenced by ast_cdr_serialize_variables(), and cdr_read().

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

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

Definition at line 192 of file cdr.c.

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

Referenced by ast_cdr_getvar().

00193 {
00194    if (ast_strlen_zero(name))
00195       return NULL;
00196 
00197    for (; cdr; cdr = recur ? cdr->next : NULL) {
00198       struct ast_var_t *variables;
00199       struct varshead *headp = &cdr->varshead;
00200       AST_LIST_TRAVERSE(headp, variables, entries) {
00201          if (!strcasecmp(name, ast_var_name(variables)))
00202             return ast_var_value(variables);
00203       }
00204    }
00205 
00206    return NULL;
00207 }

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

References ast_channel::_state, ast_channel::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NULL, AST_STATE_UP, ast_test_flag, ast_cdr::channel, 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_channel_alloc(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().

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

int ast_cdr_isset_unanswered ( void   ) 

Definition at line 165 of file cdr.c.

References unanswered.

00166 {
00167    return unanswered;
00168 }