Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:02 2007

Asterisk developer's documentation :: Codename Pineapple


cdr.c File Reference


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.

#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)
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_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, struct ast_str **buf, char delim, char sep, int recur)
int ast_cdr_setaccount (struct ast_channel *chan, const char *account)
int ast_cdr_setamaflags (struct ast_channel *chan, const char *flag)
void ast_cdr_setapp (struct ast_cdr *cdr, char *app, char *data)
int ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *c)
void ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chann)
int ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield)
int ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur)
void ast_cdr_start (struct ast_cdr *cdr)
void ast_cdr_submit_batch (int shutdown)
void ast_cdr_unregister (const char *name)
int ast_cdr_update (struct ast_channel *c)
static AST_LIST_HEAD_STATIC (be_list, ast_cdr_beitem)
 AST_MUTEX_DEFINE_STATIC (cdr_pending_lock)
 AST_MUTEX_DEFINE_STATIC (cdr_batch_lock)
static void cdr_get_tv (struct timeval tv, const char *fmt, char *buf, int bufsize)
static void check_post (struct ast_cdr *cdr)
 print a warning if cdr already posted
static void check_start (struct ast_cdr *cdr)
 print a warning if cdr already started
static void * do_batch_backend_process (void *data)
static void * do_cdr (void *data)
static int do_reload (void)
static int handle_cli_status (int fd, int argc, char *argv[])
static int handle_cli_submit (int fd, int argc, char *argv[])
static int init_batch (void)
static void post_cdr (struct ast_cdr *cdr)
static void reset_batch (void)
static void set_one_cid (struct ast_cdr *cdr, struct ast_channel *c)
static int submit_scheduled_batch (void *data)
static void submit_unscheduled_batch (void)

Variables

char ast_default_accountcode [AST_MAX_ACCOUNT_CODE]
int ast_default_amaflags = AST_CDR_DOCUMENTATION
static struct ast_cdr_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


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

References ast_calloc.

Referenced by __agent_start_monitoring(), __ast_pbx_run(), __ast_request_and_dial(), ast_cdr_dup(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), and start_monitor_exec().

00438 {
00439    return ast_calloc(1, sizeof(struct ast_cdr));
00440 }

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 707 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(), and set_config().

00708 {
00709    if (!strcasecmp(flag, "default"))
00710       return 0;
00711    if (!strcasecmp(flag, "omit"))
00712       return AST_CDR_OMIT;
00713    if (!strcasecmp(flag, "billing"))
00714       return AST_CDR_BILLING;
00715    if (!strcasecmp(flag, "documentation"))
00716       return AST_CDR_DOCUMENTATION;
00717    return -1;
00718 }

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

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

Referenced by __ast_answer(), and __ast_read().

00457 {
00458 
00459    for (; cdr; cdr = cdr->next) {
00460       check_post(cdr);
00461       if (cdr->disposition < AST_CDR_ANSWERED)
00462          cdr->disposition = AST_CDR_ANSWERED;
00463       if (ast_tvzero(cdr->answer))
00464          cdr->answer = ast_tvnow();
00465    }
00466 }

struct ast_cdr* ast_cdr_append struct ast_cdr cdr,
struct ast_cdr newcdr
 

Definition at line 778 of file cdr.c.

References ast_cdr::next.

Referenced by attempt_transfer().

00779 {
00780    struct ast_cdr *ret;
00781 
00782    if (cdr) {
00783       ret = cdr;
00784 
00785       while (cdr->next)
00786          cdr = cdr->next;
00787       cdr->next = newcdr;
00788    } else {
00789       ret = newcdr;
00790    }
00791 
00792    return ret;
00793 }

int ast_cdr_appenduserfield struct ast_channel chan,
const char *  userfield
 

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

00675 {
00676    struct ast_cdr *cdr = chan->cdr;
00677 
00678    for ( ; cdr ; cdr = cdr->next) {
00679       int len = strlen(cdr->userfield);
00680 
00681       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00682          ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len);
00683    }
00684 
00685    return 0;
00686 }

void ast_cdr_busy struct ast_cdr cdr  ) 
 

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

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

00469 {
00470 
00471    for (; cdr; cdr = cdr->next) {
00472       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00473          check_post(cdr);
00474          if (cdr->disposition < AST_CDR_BUSY)
00475             cdr->disposition = AST_CDR_BUSY;
00476       }
00477    }
00478 }

int ast_cdr_copy_vars struct ast_cdr to_cdr,
struct ast_cdr from_cdr
 

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

00325 {
00326    struct ast_var_t *variables, *newvariable = NULL;
00327    struct varshead *headpa, *headpb;
00328    const char *var, *val;
00329    int x = 0;
00330 
00331    headpa = &from_cdr->varshead;
00332    headpb = &to_cdr->varshead;
00333 
00334    AST_LIST_TRAVERSE(headpa,variables,entries) {
00335       if (variables &&
00336           (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00337           !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00338          newvariable = ast_var_assign(var, val);
00339          AST_LIST_INSERT_HEAD(headpb, newvariable, entries);
00340          x++;
00341       }
00342    }
00343 
00344    return x;
00345 }

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 890 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_cdr_reset(), ast_hangup(), and ast_pbx_outgoing_cdr_failed().

00891 {
00892    struct ast_cdr_batch_item *newtail;
00893    int curr;
00894 
00895    /* maybe they disabled CDR stuff completely, so just drop it */
00896    if (!enabled) {
00897       if (option_debug)
00898          ast_log(LOG_DEBUG, "Dropping CDR !\n");
00899       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
00900       ast_cdr_free(cdr);
00901       return;
00902    }
00903 
00904    /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
00905    if (!batchmode) {
00906       post_cdr(cdr);
00907       ast_cdr_free(cdr);
00908       return;
00909    }
00910 
00911    /* otherwise, each CDR gets put into a batch list (at the end) */
00912    if (option_debug)
00913       ast_log(LOG_DEBUG, "CDR detaching from this thread\n");
00914 
00915    /* we'll need a new tail for every CDR */
00916    if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
00917       post_cdr(cdr);
00918       ast_cdr_free(cdr);
00919       return;
00920    }
00921 
00922    /* don't traverse a whole list (just keep track of the tail) */
00923    ast_mutex_lock(&cdr_batch_lock);
00924    if (!batch)
00925       init_batch();
00926    if (!batch->head) {
00927       /* new batch is empty, so point the head at the new tail */
00928       batch->head = newtail;
00929    } else {
00930       /* already got a batch with something in it, so just append a new tail */
00931       batch->tail->next = newtail;
00932    }
00933    newtail->cdr = cdr;
00934    batch->tail = newtail;
00935    curr = batch->size++;
00936    ast_mutex_unlock(&cdr_batch_lock);
00937 
00938    /* if we have enough stuff to post, then do it */
00939    if (curr >= (batchsize - 1))
00940       submit_unscheduled_batch();
00941 }

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

References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, and AST_CDR_NOANSWER.

Referenced by ast_cdr_getvar().

00610 {
00611    switch (disposition) {
00612    case AST_CDR_NOANSWER:
00613       return "NO ANSWER";
00614    case AST_CDR_FAILED:
00615       return "FAILED";     
00616    case AST_CDR_BUSY:
00617       return "BUSY";    
00618    case AST_CDR_ANSWERED:
00619       return "ANSWERED";
00620    }
00621    return "UNKNOWN";
00622 }

int ast_cdr_disposition struct ast_cdr cdr,
int  cause
 

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

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

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

00492 {
00493    int res = 0;
00494 
00495    for (; cdr; cdr = cdr->next) {
00496       switch (cause) {
00497       case AST_CAUSE_BUSY:
00498          ast_cdr_busy(cdr);
00499          break;
00500       case AST_CAUSE_FAILURE:
00501          ast_cdr_failed(cdr);
00502          break;
00503       case AST_CAUSE_NORMAL:
00504          break;
00505       case AST_CAUSE_NOTDEFINED:
00506          res = -1;
00507          break;
00508       default:
00509          res = -1;
00510          ast_log(LOG_WARNING, "Cause not handled\n");
00511       }
00512    }
00513    return res;
00514 }

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

References ast_cdr_alloc(), and ast_cdr_copy_vars().

Referenced by ast_cdr_reset().

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

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 important

Definition at line 594 of file cdr.c.

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

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

00595 {
00596    for ( ; cdr ; cdr = cdr->next) {
00597       check_post(cdr);
00598       if (ast_tvzero(cdr->end))
00599          cdr->end = ast_tvnow();
00600       if (ast_tvzero(cdr->start)) {
00601          ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>"));
00602          cdr->disposition = AST_CDR_FAILED;
00603       } else
00604          cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
00605       cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec;
00606    }
00607 }

int ast_cdr_engine_init void   ) 
 

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

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

01142 {
01143    int res;
01144 
01145    sched = sched_context_create();
01146    if (!sched) {
01147       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
01148       return -1;
01149    }
01150 
01151    ast_cli_register(&cli_status);
01152 
01153    res = do_reload();
01154    if (res) {
01155       ast_mutex_lock(&cdr_batch_lock);
01156       res = init_batch();
01157       ast_mutex_unlock(&cdr_batch_lock);
01158    }
01159 
01160    return res;
01161 }

int ast_cdr_engine_reload void   ) 
 

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

Definition at line 1170 of file cdr.c.

References do_reload().

01171 {
01172    return do_reload();
01173 }

void ast_cdr_engine_term void   ) 
 

Submit any remaining CDRs and prepare for shutdown

Definition at line 1165 of file cdr.c.

References ast_cdr_submit_batch(), and batchsafeshutdown.

Referenced by do_reload(), and quit_handler().

01166 {
01167    ast_cdr_submit_batch(batchsafeshutdown);
01168 }

void ast_cdr_failed struct ast_cdr cdr  ) 
 

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

Definition at line 480 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_cdr_disposition(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), and ast_pbx_outgoing_exten().

00481 {
00482    for (; cdr; cdr = cdr->next) {
00483       check_post(cdr);
00484       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00485          if (cdr->disposition < AST_CDR_FAILED)
00486             cdr->disposition = AST_CDR_FAILED;
00487       }
00488    }
00489 }

char* ast_cdr_flags2str int  flag  ) 
 

Converts AMA flag to printable string

Definition at line 625 of file cdr.c.

References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.

Referenced by _sip_show_device(), _sip_show_peer(), ast_cdr_getvar(), and sip_show_user().

00626 {
00627    switch (flag) {
00628    case AST_CDR_OMIT:
00629       return "OMIT";
00630    case AST_CDR_BILLING:
00631       return "BILLING";
00632    case AST_CDR_DOCUMENTATION:
00633       return "DOCUMENTATION";
00634    }
00635    return "Unknown";
00636 }

void ast_cdr_free struct ast_cdr cdr  ) 
 

Free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing important

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

Referenced by ast_cdr_detach(), and do_batch_backend_process().

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

void ast_cdr_free_vars struct ast_cdr cdr,
int  recur
 

Definition at line 392 of file cdr.c.

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

Referenced by ast_cdr_free().

00393 {
00394 
00395    /* clear variables */
00396    for (; cdr; cdr = recur ? cdr->next : NULL) {
00397       struct ast_var_t *vardata;
00398       struct varshead *headp = &cdr->varshead;
00399       while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
00400          ast_var_delete(vardata);
00401    }
00402 }

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

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

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

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

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

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

References ast_channel::_state, ast_cdr::accountcode, ast_cdr::amaflags, ast_channel::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_default_amaflags, 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_cdr::next, S_OR, set_one_cid(), and ast_cdr::uniqueid.

Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), and ast_pbx_outgoing_exten().

00570 {
00571    char *chan;
00572 
00573    for ( ; cdr ; cdr = cdr->next) {
00574       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00575          chan = S_OR(cdr->channel, "<unknown>");
00576          if (!ast_strlen_zero(cdr->channel)) 
00577             ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan); 
00578          ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
00579          set_one_cid(cdr, c);
00580 
00581          cdr->disposition = (c->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NOANSWER;
00582          cdr->amaflags = c->amaflags ? c->amaflags :  ast_default_amaflags;
00583          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
00584          /* Destination information */
00585          ast_copy_string(cdr->dst, c->exten, sizeof(cdr->dst));
00586          ast_copy_string(cdr->dcontext, c->context, sizeof(cdr->dcontext));
00587          /* Unique call identifier */
00588          ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid));
00589       }
00590    }
00591    return 0;
00592 }

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 fai