Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:23 2009

## Asterisk developer's documentation

# cdr.c File Reference

Call Detail Record API. More...

`#include <unistd.h>`
`#include <stdlib.h>`
`#include <string.h>`
`#include <stdio.h>`
`#include <signal.h>`
`#include "asterisk.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/module.h"`

Include dependency graph for cdr.c:

Go to the source code of this file.

## Data Structures

struct | ast_cdr_batch
struct | ast_cdr_batch_item
struct | ast_cdr_beitem

## Defines

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

## Functions

struct ast_cdr * | ast_cdr_alloc (void)
| Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
int | ast_cdr_amaflags2int (const char *flag)
void | ast_cdr_answer (struct ast_cdr *cdr)
struct ast_cdr * | ast_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)
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).
void | ast_cdr_end (struct ast_cdr *cdr)
int | ast_cdr_engine_init (void)
void | 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)
static const char * | ast_cdr_getvar_internal (struct ast_cdr *cdr, const char *name, int recur)
int | ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *c)
| Initialize based on a channel.
void | ast_cdr_noanswer (struct ast_cdr *cdr)
int | ast_cdr_register (char *name, 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, 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 (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 * | 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 int | submit_scheduled_batch (void *data)
static void | submit_unscheduled_batch (void)

## Variables

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

## Detailed Description

Call Detail Record API.

Includes code and algorithms from the Zapata library.

Note:
  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 87 of file cdr.c.

Referenced by do_reload().

#define BATCH_SCHEDULER_ONLY_DEFAULT 0

Definition at line 86 of file cdr.c.

Referenced by do_reload().

#define BATCH_SIZE_DEFAULT 100

Definition at line 84 of file cdr.c.

Referenced by do_reload().

#define BATCH_TIME_DEFAULT 300

Definition at line 85 of file cdr.c.

Referenced by do_reload().

## Function Documentation

struct ast_cdr* ast_cdr_alloc | ( | void |  | ) | `[read]`

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

Definition at line 455 of file cdr.c.

References malloc.

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

    00456 {
    00457    struct ast_cdr *cdr;
    00458
    00459    cdr = malloc(sizeof(*cdr));
    00460    if (cdr)
    00461       memset(cdr, 0, sizeof(*cdr));
    00462
    00463    return cdr;
    00464 }

int ast_cdr_amaflags2int | ( | const char * | flag | ) |

Convert a string to a detail record AMA flag

Parameters:

  | flag | string form of flag Converts the string form of the flag to the binary form. Returns the binary form of the flag

Definition at line 809 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(), set_config(), and setup_zap().

    00810 {
    00811    if (!strcasecmp(flag, "default"))
    00812       return 0;
    00813    if (!strcasecmp(flag, "omit"))
    00814       return AST_CDR_OMIT;
    00815    if (!strcasecmp(flag, "billing"))
    00816       return AST_CDR_BILLING;
    00817    if (!strcasecmp(flag, "documentation"))
    00818       return AST_CDR_DOCUMENTATION;
    00819    return -1;
    00820 }

void ast_cdr_answer | ( | struct ast_cdr * | cdr | ) |

Answer a call

Parameters:

  | cdr | the cdr you wish to associate with the call Starts all CDR stuff necessary for doing CDR when answering a call

Definition at line 483 of file cdr.c.

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

Referenced by ast_answer(), and ast_read().

    00484 {
    00485    char *chan;
    00486
    00487    while (cdr) {
    00488       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00489       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
    00490          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
    00491       if (cdr->disposition < AST_CDR_ANSWERED)
    00492          cdr->disposition = AST_CDR_ANSWERED;
    00493       if (ast_tvzero(cdr->answer))
    00494          cdr->answer = ast_tvnow();
    00495       cdr = cdr->next;
    00496    }
    00497 }

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

Definition at line 891 of file cdr.c.

References ast_cdr::next.

Referenced by ast_cdr_fork(), and attempt_transfer().

    00892 {
    00893    struct ast_cdr *ret;
    00894
    00895    if (cdr) {
    00896       ret = cdr;
    00897
    00898       while (cdr->next)
    00899          cdr = cdr->next;
    00900       cdr->next = newcdr;
    00901    } else {
    00902       ret = newcdr;
    00903    }
    00904
    00905    return ret;
    00906 }

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

Definition at line 760 of file cdr.c.

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

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

    00761 {
    00762    struct ast_cdr *cdr = chan->cdr;
    00763
    00764    while (cdr) {
    00765       int len = strlen(cdr->userfield);
    00766
    00767       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
    00768          strncpy(cdr->userfield+len, userfield, sizeof(cdr->userfield) - len - 1);
    00769
    00770       cdr = cdr->next;
    00771    }
    00772
    00773    return 0;
    00774 }

void ast_cdr_busy | ( | struct ast_cdr * | cdr | ) |

Busy a call

Parameters:

  | cdr | the cdr you wish to associate with the call Returns nothing important

Definition at line 499 of file cdr.c.

References AST_CDR_BUSY, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, 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(), ring_entry(), and wait_for_answer().

    00500 {
    00501    char *chan;
    00502
    00503    while (cdr) {
    00504       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
    00505          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00506          if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
    00507             ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
    00508          if (cdr->disposition < AST_CDR_BUSY)
    00509             cdr->disposition = AST_CDR_BUSY;
    00510       }
    00511       cdr = cdr->next;
    00512    }
    00513 }

int ast_cdr_copy_vars | ( | struct ast_cdr * | to_cdr,
|  | struct ast_cdr * | from_cdr |
| ) |  |  |

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

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

void ast_cdr_detach | ( | struct ast_cdr * | cdr | ) |

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

Parameters:

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

Definition at line 1006 of file cdr.c.

References 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, LOG_WARNING, malloc, 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().

    01007 {
    01008    struct ast_cdr_batch_item *newtail;
    01009    int curr;
    01010
    01011    /* maybe they disabled CDR stuff completely, so just drop it */
    01012    if (!enabled) {
    01013       if (option_debug)
    01014          ast_log(LOG_DEBUG, "Dropping CDR !\n");
    01015       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
    01016       ast_cdr_free(cdr);
    01017       return;
    01018    }
    01019
    01020    /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
    01021    if (!batchmode) {
    01022       post_cdr(cdr);
    01023       ast_cdr_free(cdr);
    01024       return;
    01025    }
    01026
    01027    /* otherwise, each CDR gets put into a batch list (at the end) */
    01028    if (option_debug)
    01029       ast_log(LOG_DEBUG, "CDR detaching from this thread\n");
    01030
    01031    /* we'll need a new tail for every CDR */
    01032    newtail = malloc(sizeof(*newtail));
    01033    if (!newtail) {
    01034       ast_log(LOG_WARNING, "CDR: out of memory while trying to detach, will try in this thread instead\n");
    01035       post_cdr(cdr);
    01036       ast_cdr_free(cdr);
    01037       return;
    01038    }
    01039    memset(newtail, 0, sizeof(*newtail));
    01040
    01041    /* don't traverse a whole list (just keep track of the tail) */
    01042    ast_mutex_lock(&cdr_batch_lock);
    01043    if (!batch)
    01044       init_batch();
    01045    if (!batch->head) {
    01046       /* new batch is empty, so point the head at the new tail */
    01047       batch->head = newtail;
    01048    } else {
    01049       /* already got a batch with something in it, so just append a new tail */
    01050       batch->tail->next = newtail;
    01051    }
    01052    newtail->cdr = cdr;
    01053    batch->tail = newtail;
    01054    curr = batch->size++;
    01055    ast_mutex_unlock(&cdr_batch_lock);
    01056
    01057    /* if we have enough stuff to post, then do it */
    01058    if (curr >= (batchsize - 1))
    01059       submit_unscheduled_batch();
    01060 }

char* ast_cdr_disp2str | ( | int | disposition | ) |

Disposition to a string

Parameters:

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

Definition at line 687 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(), csv_log(), manager_log(), odbc_log(), pgsql_log(), and tds_log().

    00688 {
    00689    switch (disposition) {
    00690    case AST_CDR_NULL:
    00691       return "NO ANSWER"; /* by default, for backward compatibility */
    00692    case AST_CDR_NOANSWER:
    00693       return "NO ANSWER";
    00694    case AST_CDR_FAILED:
    00695       return "FAILED";
    00696    case AST_CDR_BUSY:
    00697       return "BUSY";
    00698    case AST_CDR_ANSWERED:
    00699       return "ANSWERED";
    00700    }
    00701    return "UNKNOWN";
    00702 }

int ast_cdr_disposition | ( | struct ast_cdr * | cdr,
|  | int | cause |
| ) |  |  |

Save the result of the call based on the AST_CAUSE_*

Parameters:

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

Definition at line 547 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_feature_request_and_dial(), ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten().

    00548 {
    00549    int res = 0;
    00550
    00551    while (cdr) {
    00552       switch(cause) {
    00553       case AST_CAUSE_BUSY:
    00554          ast_cdr_busy(cdr);
    00555          break;
    00556       case AST_CAUSE_FAILURE:
    00557          ast_cdr_failed(cdr);
    00558          break;
    00559       case AST_CAUSE_NORMAL:
    00560          break;
    00561       case AST_CAUSE_NOTDEFINED:
    00562          res = -1;
    00563          break;
    00564       default:
    00565          res = -1;
    00566          ast_log(LOG_WARNING, "Cause not handled\n");
    00567       }
    00568       cdr = cdr->next;
    00569    }
    00570    return res;
    00571 }

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

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

Duplicate a CDR record

Returns:
  Pointer to new CDR record

Definition at line 167 of file cdr.c.

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

Referenced by ast_cdr_fork(), and ast_cdr_reset().

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

void ast_cdr_end | ( | struct ast_cdr * | cdr | ) |

End a call

Parameters:

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

Definition at line 671 of file cdr.c.

References AST_CDR_FLAG_POSTED, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::end, LOG_WARNING, ast_cdr::next, and ast_cdr::start.

Referenced by __ast_request_and_dial(), ast_cdr_reset(), ast_feature_request_and_dial(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), and ast_read().

    00672 {
    00673    char *chan;
    00674
    00675    while (cdr) {
    00676       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00677       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
    00678          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
    00679       if (ast_tvzero(cdr->start))
    00680          ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", chan);
    00681       if (ast_tvzero(cdr->end))
    00682          cdr->end = ast_tvnow();
    00683       cdr = cdr->next;
    00684    }
    00685 }

int ast_cdr_engine_init | ( | void |  | ) |

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

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

    01262 {
    01263    int res;
    01264
    01265    sched = sched_context_create();
    01266    if (!sched) {
    01267       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
    01268       return -1;
    01269    }
    01270
    01271    ast_cli_register(&cli_status);
    01272
    01273    res = do_reload();
    01274    if (res) {
    01275       ast_mutex_lock(&cdr_batch_lock);
    01276       res = init_batch();
    01277       ast_mutex_unlock(&cdr_batch_lock);
    01278    }
    01279
    01280    return res;
    01281 }

void ast_cdr_engine_reload | ( | void |  | ) |

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

Definition at line 1290 of file cdr.c.

References do_reload().

Referenced by ast_module_reload().

    01291 {
    01292    do_reload();
    01293 }

void ast_cdr_engine_term | ( | void |  | ) |

Submit any remaining CDRs and prepare for shutdown

Definition at line 1285 of file cdr.c.

References ast_cdr_submit_batch(), and batchsafeshutdown.

Referenced by do_reload(), and quit_handler().

    01286 {
    01287    ast_cdr_submit_batch(batchsafeshutdown);
    01288 }

void ast_cdr_failed | ( | struct ast_cdr * | cdr | ) |

Fail a call

Parameters:

  | cdr | the cdr you wish to associate with the call Returns nothing important

Definition at line 515 of file cdr.c.

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

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

    00516 {
    00517    char *chan;
    00518
    00519    while (cdr) {
    00520       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00521       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
    00522          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
    00523       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
    00524          if (cdr->disposition < AST_CDR_FAILED)
    00525             cdr->disposition = AST_CDR_FAILED;
    00526       }
    00527       cdr = cdr->next;
    00528    }
    00529 }

char* ast_cdr_flags2str | ( | int | flag | ) |

Converts AMA flag to printable string

Definition at line 705 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(), csv_log(), manager_log(), sip_show_user(), and tds_log().

    00706 {
    00707    switch(flag) {
    00708    case AST_CDR_OMIT:
    00709       return "OMIT";
    00710    case AST_CDR_BILLING:
    00711       return "BILLING";
    00712    case AST_CDR_DOCUMENTATION:
    00713       return "DOCUMENTATION";
    00714    }
    00715    return "Unknown";
    00716 }

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

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

Referenced by ast_cdr_detach(), do_batch_backend_process(), and nocdr_exec().

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

void ast_cdr_free_vars | ( | struct ast_cdr * | cdr,
|  | int | recur |
| ) |  |  |

Definition at line 413 of file cdr.c.

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

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

    00414 {
    00415    struct varshead *headp;
    00416    struct ast_var_t *vardata;
    00417
    00418    /* clear variables */
    00419    while (cdr) {
    00420       headp = &cdr->varshead;
    00421       while (!AST_LIST_EMPTY(headp)) {
    00422          vardata = AST_LIST_REMOVE_HEAD(headp, entries);
    00423          ast_var_delete(vardata);
    00424       }
    00425
    00426       if (!recur) {
    00427          break;
    00428       }
    00429
    00430       cdr = cdr->next;
    00431    }
    00432 }

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

CDR channel variable retrieval

Definition at line 208 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, 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, t, ast_cdr::uniqueid, and ast_cdr::userfield.

Referenced by ast_cdr_serialize_variables(), builtin_function_cdr_read(), and pickup_exec().

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

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

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

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

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

References ast_channel::_state, ast_channel::accountcode, ast_cdr::accountcode, ast_channel::amaflags, ast_cdr::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NULL, ast_log(), AST_MAX_EXTENSION, AST_STATE_UP, ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_cdr::next, ast_cdr::src, ast_channel::uniqueid, and ast_cdr::uniqueid.

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

    00634 {
    00635    char *chan;
    00636    char *num;
    00637    char tmp[AST_MAX_EXTENSION] = "";
    00638
    00639    while (cdr) {
    00640       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
    00641          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00642          if (!ast_strlen_zero(cdr->channel))
    00643             ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan);
    00644          ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel));
    00645          /* Grab source from ANI or normal Caller*ID */
    00646          num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
    00647
    00648          if (c->cid.cid_name && num)
    00649             snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
    00650          else if (c->cid.cid_name)
    00651             ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
    00652          else if (num)
    00653             ast_copy_string(tmp, num, sizeof(tmp));
    00654          ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
    00655          ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
    00656
    00657          cdr->disposition = (c->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NULL;
    00658          cdr->amaflags = c->amaflags ? c->amaflags :  ast_default_amaflags;
    00659          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
    00660          /* Destination information */
    00661          ast_copy_string(cdr->dst, c->exten, sizeof(cdr->dst));
    00662          ast_copy_string(cdr->dcontext, c->context, sizeof(cdr->dcontext));
    00663          /* Unique call identifier */
    00664          ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid));
    00665       }
    00666       cdr = cdr->next;
    00667    }
    00668    return 0;
    00669 }

void ast_cdr_noanswer | ( | struct ast_cdr * | cdr | ) |

A call wasn't answered

Parameters:

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

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

    00532 {
    00533    char *chan;
    00534
    00535    while (cdr) {
    00536       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00537       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
    00538          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
    00539       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
    00540          if (cdr->disposition < AST_CDR_NOANSWER)
    00541             cdr->disposition = AST_CDR_NOANSWER;
    00542       }
    00543       cdr = cdr->next;
    00544    }
    00545 }

int ast_cdr_register | ( | char * | name,
|  | 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 106 of file cdr.c.

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

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

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

void ast_cdr_reset | ( | struct ast_cdr * | cdr,
|  | struct ast_flags * | flags |
| ) |  |  |

Reset the detail record, optionally posting it first

Parameters:

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

Definition at line 852 of file cdr.c.

References ast_cdr::answer, ast_cdr_detach(), ast_cdr_dup(), ast_cdr_end(), AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), AST_CDR_NULL, ast_cdr_start(), ast_clear_flag, ast_copy_flags, AST_FLAGS_ALL, ast_set_flag, ast_test_flag, ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, ast_cdr::next, and ast_cdr::start.

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

    00853 {
    00854    struct ast_cdr *dup;
    00855    struct ast_flags flags = { 0 };
    00856
    00857    if (_flags)
    00858       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
    00859
    00860    while (cdr) {
    00861       /* Detach if post is requested */
    00862       if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
    00863          if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
    00864             ast_cdr_end(cdr);
    00865             if ((dup = ast_cdr_dup(cdr))) {
    00866                ast_cdr_detach(dup);
    00867             }
    00868             ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
    00869          }
    00870
    00871          /* clear variables */
    00872          if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
    00873             ast_cdr_free_vars(cdr, 0);
    00874          }
    00875
    00876          /* Reset to initial state */
    00877          ast_clear_flag(cdr, AST_FLAGS_ALL);
    00878          memset(&cdr->start, 0, sizeof(cdr->start));
    00879          memset(&cdr->end, 0, sizeof(cdr->end));
    00880          memset(&cdr->answer, 0, sizeof(cdr->answer));
    00881          cdr->billsec = 0;
    00882          cdr->duration = 0;
    00883          ast_cdr_start(cdr);
    00884          cdr->disposition = AST_CDR_NULL;
    00885       }
    00886
    00887       cdr = cdr->next;
    00888    }
    00889 }

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

Definition at line 349 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(), LOG_ERROR, ast_cdr::next, total, var, and ast_cdr::varshead.

Referenced by handle_showchan().

    00350 {
    00351    struct ast_var_t *variables;
    00352    char *var, *val;
    00353    char *tmp;
    00354    char workspace[256];
    00355    int total = 0, x = 0, i;
    00356    const char *cdrcols[] = {
    00357       "clid",
    00358       "src",
    00359       "dst",
    00360       "dcontext",
    00361       "channel",
    00362       "dstchannel",
    00363       "lastapp",
    00364       "lastdata",
    00365       "start",
    00366       "answer",
    00367       "end",
    00368       "duration",
    00369       "billsec",
    00370       "disposition",
    00371       "amaflags",
    00372       "accountcode",
    00373       "uniqueid",
    00374       "userfield"
    00375    };
    00376
    00377    memset(buf, 0, size);
    00378
    00379    for (; cdr; cdr = recur ? cdr->next : NULL) {
    00380       if (++x > 1)
    00381          ast_build_string(&buf, &size, "\n");
    00382
    00383       AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
    00384          if (variables &&
    00385              (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
    00386              !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
    00387             if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, var, delim, val, sep)) {
    00388                ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
    00389                break;
    00390             } else
    00391                total++;
    00392          } else
    00393             break;
    00394       }
    00395
    00396       for (i = 0; i < (sizeof(cdrcols) / sizeof(cdrcols[0])); i++) {
    00397          ast_cdr_getvar(cdr, cdrcols[i], &tmp, workspace, sizeof(workspace), 0);
    00398          if (!tmp)
    00399             continue;
    00400
    00401          if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, cdrcols[i], delim, tmp, sep)) {
    00402             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
    00403             break;
    00404          } else
    00405             total++;
    00406       }
    00407    }
    00408
    00409    return total;
    00410 }

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

Definition at line 718 of file cdr.c.

References ast_cdr::accountcode, ast_channel::accountcode, AST_CDR_FLAG_LOCKED, 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(), builtin_function_cdr_write(), and pbx_builtin_setaccount().

    00719 {
    00720    struct ast_cdr *cdr = chan->cdr;
    00721
    00722    ast_copy_string(chan->accountcode, account, sizeof(chan->accountcode));
    00723    while (cdr) {
    00724       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
    00725          ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode));
    00726       cdr = cdr->next;
    00727    }
    00728    return 0;
    00729 }

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

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

    00732 {
    00733    struct ast_cdr *cdr;
    00734    int newflag;
    00735
    00736    newflag = ast_cdr_amaflags2int(flag);
    00737    if (newflag) {
    00738       for (cdr = chan->cdr; cdr; cdr = cdr->next) {
    00739          if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
    00740             cdr->amaflags = newflag;
    00741       }
    00742    }
    00743
    00744    return 0;
    00745 }

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

Set the last executed application

Parameters:

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

Definition at line 587 of file cdr.c.

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

Referenced by __ast_request_and_dial(), ast_feature_request_and_dial(), and pbx_exec().

    00588 {
    00589    char *chan;
    00590
    00591    while (cdr) {
    00592       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
    00593          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00594          if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
    00595             ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
    00596          if (!app)
    00597             app = "";
    00598          ast_copy_string(cdr->lastapp, app, sizeof(cdr->lastapp));
    00599          if (!data)
    00600             data = "";
    00601          ast_copy_string(cdr->lastdata, data, sizeof(cdr->lastdata));
    00602       }
    00603       cdr = cdr->next;
    00604    }
    00605 }

int ast_cdr_setcid | ( | struct ast_cdr * | cdr,
|  | struct ast_channel * | chan |
| ) |  |  |

Initialize based on a channel

Parameters:

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

Definition at line 607 of file cdr.c.

References AST_CDR_FLAG_LOCKED, AST_MAX_EXTENSION, ast_test_flag, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, ast_cdr::next, and ast_cdr::src.

Referenced by ast_set_callerid().

    00608 {
    00609    char tmp[AST_MAX_EXTENSION] = "";
    00610    char *num;
    00611
    00612    while (cdr) {
    00613       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
    00614          /* Grab source from ANI or normal Caller*ID */
    00615          num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
    00616
    00617          if (c->cid.cid_name && num)
    00618             snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
    00619          else if (c->cid.cid_name)
    00620             ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
    00621          else if (num)
    00622             ast_copy_string(tmp, num, sizeof(tmp));
    00623          ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
    00624          ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
    00625       }
    00626       cdr = cdr->next;
    00627    }
    00628
    00629    return 0;
    00630 }

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

Set the destination channel, if there was one

Parameters:

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

Definition at line 573 of file cdr.c.

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

Referenced by ast_bridge_call_thread(), dial_exec_full(), and try_calling().

    00574 {
    00575    char *chan;
    00576
    00577    while (cdr) {
    00578       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00579       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
    00580          ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
    00581       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
    00582          ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel));
    00583       cdr = cdr->next;
    00584    }
    00585 }

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

Definition at line 747 of file cdr.c.

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

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

    00748 {
    00749    struct ast_cdr *cdr = chan->cdr;
    00750
    00751    while (cdr) {
    00752       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
    00753          ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield));
    00754       cdr = cdr->next;
    00755    }
    00756
    00757    return 0;
    00758 }

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

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

Referenced by builtin_function_cdr_write().

    00278 {
    00279    struct ast_var_t *newvariable;
    00280    struct varshead *headp;
    00281    const char *read_only[] = { "clid", "src", "dst", "dcontext", "channel", "dstchannel",
    00282                 "lastapp", "lastdata", "start", "answer", "end", "duration",
    00283                 "billsec", "disposition", "amaflags", "accountcode", "uniqueid",
    00284                 "userfield", NULL };
    00285    int x;
    00286
    00287    for(x = 0; read_only[x]; x++) {
    00288       if (!strcasecmp(name, read_only[x])) {
    00289          ast_log(LOG_ERROR, "Attempt to set a read-only variable!.\n");
    00290          return -1;
    00291       }
    00292    }
    00293
    00294    if (!cdr) {
    00295       ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n");
    00296       return -1;
    00297    }
    00298
    00299    while (cdr) {
    00300       headp = &cdr->varshead;
    00301       AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
    00302          if (!strcasecmp(ast_var_name(newvariable), name)) {
    00303             /* there is already such a variable, delete it */
    00304             AST_LIST_REMOVE_CURRENT(headp, entries);
    00305             ast_var_delete(newvariable);
    00306             break;
    00307          }
    00308       }
    00309       AST_LIST_TRAVERSE_SAFE_END;
    00310
    00311       if (value) {
    00312          newvariable = ast_var_assign(name, value);
    00313          AST_LIST_INSERT_HEAD(headp, newvariable, entries);
    00314       }
    00315
    00316       if (!recur) {
    00317          break;
    00318       }
    00319
    00320       cdr = cdr->next;
    00321    }
    00322
    00323    return 0;
    00324 }

void ast_cdr_start | ( | struct ast_cdr * | cdr | ) |

Start a call

Parameters:

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

Definition at line 466 of file cdr.c.

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

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

    00467 {
    00468    char *chan;
    00469
    00470    while (cdr) {
    00471       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
    00472          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00473          if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
    00474             ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
    00475          if (!ast_tvzero(cdr->start))
    00476             ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan);
    00477          cdr->start = ast_tvnow();
    00478       }
    00479       cdr = cdr->next;
    00480    }
    00481 }

void ast_cdr_submit_batch | ( | int | shutdown | ) |

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

Parameters:

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

Definition at line 948 of file cdr.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, AST_PTHREADT_NULL, batch, batchscheduleronly, 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().

    00949 {
    00950    struct ast_cdr_batch_item *oldbatchitems = NULL;
    00951    pthread_attr_t attr;
    00952    pthread_t batch_post_thread = AST_PTHREADT_NULL;
    00953
    00954    /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
    00955    if (!batch || !batch->head)
    00956       return;
    00957
    00958    /* move the old CDRs aside, and prepare a new CDR batch */
    00959    ast_mutex_lock(&cdr_batch_lock);
    00960    oldbatchitems = batch->head;
    00961    reset_batch();
    00962    ast_mutex_unlock(&cdr_batch_lock);
    00963
    00964    /* if configured, spawn a new thread to post these CDRs,
    00965       also try to save as much as possible if we are shutting down safely */
    00966    if (batchscheduleronly || shutdown) {
    00967       if (option_debug)
    00968          ast_log(LOG_DEBUG, "CDR single-threaded batch processing begins now\n");
    00969       do_batch_backend_process(oldbatchitems);
    00970    } else {
    00971       pthread_attr_init(&attr);
    00972       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    00973       if (ast_pthread_create(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) {
    00974          ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
    00975          do_batch_backend_process(oldbatchitems);
    00976       } else {
    00977          if (option_debug)
    00978             ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n");
    00979       }
    00980       pthread_attr_destroy(&attr);
    00981    }
    00982 }

void ast_cdr_unregister | ( | char * | name | ) |

unregister a CDR driver

Definition at line 146 of file cdr.c.

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

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

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

int ast_cdr_update | ( | struct ast_channel * | c | ) |

Definition at line 776 of file cdr.c.

References ast_channel::accountcode, ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_check_hangup(), AST_MAX_EXTENSION, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_callerid::cid_num, ast_cdr::clid, ast_channel::context, ast_cdr::dcontext, ast_cdr::dst, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, and ast_cdr::src.

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

    00777 {
    00778    struct ast_cdr *cdr = c->cdr;
    00779    char *num;
    00780    char tmp[AST_MAX_EXTENSION] = "";
    00781
    00782    while (cdr) {
    00783       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
    00784          num = c->cid.cid_ani ? c->cid.cid_ani : c->cid.cid_num;
    00785
    00786          if (c->cid.cid_name && num)
    00787             snprintf(tmp, sizeof(tmp), "\"%s\" <%s>", c->cid.cid_name, num);
    00788          else if (c->cid.cid_name)
    00789             ast_copy_string(tmp, c->cid.cid_name, sizeof(tmp));
    00790          else if (num)
    00791             ast_copy_string(tmp, num, sizeof(tmp));
    00792          ast_copy_string(cdr->clid, tmp, sizeof(cdr->clid));
    00793          ast_copy_string(cdr->src, num ? num : "", sizeof(cdr->src));
    00794
    00795          /* Copy account code et-al */
    00796          ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode));
    00797          if (!ast_check_hangup(c)) {
    00798             /* Destination information */ /* XXX privilege macro* ? */
    00799             ast_copy_string(cdr->dst, (ast_strlen_zero(c->macroexten)) ? c->exten : c->macroexten, sizeof(cdr->dst));
    00800             ast_copy_string(cdr->dcontext, (ast_strlen_zero(c->macrocontext)) ? c->context : c->macrocontext, sizeof(cdr->dcontext));
    00801          }
    00802       }
    00803       cdr = cdr->next;
    00804    }
    00805
    00806    return 0;
    00807 }

static AST_LIST_HEAD_STATIC | ( | be_list | ,
|  | ast_cdr_beitem |  |
| ) |  |  | `[static]`

AST_MUTEX_DEFINE_STATIC | ( | cdr_pending_lock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | cdr_batch_lock |  | ) |

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

Definition at line 931 of file cdr.c.

References ast_cdr_free(), ast_cdr_batch_item::cdr, free, ast_cdr_batch_item::next, and post_cdr().

Referenced by ast_cdr_submit_batch().

    00932 {
    00933    struct ast_cdr_batch_item *processeditem;
    00934    struct ast_cdr_batch_item *batchitem = data;
    00935
    00936    /* Push each CDR into storage mechanism(s) and free all the memory */
    00937    while (batchitem) {
    00938       post_cdr(batchitem->cdr);
    00939       ast_cdr_free(batchitem->cdr);
    00940       processeditem = batchitem;
    00941       batchitem = batchitem->next;
    00942       free(processeditem);
    00943    }
    00944
    00945    return NULL;
    00946 }

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

Definition at line 1062 of file cdr.c.

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

Referenced by do_reload().

    01063 {
    01064    struct timespec timeout;
    01065    int schedms;
    01066    int numevents = 0;
    01067
    01068    for(;;) {
    01069       struct timeval now;
    01070       schedms = ast_sched_wait(sched);
    01071       /* this shouldn't happen, but provide a 1 second default just in case */
    01072       if (schedms <= 0)
    01073          schedms = 1000;
    01074       now = ast_tvadd(ast_tvnow(), ast_samp2tv(schedms, 1000));
    01075       timeout.tv_sec = now.tv_sec;
    01076       timeout.tv_nsec = now.tv_usec * 1000;
    01077       /* prevent stuff from clobbering cdr_pending_cond, then wait on signals sent to it until the timeout expires */
    01078       ast_mutex_lock(&cdr_pending_lock);
    01079       ast_cond_timedwait(&cdr_pending_cond, &cdr_pending_lock, &timeout);
    01080       numevents = ast_sched_runq(sched);
    01081       ast_mutex_unlock(&cdr_pending_lock);
    01082       if (option_debug > 1)
    01083          ast_log(LOG_DEBUG, "Processed %d scheduled CDR batches from the run queue\n", numevents);
    01084    }
    01085
    01086    return NULL;
    01087 }

static int do_reload | ( | void |  | ) | `[static]`

Definition at line 1152 of file cdr.c.

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

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

    01153 {
    01154    struct ast_config *config;
    01155    const char *enabled_value;
    01156    const char *batched_value;
    01157    const char *scheduleronly_value;
    01158    const char *batchsafeshutdown_value;
    01159    const char *size_value;
    01160    const char *time_value;
    01161    int cfg_size;
    01162    int cfg_time;
    01163    int was_enabled;
    01164    int was_batchmode;
    01165    int res=0;
    01166
    01167    ast_mutex_lock(&cdr_batch_lock);
    01168
    01169    batchsize = BATCH_SIZE_DEFAULT;
    01170    batchtime = BATCH_TIME_DEFAULT;
    01171    batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT;
    01172    batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT;
    01173    was_enabled = enabled;
    01174    was_batchmode = batchmode;
    01175    enabled = 1;
    01176    batchmode = 0;
    01177
    01178    /* don't run the next scheduled CDR posting while reloading */
    01179    if (cdr_sched > -1)
    01180       ast_sched_del(sched, cdr_sched);
    01181
    01182    if ((config = ast_config_load("cdr.conf"))) {
    01183       if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
    01184          enabled = ast_true(enabled_value);
    01185       }
    01186       if ((batched_value = ast_variable_retrieve(config, "general", "batch"))) {
    01187          batchmode = ast_true(batched_value);
    01188       }
    01189       if ((scheduleronly_value = ast_variable_retrieve(config, "general", "scheduleronly"))) {
    01190          batchscheduleronly = ast_true(scheduleronly_value);
    01191       }
    01192       if ((batchsafeshutdown_value = ast_variable_retrieve(config, "general", "safeshutdown"))) {
    01193          batchsafeshutdown = ast_true(batchsafeshutdown_value);
    01194       }
    01195       if ((size_value = ast_variable_retrieve(config, "general", "size"))) {
    01196          if (sscanf(size_value, "%30d", &cfg_size) < 1)
    01197             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", size_value);
    01198          else if (size_value < 0)
    01199             ast_log(LOG_WARNING, "Invalid maximum batch size '%d' specified, using default\n", cfg_size);
    01200          else
    01201             batchsize = cfg_size;
    01202       }
    01203       if ((time_value = ast_variable_retrieve(config, "general", "time"))) {
    01204          if (sscanf(time_value, "%30d", &cfg_time) < 1)
    01205             ast_log(LOG_WARNING, "Unable to convert '%s' to a numeric value.\n", time_value);
    01206          else if (time_value < 0)
    01207             ast_log(LOG_WARNING, "Invalid maximum batch time '%d' specified, using default\n", cfg_time);
    01208          else
    01209             batchtime = cfg_time;
    01210       }
    01211    }
    01212
    01213    if (enabled && !batchmode) {
    01214       ast_log(LOG_NOTICE, "CDR simple logging enabled.\n");
    01215    } else if (enabled && batchmode) {
    01216       cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
    01217       ast_log(LOG_NOTICE, "CDR batch mode logging enabled, first of either size %d or time %d seconds.\n", batchsize, batchtime);
    01218    } else {
    01219       ast_log(LOG_NOTICE, "CDR logging disabled, data will be lost.\n");
    01220    }
    01221
    01222    /* if this reload enabled the CDR batch mode, create the background thread
    01223       if it does not exist */
    01224    if (enabled && batchmode && (!was_enabled || !was_batchmode) && (cdr_thread == AST_PTHREADT_NULL)) {
    01225       ast_cond_init(&cdr_pending_cond, NULL);
    01226       if (ast_pthread_create(&cdr_thread, NULL, do_cdr, NULL) < 0) {
    01227          ast_log(LOG_ERROR, "Unable to start CDR thread.\n");
    01228          ast_sched_del(sched, cdr_sched);
    01229       } else {
    01230          ast_cli_register(&cli_submit);
    01231          ast_register_atexit(ast_cdr_engine_term);
    01232          res = 0;
    01233       }
    01234    /* if this reload disabled the CDR and/or batch mode and there is a background thread,
    01235       kill it */
    01236    } else if (((!enabled && was_enabled) || (!batchmode && was_batchmode)) && (cdr_thread != AST_PTHREADT_NULL)) {
    01237       /* wake up the thread so it will exit */
    01238       pthread_cancel(cdr_thread);
    01239       pthread_kill(cdr_thread, SIGURG);
    01240       pthread_join(cdr_thread, NULL);
    01241       cdr_thread = AST_PTHREADT_NULL;
    01242       ast_cond_destroy(&cdr_pending_cond);
    01243       ast_cli_unregister(&cli_submit);
    01244       ast_unregister_atexit(ast_cdr_engine_term);
    01245       res = 0;
    01246       /* if leaving batch mode, then post the CDRs in the batch,
    01247          and don't reschedule, since we are stopping CDR logging */
    01248       if (!batchmode && was_batchmode) {
    01249          ast_cdr_engine_term();
    01250       }
    01251    } else {
    01252       res = 0;
    01253    }
    01254
    01255    ast_mutex_unlock(&cdr_batch_lock);
    01256    ast_config_destroy(config);
    01257
    01258    return res;
    01259 }

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

Definition at line 1089 of file cdr.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_sched_when(), batch, batchmode, batchsafeshutdown, batchscheduleronly, batchsize, batchtime, cdr_sched, enabled, list, ast_cdr_beitem::name, RESULT_SHOWUSAGE, and ast_cdr_batch::size.

    01090 {
    01091    struct ast_cdr_beitem *beitem=NULL;
    01092    int cnt=0;
    01093    long nextbatchtime=0;
    01094
    01095    if (argc > 2)
    01096       return RESULT_SHOWUSAGE;
    01097
    01098    ast_cli(fd, "CDR logging: %s\n", enabled ? "enabled" : "disabled");
    01099    ast_cli(fd, "CDR mode: %s\n", batchmode ? "batch" : "simple");
    01100    if (enabled) {
    01101       if (batchmode) {
    01102          if (batch)
    01103             cnt = batch->size;
    01104          if (cdr_sched > -1)
    01105             nextbatchtime = ast_sched_when(sched, cdr_sched);
    01106          ast_cli(fd, "CDR safe shut down: %s\n", batchsafeshutdown ? "enabled" : "disabled");
    01107          ast_cli(fd, "CDR batch threading model: %s\n", batchscheduleronly ? "scheduler only" : "scheduler plus separate threads");
    01108          ast_cli(fd, "CDR current batch size: %d record%s\n", cnt, (cnt != 1) ? "s" : "");
    01109          ast_cli(fd, "CDR maximum batch size: %d record%s\n", batchsize, (batchsize != 1) ? "s" : "");
    01110          ast_cli(fd, "CDR maximum batch time: %d second%s\n", batchtime, (batchtime != 1) ? "s" : "");
    01111          ast_cli(fd, "CDR next scheduled batch processing time: %ld second%s\n", nextbatchtime, (nextbatchtime != 1) ? "s" : "");
    01112       }
    01113       AST_LIST_LOCK(&be_list);
    01114       AST_LIST_TRAVERSE(&be_list, beitem, list) {
    01115          ast_cli(fd, "CDR registered backend: %s\n", beitem->name);
    01116       }
    01117       AST_LIST_UNLOCK(&be_list);
    01118    }
    01119
    01120    return 0;
    01121 }

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

Definition at line 1123 of file cdr.c.

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

    01124 {
    01125    if (argc > 2)
    01126       return RESULT_SHOWUSAGE;
    01127
    01128    submit_unscheduled_batch();
    01129    ast_cli(fd, "Submitted CDRs to backend engines for processing.  This may take a while.\n");
    01130
    01131    return 0;
    01132 }

static int init_batch | ( | void |  | ) | `[static]`

Note:
  Don't call without cdr_batch_lock

Definition at line 917 of file cdr.c.

References ast_log(), batch, LOG_WARNING, malloc, and reset_batch().

Referenced by ast_cdr_detach(), and ast_cdr_engine_init().

    00918 {
    00919    /* This is the single meta-batch used to keep track of all CDRs during the entire life of the program */
    00920    batch = malloc(sizeof(*batch));
    00921    if (!batch) {
    00922       ast_log(LOG_WARNING, "CDR: out of memory while trying to handle batched records, data will most likely be lost\n");
    00923       return -1;
    00924    }
    00925
    00926    reset_batch();
    00927
    00928    return 0;
    00929 }

static void post_cdr | ( | struct ast_cdr * | cdr | ) | `[static]`

Definition at line 822 of file cdr.c.

References ast_cdr::answer, AST_CDR_FAILED, AST_CDR_FLAG_POSTED, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_cdr_beitem::be, ast_cdr::billsec, ast_cdr::channel, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, list, LOG_NOTICE, ast_cdr::next, and ast_cdr::start.

Referenced by ast_cdr_detach(), and do_batch_backend_process().

    00823 {
    00824    char *chan;
    00825    struct ast_cdr_beitem *i;
    00826
    00827    while (cdr) {
    00828       chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
    00829       if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
    00830          ast_log(LOG_NOTICE, "CDR on channel '%s' already posted\n", chan);
    00831       if (ast_tvzero(cdr->end))
    00832          ast_log(LOG_NOTICE, "CDR on channel '%s' lacks end\n", chan);
    00833       if (ast_tvzero(cdr->start)) {
    00834          ast_log(LOG_NOTICE, "CDR on channel '%s' lacks start\n", chan);
    00835          cdr->disposition = AST_CDR_FAILED;
    00836       } else
    00837          cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
    00838       if (!ast_tvzero(cdr->answer))
    00839          cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
    00840       else
    00841          cdr->billsec = 0;
    00842       ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
    00843       AST_LIST_LOCK(&be_list);
    00844       AST_LIST_TRAVERSE(&be_list, i, list) {
    00845          i->be(cdr);
    00846       }
    00847       AST_LIST_UNLOCK(&be_list);
    00848       cdr = cdr->next;
    00849    }
    00850 }

static void reset_batch | ( | void |  | ) | `[static]`

Note:
  Don't call without cdr_batch_lock

Definition at line 909 of file cdr.c.

References batch, ast_cdr_batch::head, ast_cdr_batch::size, and ast_cdr_batch::tail.

Referenced by ast_cdr_submit_batch(), and init_batch().

    00910 {
    00911    batch->size = 0;
    00912    batch->head = NULL;
    00913    batch->tail = NULL;
    00914 }

static int submit_scheduled_batch | ( | void * | data | ) | `[static]`

Definition at line 984 of file cdr.c.

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

Referenced by do_reload(), and submit_unscheduled_batch().

    00985 {
    00986    ast_cdr_submit_batch(0);
    00987    /* manually reschedule from this point in time */
    00988    cdr_sched = ast_sched_add(sched, batchtime * 1000, submit_scheduled_batch, NULL);
    00989    /* returning zero so the scheduler does not automatically reschedule */
    00990    return 0;
    00991 }

static void submit_unscheduled_batch | ( | void |  | ) | `[static]`

Definition at line 993 of file cdr.c.

References ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), ast_sched_add(), ast_sched_del(), cdr_pending_cond, cdr_sched, and submit_scheduled_batch().

Referenced by ast_cdr_detach(), and handle_cli_submit().

    00994 {
    00995    /* this is okay since we are not being called from within the scheduler */
    00996    if (cdr_sched > -1)
    00997       ast_sched_del(sched, cdr_sched);
    00998    /* schedule the submission to occur ASAP (1 ms) */
    00999    cdr_sched = ast_sched_add(sched, 1, submit_scheduled_batch, NULL);
    01000    /* signal the do_cdr thread to wakeup early and do some work (that lazy thread ;) */
    01001    ast_mutex_lock(&cdr_pending_lock);
    01002    ast_cond_signal(&cdr_pending_cond);
    01003    ast_mutex_unlock(&cdr_pending_lock);
    01004 }

## Variable Documentation

char ast_default_accountcode[AST_MAX_ACCOUNT_CODE] = ""

Definition at line 58 of file cdr.c.

Referenced by ast_channel_alloc().

int ast_default_amaflags = AST_CDR_DOCUMENTATION

Default AMA flag for billing records (CDR's)

Definition at line 57 of file cdr.c.

Referenced by ast_channel_alloc().

struct ast_cdr_batch * batch`[static]`

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

int batchmode`[static]`

Definition at line 90 of file cdr.c.

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

int batchsafeshutdown`[static]`

Definition at line 94 of file cdr.c.

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

int batchscheduleronly`[static]`

Definition at line 93 of file cdr.c.

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

int batchsize`[static]`

Definition at line 91 of file cdr.c.

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

int batchtime`[static]`

Definition at line 92 of file cdr.c.

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

ast_cond_t cdr_pending_cond`[static]`

Definition at line 100 of file cdr.c.

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

int cdr_sched = -1`[static]`

Definition at line 81 of file cdr.c.

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

pthread_t cdr_thread = AST_PTHREADT_NULL`[static]`

Definition at line 82 of file cdr.c.

Referenced by do_reload().

struct ast_cli_entry cli_status`[static]`

Definition at line 1143 of file cdr.c.

Referenced by ast_cdr_engine_init(), and dnsmgr_init().

struct ast_cli_entry cli_submit`[static]`

Definition at line 1134 of file cdr.c.

Referenced by do_reload().

int enabled`[static]`

Definition at line 89 of file cdr.c.

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

struct sched_context* sched`[static]`

Definition at line 80 of file cdr.c.