Fri Feb 10 06:35:06 2012

Asterisk developer's documentation


cdr.h File Reference

Call Detail Record API. More...

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

Include dependency graph for cdr.h:

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

Go to the source code of this file.

Data Structures

struct  ast_cdr
 Responsible for call detail data. More...

Defines

#define AST_MAX_ACCOUNT_CODE   20
#define AST_MAX_USER_FIELD   256

Typedefs

typedef int(* ast_cdrbe )(struct ast_cdr *cdr)
 CDR backend callback.

Enumerations

enum  {
  AST_CDR_FLAG_KEEP_VARS = (1 << 0), AST_CDR_FLAG_POSTED = (1 << 1), AST_CDR_FLAG_LOCKED = (1 << 2), AST_CDR_FLAG_CHILD = (1 << 3),
  AST_CDR_FLAG_POST_DISABLED = (1 << 4), AST_CDR_FLAG_BRIDGED = (1 << 5), AST_CDR_FLAG_MAIN = (1 << 6), AST_CDR_FLAG_ENABLE = (1 << 7),
  AST_CDR_FLAG_ANSLOCKED = (1 << 8), AST_CDR_FLAG_DONT_TOUCH = (1 << 9), AST_CDR_FLAG_POST_ENABLE = (1 << 10), AST_CDR_FLAG_DIALED = (1 << 11),
  AST_CDR_FLAG_ORIGINATED = (1 << 12)
}
 CDR Flags. More...
enum  {
  AST_CDR_NOANSWER = 0, AST_CDR_NULL = (1 << 0), AST_CDR_FAILED = (1 << 1), AST_CDR_BUSY = (1 << 2),
  AST_CDR_ANSWERED = (1 << 3), AST_CDR_CONGESTION = (1 << 4)
}
 CDR Flags - Disposition. More...
enum  { AST_CDR_OMIT = 1, AST_CDR_BILLING = 2, AST_CDR_DOCUMENTATION = 3 }
 CDR AMA Flags. More...

Functions

struct ast_cdrast_cdr_alloc (void)
 Allocate a CDR record.
int ast_cdr_amaflags2int (const char *flag)
 Convert a string to a detail record AMA flag.
void ast_cdr_answer (struct ast_cdr *cdr)
 Answer a call.
struct ast_cdrast_cdr_append (struct ast_cdr *cdr, struct ast_cdr *newcdr)
int ast_cdr_appenduserfield (struct ast_channel *chan, const char *userfield)
 Append to CDR user field for channel (stored in CDR).
void ast_cdr_busy (struct ast_cdr *cdr)
 Busy a call.
void ast_cdr_congestion (struct ast_cdr *cdr)
 A call was set to congestion.
int ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr)
int ast_cdr_data_add_structure (struct ast_data *tree, struct ast_cdr *cdr, int recur)
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.
void ast_cdr_discard (struct ast_cdr *cdr)
 Discard and free a CDR record.
char * ast_cdr_disp2str (int disposition)
 Disposition to a string.
int ast_cdr_disposition (struct ast_cdr *cdr, int cause)
 Save the result of the call based on the AST_CAUSE_*.
struct ast_cdrast_cdr_dup (struct ast_cdr *cdr)
 Duplicate a record.
struct ast_cdrast_cdr_dup_unique (struct ast_cdr *cdr)
 Duplicate a record and increment the sequence number.
struct ast_cdrast_cdr_dup_unique_swap (struct ast_cdr *cdr)
 Duplicate a record and increment the sequence number of the old record.
void ast_cdr_end (struct ast_cdr *cdr)
 End a call.
int ast_cdr_engine_init (void)
 Load the configuration file cdr.conf and possibly start the CDR scheduling thread.
int ast_cdr_engine_reload (void)
 Reload the configuration file cdr.conf and start/stop CDR scheduling thread.
void ast_cdr_engine_term (void)
void ast_cdr_failed (struct ast_cdr *cdr)
 Fail a call.
char * ast_cdr_flags2str (int flags)
void ast_cdr_free (struct ast_cdr *cdr)
 Free a CDR record.
void ast_cdr_free_vars (struct ast_cdr *cdr, int recur)
void ast_cdr_getvar (struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw)
int ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *chan)
 Initialize based on a channel.
int ast_cdr_isset_congestion (void)
int ast_cdr_isset_unanswered (void)
void ast_cdr_merge (struct ast_cdr *to, struct ast_cdr *from)
 Move the non-null data from the "from" cdr to the "to" cdr.
void ast_cdr_noanswer (struct ast_cdr *cdr)
 A call wasn't answered.
int ast_cdr_register (const char *name, const char *desc, ast_cdrbe be)
 Register a CDR handling engine.
void ast_cdr_reset (struct ast_cdr *cdr, struct ast_flags *flags)
 Reset the detail record, optionally posting it first.
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)
 Set account code, will generate AMI event.
int ast_cdr_setamaflags (struct ast_channel *chan, const char *amaflags)
 Set AMA flags for channel.
void ast_cdr_setanswer (struct ast_cdr *cdr, struct timeval t)
 Set the answer time for a call.
void ast_cdr_setapp (struct ast_cdr *cdr, const char *app, const char *data)
 Set the last executed application.
int ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *chan)
 Initialize based on a channel.
void ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chan)
 Set the destination channel, if there was one.
void ast_cdr_setdisposition (struct ast_cdr *cdr, long int disposition)
 Set the disposition for a call.
int ast_cdr_setpeeraccount (struct ast_channel *chan, const char *account)
 Set the peer account.
int ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield)
 Set CDR user field for channel (stored in CDR).
int ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur)
void ast_cdr_specialized_reset (struct ast_cdr *cdr, struct ast_flags *flags)
void ast_cdr_start (struct ast_cdr *cdr)
 Start a call.
void ast_cdr_submit_batch (int shutdown)
 Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines.
void ast_cdr_unregister (const char *name)
 Unregister a CDR handling engine.
int ast_cdr_update (struct ast_channel *chan)
 Update CDR on a channel.
int check_cdr_enabled (void)
 Return TRUE if CDR subsystem is enabled.

Variables

char ast_default_accountcode [AST_MAX_ACCOUNT_CODE]
int ast_default_amaflags


Detailed Description

Call Detail Record API.

Author:
Mark Spencer <markster@digium.com>

Definition in file cdr.h.


Define Documentation

#define AST_MAX_ACCOUNT_CODE   20

Definition at line 74 of file cdr.h.

#define AST_MAX_USER_FIELD   256


Typedef Documentation

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

CDR backend callback.

Warning:
CDR backends should NOT attempt to access the channel associated with a CDR record. This channel is not guaranteed to exist when the CDR backend is invoked.

Definition at line 150 of file cdr.h.


Enumeration Type Documentation

anonymous enum

CDR Flags.

Enumerator:
AST_CDR_FLAG_KEEP_VARS 
AST_CDR_FLAG_POSTED 
AST_CDR_FLAG_LOCKED 
AST_CDR_FLAG_CHILD 
AST_CDR_FLAG_POST_DISABLED 
AST_CDR_FLAG_BRIDGED 
AST_CDR_FLAG_MAIN 
AST_CDR_FLAG_ENABLE 
AST_CDR_FLAG_ANSLOCKED 
AST_CDR_FLAG_DONT_TOUCH 
AST_CDR_FLAG_POST_ENABLE 
AST_CDR_FLAG_DIALED 
AST_CDR_FLAG_ORIGINATED 

Definition at line 36 of file cdr.h.

00036      {
00037    AST_CDR_FLAG_KEEP_VARS     = (1 << 0),
00038    AST_CDR_FLAG_POSTED        = (1 << 1),
00039    AST_CDR_FLAG_LOCKED        = (1 << 2),
00040    AST_CDR_FLAG_CHILD         = (1 << 3),
00041    AST_CDR_FLAG_POST_DISABLED = (1 << 4),
00042    AST_CDR_FLAG_BRIDGED       = (1 << 5),
00043    AST_CDR_FLAG_MAIN          = (1 << 6),
00044    AST_CDR_FLAG_ENABLE        = (1 << 7),
00045    AST_CDR_FLAG_ANSLOCKED     = (1 << 8),
00046    AST_CDR_FLAG_DONT_TOUCH    = (1 << 9),
00047    AST_CDR_FLAG_POST_ENABLE   = (1 << 10),
00048    AST_CDR_FLAG_DIALED        = (1 << 11),
00049    AST_CDR_FLAG_ORIGINATED    = (1 << 12),
00050 };

anonymous enum

CDR Flags - Disposition.

Enumerator:
AST_CDR_NOANSWER 
AST_CDR_NULL 
AST_CDR_FAILED 
AST_CDR_BUSY 
AST_CDR_ANSWERED 
AST_CDR_CONGESTION 

Definition at line 55 of file cdr.h.

00055      {
00056    AST_CDR_NOANSWER = 0,
00057    AST_CDR_NULL     = (1 << 0),
00058    AST_CDR_FAILED   = (1 << 1),
00059    AST_CDR_BUSY     = (1 << 2),
00060    AST_CDR_ANSWERED = (1 << 3),
00061    AST_CDR_CONGESTION = (1 << 4),
00062 };

anonymous enum

CDR AMA Flags.

Enumerator:
AST_CDR_OMIT 
AST_CDR_BILLING 
AST_CDR_DOCUMENTATION 

Definition at line 67 of file cdr.h.

00067      {
00068    AST_CDR_OMIT          = 1,
00069    AST_CDR_BILLING       = 2,
00070    AST_CDR_DOCUMENTATION = 3,
00071 };


Function Documentation

struct ast_cdr* ast_cdr_alloc ( void   )  [read]

Allocate a CDR record.

Return values:
a malloc'd ast_cdr structure
NULL on error (malloc failure)

Definition at line 502 of file cdr.c.

References ast_calloc, ast_log(), and LOG_ERROR.

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

00503 {
00504    struct ast_cdr *x;
00505    x = ast_calloc(1, sizeof(*x));
00506    if (!x)
00507       ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n");
00508    return x;
00509 }

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 1135 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(), config_parse_variables(), process_dahdi(), and set_config().

01136 {
01137    if (!strcasecmp(flag, "default"))
01138       return 0;
01139    if (!strcasecmp(flag, "omit"))
01140       return AST_CDR_OMIT;
01141    if (!strcasecmp(flag, "billing"))
01142       return AST_CDR_BILLING;
01143    if (!strcasecmp(flag, "documentation"))
01144       return AST_CDR_DOCUMENTATION;
01145    return -1;
01146 }

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
Note:
NULL argument is just fine.

Definition at line 737 of file cdr.c.

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

Referenced by __ast_request_and_dial(), ast_bridge_call(), and ast_raw_answer().

00738 {
00739 
00740    for (; cdr; cdr = cdr->next) {
00741       if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED))
00742          continue;
00743       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00744          continue;
00745       check_post(cdr);
00746       if (cdr->disposition < AST_CDR_ANSWERED)
00747          cdr->disposition = AST_CDR_ANSWERED;
00748       if (ast_tvzero(cdr->answer))
00749          cdr->answer = ast_tvnow();
00750    }
00751 }

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

Definition at line 1246 of file cdr.c.

References ast_cdr::next.

Referenced by ast_cdr_fork(), ast_cdr_merge(), attempt_transfer(), and try_calling().

01247 {
01248    struct ast_cdr *ret;
01249 
01250    if (cdr) {
01251       ret = cdr;
01252 
01253       while (cdr->next)
01254          cdr = cdr->next;
01255       cdr->next = newcdr;
01256    } else {
01257       ret = newcdr;
01258    }
01259 
01260    return ret;
01261 }

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

Append to CDR user field for channel (stored in CDR).

Note:
The channel should be locked before calling.

Definition at line 1099 of file cdr.c.

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

Referenced by ast_bridge_call().

01100 {
01101    struct ast_cdr *cdr = chan->cdr;
01102 
01103    for ( ; cdr ; cdr = cdr->next) {
01104       int len = strlen(cdr->userfield);
01105 
01106       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
01107          ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len);
01108    }
01109 
01110    return 0;
01111 }

void ast_cdr_busy ( struct ast_cdr cdr  ) 

Busy a call.

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

Definition at line 753 of file cdr.c.

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

00754 {
00755 
00756    for (; cdr; cdr = cdr->next) {
00757       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00758          check_post(cdr);
00759          cdr->disposition = AST_CDR_BUSY;
00760       }
00761    }
00762 }

void ast_cdr_congestion ( struct ast_cdr cdr  ) 

A call was set to congestion.

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

Definition at line 787 of file cdr.c.

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

Referenced by ast_cdr_disposition(), and pbx_builtin_congestion().

00788 {
00789    char *chan;
00790 
00791    /* if congestion log is disabled, pass the buck to ast_cdr_failed */
00792    if (!congestion) {
00793       ast_cdr_failed(cdr);
00794    }
00795 
00796    while (cdr && congestion) {
00797       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00798          chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
00799 
00800          if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) {
00801             ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00802          }
00803 
00804          if (cdr->disposition < AST_CDR_CONGESTION) {
00805             cdr->disposition = AST_CDR_CONGESTION;
00806          }
00807       }
00808       cdr = cdr->next;
00809    }
00810 }

int ast_cdr_copy_vars ( struct ast_cdr to_cdr,
struct ast_cdr from_cdr 
)

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

00387 {
00388    struct ast_var_t *variables, *newvariable = NULL;
00389    struct varshead *headpa, *headpb;
00390    const char *var, *val;
00391    int x = 0;
00392 
00393    if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */
00394       return 0;
00395 
00396    headpa = &from_cdr->varshead;
00397    headpb = &to_cdr->varshead;
00398 
00399    AST_LIST_TRAVERSE(headpa,variables,entries) {
00400       if (variables &&
00401           (var = ast_var_name(variables)) && (val = ast_var_value(variables)) &&
00402           !ast_strlen_zero(var) && !ast_strlen_zero(val)) {
00403          newvariable = ast_var_assign(var, val);
00404          AST_LIST_INSERT_HEAD(headpb, newvariable, entries);
00405          x++;
00406       }
00407    }
00408 
00409    return x;
00410 }

int ast_cdr_data_add_structure ( struct ast_data tree,
struct ast_cdr cdr,
int  recur 
)

Parameters:
[in] tree Where to insert the cdr.
[in] cdr The cdr structure to insert in 'tree'.
[in] recur Go throw all the cdr levels.
Return values:
<0 on error.
0 on success.

Definition at line 1670 of file cdr.c.

References ast_cdr_getvar(), ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_name(), ast_var_value(), cdr_readonly_vars, ast_var_t::entries, ast_cdr::next, var, and ast_cdr::varshead.

Referenced by ast_channel_data_add_structure().

01671 {
01672    struct ast_cdr *tmpcdr;
01673    struct ast_data *level;
01674    struct ast_var_t *variables;
01675    const char *var, *val;
01676    int x = 1, i;
01677    char workspace[256];
01678    char *tmp;
01679 
01680    if (!cdr) {
01681       return -1;
01682    }
01683 
01684    for (tmpcdr = cdr; tmpcdr; tmpcdr = (recur ? tmpcdr->next : NULL)) {
01685       level = ast_data_add_node(tree, "level");
01686       if (!level) {
01687          continue;
01688       }
01689 
01690       ast_data_add_int(level, "level_number", x);
01691 
01692       AST_LIST_TRAVERSE(&tmpcdr->varshead, variables, entries) {
01693          if (variables && (var = ast_var_name(variables)) &&
01694                (val = ast_var_value(variables)) && !ast_strlen_zero(var)
01695                && !ast_strlen_zero(val)) {
01696             ast_data_add_str(level, var, val);
01697          } else {
01698             break;
01699          }
01700       }
01701 
01702       for (i = 0; cdr_readonly_vars[i]; i++) {
01703          workspace[0] = 0; /* null out the workspace, because the cdr_get_tv() won't write anything if time is NULL, so you get old vals */
01704          ast_cdr_getvar(tmpcdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0);
01705          if (!tmp) {
01706             continue;
01707          }
01708          ast_data_add_str(level, cdr_readonly_vars[i], tmp);
01709       }
01710 
01711       x++;
01712    }
01713 
01714    return 0;
01715 }

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

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

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

01352 {
01353    struct ast_cdr_batch_item *newtail;
01354    int curr;
01355 
01356    if (!cdr)
01357       return;
01358 
01359    /* maybe they disabled CDR stuff completely, so just drop it */
01360    if (!enabled) {
01361       ast_debug(1, "Dropping CDR !\n");
01362       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01363       ast_cdr_free(cdr);
01364       return;
01365    }
01366 
01367    /* post stuff immediately if we are not in batch mode, this is legacy behaviour */
01368    if (!batchmode) {
01369       post_cdr(cdr);
01370       ast_cdr_free(cdr);
01371       return;
01372    }
01373 
01374    /* otherwise, each CDR gets put into a batch list (at the end) */
01375    ast_debug(1, "CDR detaching from this thread\n");
01376 
01377    /* we'll need a new tail for every CDR */
01378    if (!(newtail = ast_calloc(1, sizeof(*newtail)))) {
01379       post_cdr(cdr);
01380       ast_cdr_free(cdr);
01381       return;
01382    }
01383 
01384    /* don't traverse a whole list (just keep track of the tail) */
01385    ast_mutex_lock(&cdr_batch_lock);
01386    if (!batch)
01387       init_batch();
01388    if (!batch->head) {
01389       /* new batch is empty, so point the head at the new tail */
01390       batch->head = newtail;
01391    } else {
01392       /* already got a batch with something in it, so just append a new tail */
01393       batch->tail->next = newtail;
01394    }
01395    newtail->cdr = cdr;
01396    batch->tail = newtail;
01397    curr = batch->size++;
01398    ast_mutex_unlock(&cdr_batch_lock);
01399 
01400    /* if we have enough stuff to post, then do it */
01401    if (curr >= (batchsize - 1))
01402       submit_unscheduled_batch();
01403 }

void ast_cdr_discard ( struct ast_cdr cdr  ) 

Discard and free a CDR record.

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

Definition at line 491 of file cdr.c.

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

Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_merge(), ast_channel_destructor(), and ast_dummy_channel_destructor().

00492 {
00493    while (cdr) {
00494       struct ast_cdr *next = cdr->next;
00495 
00496       ast_cdr_free_vars(cdr, 0);
00497       ast_free(cdr);
00498       cdr = next;
00499    }
00500 }

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

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

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

00988 {
00989    switch (disposition) {
00990    case AST_CDR_NULL:
00991       return "NO ANSWER"; /* by default, for backward compatibility */
00992    case AST_CDR_NOANSWER:
00993       return "NO ANSWER";
00994    case AST_CDR_FAILED:
00995       return "FAILED";
00996    case AST_CDR_BUSY:
00997       return "BUSY";
00998    case AST_CDR_ANSWERED:
00999       return "ANSWERED";
01000    case AST_CDR_CONGESTION:
01001       return "CONGESTION";
01002    }
01003    return "UNKNOWN";
01004 }

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
cause the AST_CAUSE_* Returns nothing

Definition at line 815 of file cdr.c.

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

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

00816 {
00817    int res = 0;
00818 
00819    for (; cdr; cdr = cdr->next) {
00820       switch (cause) {  /* handle all the non failure, busy cases, return 0 not to set disposition,
00821                      return -1 to set disposition to FAILED */
00822       case AST_CAUSE_BUSY:
00823          ast_cdr_busy(cdr);
00824          break;
00825       case AST_CAUSE_NO_ANSWER:
00826          ast_cdr_noanswer(cdr);
00827          break;
00828       case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
00829          ast_cdr_congestion(cdr);
00830          break;
00831       case AST_CAUSE_NORMAL:
00832          break;
00833       default:
00834          res = -1;
00835       }
00836    }
00837    return res;
00838 }

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

Duplicate a record.

Parameters:
cdr the record to duplicate
Return values:
a malloc'd ast_cdr structure,
NULL on error (malloc failure)
See also:
ast_cdr_dup_unique()

ast_cdr_dup_unique_swap()

Duplicate a CDR record
Returns:
Pointer to new CDR record

Definition at line 215 of file cdr.c.

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

Referenced by ast_async_goto(), ast_cdr_dup_unique(), ast_cdr_dup_unique_swap(), ast_cdr_merge(), custom_log(), manager_log(), syslog_log(), try_calling(), and write_cdr().

00216 {
00217    struct ast_cdr *newcdr;
00218 
00219    if (!cdr) /* don't die if we get a null cdr pointer */
00220       return NULL;
00221    newcdr = ast_cdr_alloc();
00222    if (!newcdr)
00223       return NULL;
00224 
00225    memcpy(newcdr, cdr, sizeof(*newcdr));
00226    /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */
00227    memset(&newcdr->varshead, 0, sizeof(newcdr->varshead));
00228    ast_cdr_copy_vars(newcdr, cdr);
00229    newcdr->next = NULL;
00230 
00231    return newcdr;
00232 }

struct ast_cdr* ast_cdr_dup_unique ( struct ast_cdr cdr  )  [read]

Duplicate a record and increment the sequence number.

Parameters:
cdr the record to duplicate
Return values:
a malloc'd ast_cdr structure,
NULL on error (malloc failure)
See also:
ast_cdr_dup()

ast_cdr_dup_unique_swap()

Definition at line 192 of file cdr.c.

References ast_cdr_dup(), and cdr_seq_inc().

Referenced by ast_cdr_fork().

00193 {
00194    struct ast_cdr *newcdr = ast_cdr_dup(cdr);
00195    if (!newcdr)
00196       return NULL;
00197 
00198    cdr_seq_inc(newcdr);
00199    return newcdr;
00200 }

struct ast_cdr* ast_cdr_dup_unique_swap ( struct ast_cdr cdr  )  [read]

Duplicate a record and increment the sequence number of the old record.

Parameters:
cdr the record to duplicate
Return values:
a malloc'd ast_cdr structure,
NULL on error (malloc failure)
Note:
This version increments the original CDR's sequence number rather than the duplicate's sequence number. The effect is as if the original CDR's sequence number was swapped with the duplicate's sequence number.
See also:
ast_cdr_dup()

ast_cdr_dup_unique()

Definition at line 202 of file cdr.c.

References ast_cdr_dup(), and cdr_seq_inc().

Referenced by ast_bridge_call(), and ast_cdr_reset().

00203 {
00204    struct ast_cdr *newcdr = ast_cdr_dup(cdr);
00205    if (!newcdr)
00206       return NULL;
00207 
00208    cdr_seq_inc(cdr);
00209    return newcdr;
00210 }

void ast_cdr_end ( struct ast_cdr cdr  ) 

End a call.

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

Definition at line 961 of file cdr.c.

References ast_cdr::answer, AST_CDR_ANSWERED, AST_CDR_FAILED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_log(), AST_OPT_FLAG_INITIATED_SECONDS, ast_options, ast_test_flag, ast_tvnow(), ast_tvzero(), ast_cdr::billsec, ast_cdr::channel, check_post(), ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, LOG_WARNING, ast_cdr::next, S_OR, and ast_cdr::start.

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

00962 {
00963    for ( ; cdr ; cdr = cdr->next) {
00964       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00965          continue;
00966       check_post(cdr);
00967       if (ast_tvzero(cdr->end))
00968          cdr->end = ast_tvnow();
00969       if (ast_tvzero(cdr->start)) {
00970          ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>"));
00971          cdr->disposition = AST_CDR_FAILED;
00972       } else
00973          cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec;
00974       if (ast_tvzero(cdr->answer)) {
00975          if (cdr->disposition == AST_CDR_ANSWERED) {
00976             ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>"));
00977             cdr->disposition = AST_CDR_FAILED;
00978          }
00979       } else {
00980          cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec;
00981          if (ast_test_flag(&ast_options, AST_OPT_FLAG_INITIATED_SECONDS))
00982             cdr->billsec += cdr->end.tv_usec > cdr->answer.tv_usec ? 1 : 0;
00983       }
00984    }
00985 }

int ast_cdr_engine_init ( void   ) 

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

Definition at line 1636 of file cdr.c.

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

Referenced by main().

01637 {
01638    int res;
01639 
01640    sched = ast_sched_context_create();
01641    if (!sched) {
01642       ast_log(LOG_ERROR, "Unable to create schedule context.\n");
01643       return -1;
01644    }
01645 
01646    ast_cli_register(&cli_status);
01647 
01648    res = do_reload(0);
01649    if (res) {
01650       ast_mutex_lock(&cdr_batch_lock);
01651       res = init_batch();
01652       ast_mutex_unlock(&cdr_batch_lock);
01653    }
01654 
01655    return res;
01656 }

int ast_cdr_engine_reload ( void   ) 

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

Definition at line 1665 of file cdr.c.

References do_reload().

01666 {
01667    return do_reload(1);
01668 }

void ast_cdr_engine_term ( void   ) 

Submit any remaining CDRs and prepare for shutdown

Definition at line 1660 of file cdr.c.

References ast_cdr_submit_batch(), and batchsafeshutdown.

Referenced by can_safely_quit(), and do_reload().

01661 {
01662    ast_cdr_submit_batch(batchsafeshutdown);
01663 }

void ast_cdr_failed ( struct ast_cdr cdr  ) 

Fail a call.

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

Definition at line 764 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_congestion(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), clear_caller(), findmeexec(), handle_cause(), try_calling(), and wait_for_answer().

00765 {
00766    for (; cdr; cdr = cdr->next) {
00767       check_post(cdr);
00768       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00769          check_post(cdr);
00770          if (cdr->disposition < AST_CDR_FAILED)
00771             cdr->disposition = AST_CDR_FAILED;
00772       }
00773    }
00774 }

char* ast_cdr_flags2str ( int  flag  ) 

Flags to a string

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

Definition at line 1007 of file cdr.c.

References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.

Referenced by _sip_show_peer(), _skinny_show_line(), ast_cdr_getvar(), ast_channel_data_add_structure(), build_csv_record(), build_radius_record(), csv_log(), manager_log(), peers_data_provider_get(), sip_show_user(), tds_log(), and users_data_provider_get().

01008 {
01009    switch (flag) {
01010    case AST_CDR_OMIT:
01011       return "OMIT";
01012    case AST_CDR_BILLING:
01013       return "BILLING";
01014    case AST_CDR_DOCUMENTATION:
01015       return "DOCUMENTATION";
01016    }
01017    return "Unknown";
01018 }

void ast_cdr_free ( struct ast_cdr cdr  ) 

Free a CDR record.

Parameters:
cdr ast_cdr structure to free Returns nothing

Definition at line 478 of file cdr.c.

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

Referenced by ast_cdr_detach(), and do_batch_backend_process().

00479 {
00480 
00481    while (cdr) {
00482       struct ast_cdr *next = cdr->next;
00483 
00484       ast_cdr_free_vars(cdr, 0);
00485       ast_free(cdr);
00486       cdr = next;
00487    }
00488 }

void ast_cdr_free_vars ( struct ast_cdr cdr,
int  recur 
)

Definition at line 457 of file cdr.c.

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

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

00458 {
00459 
00460    /* clear variables */
00461    for (; cdr; cdr = recur ? cdr->next : NULL) {
00462       struct ast_var_t *vardata;
00463       struct varshead *headp = &cdr->varshead;
00464       while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
00465          ast_var_delete(vardata);
00466    }
00467 }

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

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

Referenced by ast_cdr_data_add_structure(), ast_cdr_serialize_variables(), cdr_handler(), cdr_read(), odbc_log(), and pgsql_log().

00267 {
00268    const char *fmt = "%Y-%m-%d %T";
00269    const char *varbuf;
00270 
00271    if (!cdr)  /* don't die if the cdr is null */
00272       return;
00273 
00274    *ret = NULL;
00275    /* special vars (the ones from the struct ast_cdr when requested by name)
00276       I'd almost say we should convert all the stringed vals to vars */
00277 
00278    if (!strcasecmp(name, "clid"))
00279       ast_copy_string(workspace, cdr->clid, workspacelen);
00280    else if (!strcasecmp(name, "src"))
00281       ast_copy_string(workspace, cdr->src, workspacelen);
00282    else if (!strcasecmp(name, "dst"))
00283       ast_copy_string(workspace, cdr->dst, workspacelen);
00284    else if (!strcasecmp(name, "dcontext"))
00285       ast_copy_string(workspace, cdr->dcontext, workspacelen);
00286    else if (!strcasecmp(name, "channel"))
00287       ast_copy_string(workspace, cdr->channel, workspacelen);
00288    else if (!strcasecmp(name, "dstchannel"))
00289       ast_copy_string(workspace, cdr->dstchannel, workspacelen);
00290    else if (!strcasecmp(name, "lastapp"))
00291       ast_copy_string(workspace, cdr->lastapp, workspacelen);
00292    else if (!strcasecmp(name, "lastdata"))
00293       ast_copy_string(workspace, cdr->lastdata, workspacelen);
00294    else if (!strcasecmp(name, "start"))
00295       cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen);
00296    else if (!strcasecmp(name, "answer"))
00297       cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen);
00298    else if (!strcasecmp(name, "end"))
00299       cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen);
00300    else if (!strcasecmp(name, "duration"))
00301       snprintf(workspace, workspacelen, "%ld", cdr->duration ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000);
00302    else if (!strcasecmp(name, "billsec"))
00303       snprintf(workspace, workspacelen, "%ld", cdr->billsec || cdr->answer.tv_sec == 0 ? cdr->billsec : (long)ast_tvdiff_ms(ast_tvnow(), cdr->answer) / 1000);
00304    else if (!strcasecmp(name, "disposition")) {
00305       if (raw) {
00306          snprintf(workspace, workspacelen, "%ld", cdr->disposition);
00307       } else {
00308          ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen);
00309       }
00310    } else if (!strcasecmp(name, "amaflags")) {
00311       if (raw) {
00312          snprintf(workspace, workspacelen, "%ld", cdr->amaflags);
00313       } else {
00314          ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen);
00315       }
00316    } else if (!strcasecmp(name, "accountcode"))
00317       ast_copy_string(workspace, cdr->accountcode, workspacelen);
00318    else if (!strcasecmp(name, "peeraccount"))
00319       ast_copy_string(workspace, cdr->peeraccount, workspacelen);
00320    else if (!strcasecmp(name, "uniqueid"))
00321       ast_copy_string(workspace, cdr->uniqueid, workspacelen);
00322    else if (!strcasecmp(name, "linkedid"))
00323       ast_copy_string(workspace, cdr->linkedid, workspacelen);
00324    else if (!strcasecmp(name, "userfield"))
00325       ast_copy_string(workspace, cdr->userfield, workspacelen);
00326    else if (!strcasecmp(name, "sequence"))
00327       snprintf(workspace, workspacelen, "%d", cdr->sequence);
00328    else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur)))
00329       ast_copy_string(workspace, varbuf, workspacelen);
00330    else
00331       workspace[0] = '\0';
00332 
00333    if (!ast_strlen_zero(workspace))
00334       *ret = workspace;
00335 }

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
Note:
The channel should be locked before calling.
Returns:
0 by default

Definition at line 925 of file cdr.c.

References ast_channel::_state, ast_cdr::accountcode, ast_channel::amaflags, ast_cdr::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_channel_accountcode(), ast_channel_linkedid(), ast_channel_name(), ast_channel_peeraccount(), ast_channel_uniqueid(), ast_copy_string(), AST_STATE_UP, ast_test_flag, cdr_seq_inc(), ast_cdr::channel, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, ast_cdr::linkedid, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, ast_cdr::peeraccount, S_OR, set_one_cid(), and ast_cdr::uniqueid.

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

00926 {
00927    for ( ; cdr ; cdr = cdr->next) {
00928       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00929          ast_copy_string(cdr->channel, ast_channel_name(c), sizeof(cdr->channel));
00930          set_one_cid(cdr, c);
00931          cdr_seq_inc(cdr);
00932 
00933          cdr->disposition = (c->_state == AST_STATE_UP) ?  AST_CDR_ANSWERED : AST_CDR_NOANSWER;
00934          cdr->amaflags = c->amaflags ? c->amaflags :  ast_default_amaflags;
00935          ast_copy_string(cdr->accountcode, ast_channel_accountcode(c), sizeof(cdr->accountcode));
00936          ast_copy_string(cdr->peeraccount, ast_channel_peeraccount(c), sizeof(cdr->peeraccount));
00937          /* Destination information */
00938          ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst));
00939          ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext));
00940          /* Unique call identifier */
00941          ast_copy_string(cdr->uniqueid, ast_channel_uniqueid(c), sizeof(cdr->uniqueid));
00942          /* Linked call identifier */
00943          ast_copy_string(cdr->linkedid, ast_channel_linkedid(c), sizeof(cdr->linkedid));
00944       }
00945    }
00946    return 0;
00947 }

int ast_cdr_isset_congestion ( void   ) 

Definition at line 187 of file cdr.c.

References congestion.

00188 {
00189    return congestion;
00190 }

int ast_cdr_isset_unanswered ( void   ) 

Definition at line 182 of file cdr.c.

References unanswered.

Referenced by ring_entry(), and try_calling().

00183 {
00184    return unanswered;
00185 }

void ast_cdr_merge ( struct ast_cdr to,
struct ast_cdr from 
)

Move the non-null data from the "from" cdr to the "to" cdr.

Parameters:
to the cdr to get the goodies
from the cdr to give the goodies

Definition at line 546 of file cdr.c.

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

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

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" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application.

Definition at line 776 of file cdr.c.

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

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

00777 {
00778    while (cdr) {
00779       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00780          check_post(cdr);
00781          cdr->disposition = AST_CDR_NOANSWER;
00782       }
00783       cdr = cdr->next;
00784    }
00785 }

int ast_cdr_register ( const char *  name,
const char *  desc,
ast_cdrbe  be 
)

Register a CDR handling engine.

Parameters:
name name associated with the particular CDR handler
desc description of the CDR handler
be function pointer to a CDR handler Used to register a Call Detail Record handler.
Return values:
0 on success.
-1 on error
Register a CDR handling engine.

Return values:
0 on success.
-1 on error

Definition at line 127 of file cdr.c.

References ast_calloc, ast_copy_string(), ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_cdr_beitem::be, ast_cdr_beitem::desc, ast_cdr_beitem::list, LOG_WARNING, and ast_cdr_beitem::name.

Referenced by load_config(), load_module(), odbc_load_module(), and unload_module().

00128 {
00129    struct ast_cdr_beitem *i = NULL;
00130 
00131    if (!name)
00132       return -1;
00133 
00134    if (!be) {
00135       ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
00136       return -1;
00137    }
00138 
00139    AST_RWLIST_WRLOCK(&be_list);
00140    AST_RWLIST_TRAVERSE(&be_list, i, list) {
00141       if (!strcasecmp(name, i->name)) {
00142          ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
00143          AST_RWLIST_UNLOCK(&be_list);
00144          return -1;
00145       }
00146    }
00147 
00148    if (!(i = ast_calloc(1, sizeof(*i))))
00149       return -1;
00150 
00151    i->be = be;
00152    ast_copy_string(i->name, name, sizeof(i->name));
00153    ast_copy_string(i->desc, desc, sizeof(i->desc));
00154 
00155    AST_RWLIST_INSERT_HEAD(&be_list, i, list);
00156    AST_RWLIST_UNLOCK(&be_list);
00157 
00158    return 0;
00159 }

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

References ast_cdr::answer, ast_cdr_detach(), ast_cdr_dup_unique_swap(), ast_cdr_end(), AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POST_ENABLE, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), AST_CDR_NOANSWER, 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_cdr_fork(), dial_exec_full(), disa_exec(), pbx_builtin_resetcdr(), and try_calling().

01180 {
01181    struct ast_cdr *duplicate;
01182    struct ast_flags flags = { 0 };
01183 
01184    if (_flags)
01185       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
01186 
01187    for ( ; cdr ; cdr = cdr->next) {
01188       /* Detach if post is requested */
01189       if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01190          if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) {
01191             ast_cdr_end(cdr);
01192             if ((duplicate = ast_cdr_dup_unique_swap(cdr))) {
01193                ast_cdr_detach(duplicate);
01194             }
01195             ast_set_flag(cdr, AST_CDR_FLAG_POSTED);
01196          }
01197 
01198          /* enable CDR only */
01199          if (ast_test_flag(&flags, AST_CDR_FLAG_POST_ENABLE)) {
01200             ast_clear_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01201             continue;
01202          }
01203 
01204          /* clear variables */
01205          if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
01206             ast_cdr_free_vars(cdr, 0);
01207          }
01208 
01209          /* Reset to initial state */
01210          ast_clear_flag(cdr, AST_FLAGS_ALL);
01211          memset(&cdr->start, 0, sizeof(cdr->start));
01212          memset(&cdr->end, 0, sizeof(cdr->end));
01213          memset(&cdr->answer, 0, sizeof(cdr->answer));
01214          cdr->billsec = 0;
01215          cdr->duration = 0;
01216          ast_cdr_start(cdr);
01217          cdr->disposition = AST_CDR_NOANSWER;
01218       }
01219    }
01220 }

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

Definition at line 412 of file cdr.c.

References ast_cdr_getvar(), AST_LIST_TRAVERSE, ast_log(), ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), cdr_readonly_vars, ast_var_t::entries, LOG_ERROR, ast_cdr::next, S_OR, total, var, and ast_cdr::varshead.

Referenced by handle_showchan().

00413 {
00414    struct ast_var_t *variables;
00415    const char *var;
00416    char *tmp;
00417    char workspace[256];
00418    int total = 0, x = 0, i;
00419 
00420    ast_str_reset(*buf);
00421 
00422    for (; cdr; cdr = recur ? cdr->next : NULL) {
00423       if (++x > 1)
00424          ast_str_append(buf, 0, "\n");
00425 
00426       AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
00427          if (!(var = ast_var_name(variables))) {
00428             continue;
00429          }
00430 
00431          if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variables), ""), sep) < 0) {
00432             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00433             break;
00434          }
00435 
00436          total++;
00437       }
00438 
00439       for (i = 0; cdr_readonly_vars[i]; i++) {
00440          workspace[0] = 0; /* null out the workspace, because the cdr_get_tv() won't write anything if time is NULL, so you get old vals */
00441          ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0);
00442          if (!tmp)
00443             continue;
00444 
00445          if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep) < 0) {
00446             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
00447             break;
00448          } else
00449             total++;
00450       }
00451    }
00452 
00453    return total;
00454 }

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

Set account code, will generate AMI event.

Note:
The channel should be locked before calling.

Definition at line 1020 of file cdr.c.

References ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_channel_accountcode(), ast_channel_name(), ast_channel_uniqueid(), ast_copy_string(), ast_manager_event, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, EVENT_FLAG_CALL, and ast_cdr::next.

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

01021 {
01022    struct ast_cdr *cdr = chan->cdr;
01023    const char *old_acct = "";
01024 
01025    if (!ast_strlen_zero(ast_channel_accountcode(chan))) {
01026       old_acct = ast_strdupa(ast_channel_accountcode(chan));
01027    }
01028 
01029    ast_channel_accountcode_set(chan, account);
01030    for ( ; cdr ; cdr = cdr->next) {
01031       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01032          ast_copy_string(cdr->accountcode, ast_channel_accountcode(chan), sizeof(cdr->accountcode));
01033       }
01034    }
01035 
01036    ast_manager_event(chan, EVENT_FLAG_CALL, "NewAccountCode",
01037          "Channel: %s\r\n"
01038          "Uniqueid: %s\r\n"
01039          "AccountCode: %s\r\n"
01040          "OldAccountCode: %s\r\n",
01041          ast_channel_name(chan), ast_channel_uniqueid(chan), ast_channel_accountcode(chan), old_acct);
01042 
01043    return 0;
01044 }

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

Set AMA flags for channel.

Note:
The channel should be locked before calling.

Definition at line 1072 of file cdr.c.

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

Referenced by cdr_write(), and pbx_builtin_setamaflags().

01073 {
01074    struct ast_cdr *cdr;
01075    int newflag = ast_cdr_amaflags2int(flag);
01076    if (newflag) {
01077       for (cdr = chan->cdr; cdr; cdr = cdr->next) {
01078          if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01079             cdr->amaflags = newflag;
01080          }
01081       }
01082    }
01083 
01084    return 0;
01085 }

void ast_cdr_setanswer ( struct ast_cdr cdr,
struct timeval  t 
)

Set the answer time for a call.

Parameters:
cdr the cdr you wish to associate with the call
t the answer time Starts all CDR stuff necessary for doing CDR when answering a call NULL argument is just fine.

Definition at line 862 of file cdr.c.

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

Referenced by ast_bridge_call(), and dial_exec_full().

00863 {
00864 
00865    for (; cdr; cdr = cdr->next) {
00866       if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED))
00867          continue;
00868       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00869          continue;
00870       check_post(cdr);
00871       cdr->answer = t;
00872    }
00873 }

void ast_cdr_setapp ( struct ast_cdr cdr,
const char *  app,
const 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 850 of file cdr.c.

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

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

00851 {
00852 
00853    for (; cdr; cdr = cdr->next) {
00854       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00855          check_post(cdr);
00856          ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp));
00857          ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata));
00858       }
00859    }
00860 }

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
Note:
The channel should be locked before calling.
Returns:
0 by default

Definition at line 911 of file cdr.c.

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

Referenced by ast_bridge_call(), ast_channel_set_caller_event(), ast_set_callerid(), and callerid_write().

00912 {
00913    for (; cdr; cdr = cdr->next) {
00914       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00915          set_one_cid(cdr, c);
00916    }
00917    return 0;
00918 }

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

Set the destination channel, if there was one.

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

Definition at line 840 of file cdr.c.

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

Referenced by dial_exec_full(), parked_call_exec(), ring_entry(), and try_calling().

00841 {
00842    for (; cdr; cdr = cdr->next) {
00843       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00844          check_post(cdr);
00845          ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel));
00846       }
00847    }
00848 }

void ast_cdr_setdisposition ( struct ast_cdr cdr,
long int  disposition 
)

Set the disposition for a call.

Parameters:
cdr the cdr you wish to associate with the call
disposition the new disposition Set the disposition on a call. NULL argument is just fine.

Definition at line 875 of file cdr.c.

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

Referenced by ast_bridge_call().

00876 {
00877 
00878    for (; cdr; cdr = cdr->next) {
00879       if (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00880          continue;
00881       check_post(cdr);
00882       cdr->disposition = disposition;
00883    }
00884 }

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

Set the peer account.

Note:
The channel should be locked before calling.

Definition at line 1046 of file cdr.c.

References AST_CDR_FLAG_LOCKED, ast_channel_name(), ast_channel_peeraccount(), ast_channel_uniqueid(), ast_copy_string(), ast_manager_event, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, EVENT_FLAG_CALL, ast_cdr::next, and ast_cdr::peeraccount.

Referenced by cdr_write().

01047 {
01048    struct ast_cdr *cdr = chan->cdr;
01049    const char *old_acct = "";
01050 
01051    if (!ast_strlen_zero(ast_channel_peeraccount(chan))) {
01052       old_acct = ast_strdupa(ast_channel_peeraccount(chan));
01053    }
01054 
01055    ast_channel_peeraccount_set(chan, account);
01056    for ( ; cdr ; cdr = cdr->next) {
01057       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01058          ast_copy_string(cdr->peeraccount, ast_channel_peeraccount(chan), sizeof(cdr->peeraccount));
01059       }
01060    }
01061 
01062    ast_manager_event(chan, EVENT_FLAG_CALL, "NewPeerAccount",
01063          "Channel: %s\r\n"
01064          "Uniqueid: %s\r\n"
01065          "PeerAccount: %s\r\n"
01066          "OldPeerAccount: %s\r\n",
01067          ast_channel_name(chan), ast_channel_uniqueid(chan), ast_channel_peeraccount(chan), old_acct);
01068 
01069    return 0;
01070 }

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

Set CDR user field for channel (stored in CDR).

Note:
The channel should be locked before calling.

Definition at line 1087 of file cdr.c.

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

Referenced by __agent_start_monitoring(), ast_bridge_call(), cdr_write(), handle_request_info(), and start_monitor_exec().

01088 {
01089    struct ast_cdr *cdr = chan->cdr;
01090 
01091    for ( ; cdr ; cdr = cdr->next) {
01092       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
01093          ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield));
01094    }
01095 
01096    return 0;
01097 }

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

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

Referenced by ast_cdr_fork(), cdr_write(), and set_one_cid().

00346 {
00347    struct ast_var_t *newvariable;
00348    struct varshead *headp;
00349    int x;
00350 
00351    for (x = 0; cdr_readonly_vars[x]; x++) {
00352       if (!strcasecmp(name, cdr_readonly_vars[x])) {
00353          ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name);
00354          return -1;
00355       }
00356    }
00357 
00358    if (!cdr) {
00359       ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n");
00360       return -1;
00361    }
00362 
00363    for (; cdr; cdr = recur ? cdr->next : NULL) {
00364       if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED))
00365          continue;
00366       headp = &cdr->varshead;
00367       AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
00368          if (!strcasecmp(ast_var_name(newvariable), name)) {
00369             /* there is already such a variable, delete it */
00370             AST_LIST_REMOVE_CURRENT(entries);
00371             ast_var_delete(newvariable);
00372             break;
00373          }
00374       }
00375       AST_LIST_TRAVERSE_SAFE_END;
00376 
00377       if (value) {
00378          newvariable = ast_var_assign(name, value);
00379          AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00380       }
00381    }
00382 
00383    return 0;
00384 }

void ast_cdr_specialized_reset ( struct ast_cdr cdr,
struct ast_flags flags 
)

Reset the detail record times, flags

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

Definition at line 1222 of file cdr.c.

References ast_cdr::answer, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NULL, ast_cdr_start(), ast_clear_flag, ast_copy_flags, AST_FLAGS_ALL, ast_set_flag, ast_test_flag, ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, and ast_cdr::start.

Referenced by ast_bridge_call().

01223 {
01224    struct ast_flags flags = { 0 };
01225 
01226    if (_flags)
01227       ast_copy_flags(&flags, _flags, AST_FLAGS_ALL);
01228 
01229    /* Reset to initial state */
01230    if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) { /* But do NOT lose the NoCDR() setting */
01231       ast_clear_flag(cdr, AST_FLAGS_ALL);
01232       ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED);
01233    } else {
01234       ast_clear_flag(cdr, AST_FLAGS_ALL);
01235    }
01236 
01237    memset(&cdr->start, 0, sizeof(cdr->start));
01238    memset(&cdr->end, 0, sizeof(cdr->end));
01239    memset(&cdr->answer, 0, sizeof(cdr->answer));
01240    cdr->billsec = 0;
01241    cdr->duration = 0;
01242    ast_cdr_start(cdr);
01243    cdr->disposition = AST_CDR_NULL;
01244 }

void ast_cdr_start ( struct ast_cdr cdr  ) 

Start a call.

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

Definition at line 727 of file cdr.c.

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

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

00728 {
00729    for (; cdr; cdr = cdr->next) {
00730       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
00731          check_post(cdr);
00732          cdr->start = ast_tvnow();
00733       }
00734    }
00735 }

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

References ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_detached_background, AST_PTHREADT_NULL, batch, batchscheduleronly, cdr_batch_lock, do_batch_backend_process(), ast_cdr_batch::head, LOG_WARNING, and reset_batch().

Referenced by ast_cdr_engine_term(), and submit_scheduled_batch().

01301 {
01302    struct ast_cdr_batch_item *oldbatchitems = NULL;
01303    pthread_t batch_post_thread = AST_PTHREADT_NULL;
01304 
01305    /* if there's no batch, or no CDRs in the batch, then there's nothing to do */
01306    if (!batch || !batch->head)
01307       return;
01308 
01309    /* move the old CDRs aside, and prepare a new CDR batch */
01310    ast_mutex_lock(&cdr_batch_lock);
01311    oldbatchitems = batch->head;
01312    reset_batch();
01313    ast_mutex_unlock(&cdr_batch_lock);
01314 
01315    /* if configured, spawn a new thread to post these CDRs,
01316       also try to save as much as possible if we are shutting down safely */
01317    if (batchscheduleronly || do_shutdown) {
01318       ast_debug(1, "CDR single-threaded batch processing begins now\n");
01319       do_batch_backend_process(oldbatchitems);
01320    } else {
01321       if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) {
01322          ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n");
01323          do_batch_backend_process(oldbatchitems);
01324       } else {
01325          ast_debug(1, "CDR multi-threaded batch processing begins now\n");
01326       }
01327    }
01328 }

void ast_cdr_unregister ( const char *  name  ) 

Unregister a CDR handling engine.

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

Definition at line 162 of file cdr.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_cdr_beitem::list, and ast_cdr_beitem::name.

Referenced by load_config(), odbc_load_module(), reload(), tds_unload_module(), and unload_module().

00163 {
00164    struct ast_cdr_beitem *i = NULL;
00165 
00166    AST_RWLIST_WRLOCK(&be_list);
00167    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) {
00168       if (!strcasecmp(name, i->name)) {
00169          AST_RWLIST_REMOVE_CURRENT(list);
00170          break;
00171       }
00172    }
00173    AST_RWLIST_TRAVERSE_SAFE_END;
00174    AST_RWLIST_UNLOCK(&be_list);
00175 
00176    if (i) {
00177       ast_verb(2, "Unregistered '%s' CDR backend\n", name);
00178       ast_free(i);
00179    }
00180 }

int ast_cdr_update ( struct ast_channel chan  ) 

Update CDR on a channel.

Note:
The channel should be locked before calling.

Definition at line 1113 of file cdr.c.

References ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_channel_accountcode(), ast_channel_linkedid(), ast_channel_peeraccount(), ast_copy_string(), ast_test_flag, ast_channel::cdr, ast_channel::context, ast_cdr::dcontext, ast_cdr::dst, ast_channel::exten, ast_cdr::linkedid, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, ast_cdr::peeraccount, S_OR, and set_one_cid().

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

01114 {
01115    struct ast_cdr *cdr = c->cdr;
01116 
01117    for ( ; cdr ; cdr = cdr->next) {
01118       if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) {
01119          set_one_cid(cdr, c);
01120 
01121          /* Copy account code et-al */
01122          ast_copy_string(cdr->accountcode, ast_channel_accountcode(c), sizeof(cdr->accountcode));
01123          ast_copy_string(cdr->peeraccount, ast_channel_peeraccount(c), sizeof(cdr->peeraccount));
01124          ast_copy_string(cdr->linkedid, ast_channel_linkedid(c), sizeof(cdr->linkedid));
01125 
01126          /* Destination information */ /* XXX privilege macro* ? */
01127          ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst));
01128          ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext));
01129       }
01130    }
01131 
01132    return 0;
01133 }

int check_cdr_enabled ( void   ) 

Return TRUE if CDR subsystem is enabled.

Definition at line 117 of file cdr.c.

References enabled.

Referenced by action_coresettings(), and handle_show_settings().

00118 {
00119    return enabled;
00120 }


Variable Documentation

char ast_default_accountcode[AST_MAX_ACCOUNT_CODE]

Definition at line 56 of file cdr.c.

Referenced by __ast_channel_alloc_ap().

Default AMA flag for billing records (CDR's)

Definition at line 55 of file cdr.c.

Referenced by __ast_channel_alloc_ap(), and ast_bridge_call().


Generated on Fri Feb 10 06:35:07 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6