#include <sys/time.h>
#include "asterisk/data.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
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) } |
CDR Flags - Disposition. More... | |
enum | { AST_CDR_OMIT = 1, AST_CDR_BILLING = 2, AST_CDR_DOCUMENTATION = 3 } |
CDR AMA Flags. More... | |
Functions | |
ast_cdr * | ast_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. | |
ast_cdr * | ast_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. | |
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_*. | |
ast_cdr * | ast_cdr_dup (struct ast_cdr *cdr) |
Duplicate a record. | |
ast_cdr * | ast_cdr_dup_unique (struct ast_cdr *cdr) |
Duplicate a record and increment the sequence number. | |
ast_cdr * | ast_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_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 |
Definition in file cdr.h.
#define AST_MAX_USER_FIELD 256 |
Definition at line 72 of file cdr.h.
Referenced by ast_rtp_instance_set_stats_vars(), handle_request_bye(), sip_acf_channel_read(), sip_hangup(), and tds_log().
anonymous enum |
CDR Flags.
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.
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 };
anonymous enum |
CDR AMA Flags.
Definition at line 66 of file cdr.h.
00066 { 00067 AST_CDR_OMIT = 1, 00068 AST_CDR_BILLING = 2, 00069 AST_CDR_DOCUMENTATION = 3, 00070 };
struct ast_cdr* ast_cdr_alloc | ( | void | ) |
Allocate a CDR record.
a | malloc'd ast_cdr structure | |
NULL | on error (malloc failure) |
Definition at line 498 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().
00499 { 00500 struct ast_cdr *x; 00501 x = ast_calloc(1, sizeof(*x)); 00502 if (!x) 00503 ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n"); 00504 return x; 00505 }
int ast_cdr_amaflags2int | ( | const char * | flag | ) |
Convert a string to a detail record AMA flag.
flag | string form of flag Converts the string form of the flag to the binary form. |
Definition at line 1104 of file cdr.c.
References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
Referenced by ast_cdr_setamaflags(), build_device(), build_peer(), build_user(), config_parse_variables(), and set_config().
01105 { 01106 if (!strcasecmp(flag, "default")) 01107 return 0; 01108 if (!strcasecmp(flag, "omit")) 01109 return AST_CDR_OMIT; 01110 if (!strcasecmp(flag, "billing")) 01111 return AST_CDR_BILLING; 01112 if (!strcasecmp(flag, "documentation")) 01113 return AST_CDR_DOCUMENTATION; 01114 return -1; 01115 }
void ast_cdr_answer | ( | struct ast_cdr * | cdr | ) |
Answer a call.
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 736 of file cdr.c.
References AST_CDR_ANSWERED, AST_CDR_FLAG_ANSLOCKED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_test_flag, ast_tvnow(), ast_tvzero(), check_post(), and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_bridge_call(), and ast_raw_answer().
00737 { 00738 00739 for (; cdr; cdr = cdr->next) { 00740 if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 00741 continue; 00742 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00743 continue; 00744 check_post(cdr); 00745 if (cdr->disposition < AST_CDR_ANSWERED) 00746 cdr->disposition = AST_CDR_ANSWERED; 00747 if (ast_tvzero(cdr->answer)) 00748 cdr->answer = ast_tvnow(); 00749 } 00750 }
Definition at line 1215 of file cdr.c.
References ast_cdr::next.
Referenced by ast_cdr_fork(), ast_cdr_merge(), and attempt_transfer().
01216 { 01217 struct ast_cdr *ret; 01218 01219 if (cdr) { 01220 ret = cdr; 01221 01222 while (cdr->next) 01223 cdr = cdr->next; 01224 cdr->next = newcdr; 01225 } else { 01226 ret = newcdr; 01227 } 01228 01229 return ret; 01230 }
int ast_cdr_appenduserfield | ( | struct ast_channel * | chan, | |
const char * | userfield | |||
) |
Append to CDR user field for channel (stored in CDR).
Definition at line 1068 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().
01069 { 01070 struct ast_cdr *cdr = chan->cdr; 01071 01072 for ( ; cdr ; cdr = cdr->next) { 01073 int len = strlen(cdr->userfield); 01074 01075 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 01076 ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len); 01077 } 01078 01079 return 0; 01080 }
void ast_cdr_busy | ( | struct ast_cdr * | cdr | ) |
Busy a call.
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 752 of file cdr.c.
References AST_CDR_BUSY, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_cdr_disposition(), handle_cause(), pbx_builtin_busy(), and ring_entry().
00753 { 00754 00755 for (; cdr; cdr = cdr->next) { 00756 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00757 check_post(cdr); 00758 cdr->disposition = AST_CDR_BUSY; 00759 } 00760 } 00761 }
Definition at line 382 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_bridge_call(), and ast_cdr_dup().
00383 { 00384 struct ast_var_t *variables, *newvariable = NULL; 00385 struct varshead *headpa, *headpb; 00386 const char *var, *val; 00387 int x = 0; 00388 00389 if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */ 00390 return 0; 00391 00392 headpa = &from_cdr->varshead; 00393 headpb = &to_cdr->varshead; 00394 00395 AST_LIST_TRAVERSE(headpa,variables,entries) { 00396 if (variables && 00397 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00398 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00399 newvariable = ast_var_assign(var, val); 00400 AST_LIST_INSERT_HEAD(headpb, newvariable, entries); 00401 x++; 00402 } 00403 } 00404 00405 return x; 00406 }
[in] | tree | Where to insert the cdr. |
[in] | cdr | The cdr structure to insert in 'tree'. |
[in] | recur | Go throw all the cdr levels. |
<0 | on error. | |
0 | on success. |
Definition at line 1647 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().
01648 { 01649 struct ast_cdr *tmpcdr; 01650 struct ast_data *level; 01651 struct ast_var_t *variables; 01652 const char *var, *val; 01653 int x = 1, i; 01654 char workspace[256]; 01655 char *tmp; 01656 01657 if (!cdr) { 01658 return -1; 01659 } 01660 01661 for (tmpcdr = cdr; tmpcdr; tmpcdr = (recur ? tmpcdr->next : NULL)) { 01662 level = ast_data_add_node(tree, "level"); 01663 if (!level) { 01664 continue; 01665 } 01666 01667 ast_data_add_int(level, "level_number", x); 01668 01669 AST_LIST_TRAVERSE(&tmpcdr->varshead, variables, entries) { 01670 if (variables && (var = ast_var_name(variables)) && 01671 (val = ast_var_value(variables)) && !ast_strlen_zero(var) 01672 && !ast_strlen_zero(val)) { 01673 ast_data_add_str(level, var, val); 01674 } else { 01675 break; 01676 } 01677 } 01678 01679 for (i = 0; cdr_readonly_vars[i]; i++) { 01680 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 */ 01681 ast_cdr_getvar(tmpcdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0); 01682 if (!tmp) { 01683 continue; 01684 } 01685 ast_data_add_str(level, cdr_readonly_vars[i], tmp); 01686 } 01687 01688 x++; 01689 } 01690 01691 return 0; 01692 }
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.
cdr | Which CDR to detach from the channel thread Prevents the channel thread from blocking on the CDR handling Returns nothing |
Definition at line 1320 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().
01321 { 01322 struct ast_cdr_batch_item *newtail; 01323 int curr; 01324 01325 if (!cdr) 01326 return; 01327 01328 /* maybe they disabled CDR stuff completely, so just drop it */ 01329 if (!enabled) { 01330 ast_debug(1, "Dropping CDR !\n"); 01331 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01332 ast_cdr_free(cdr); 01333 return; 01334 } 01335 01336 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */ 01337 if (!batchmode) { 01338 post_cdr(cdr); 01339 ast_cdr_free(cdr); 01340 return; 01341 } 01342 01343 /* otherwise, each CDR gets put into a batch list (at the end) */ 01344 ast_debug(1, "CDR detaching from this thread\n"); 01345 01346 /* we'll need a new tail for every CDR */ 01347 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) { 01348 post_cdr(cdr); 01349 ast_cdr_free(cdr); 01350 return; 01351 } 01352 01353 /* don't traverse a whole list (just keep track of the tail) */ 01354 ast_mutex_lock(&cdr_batch_lock); 01355 if (!batch) 01356 init_batch(); 01357 if (!batch->head) { 01358 /* new batch is empty, so point the head at the new tail */ 01359 batch->head = newtail; 01360 } else { 01361 /* already got a batch with something in it, so just append a new tail */ 01362 batch->tail->next = newtail; 01363 } 01364 newtail->cdr = cdr; 01365 batch->tail = newtail; 01366 curr = batch->size++; 01367 ast_mutex_unlock(&cdr_batch_lock); 01368 01369 /* if we have enough stuff to post, then do it */ 01370 if (curr >= (batchsize - 1)) 01371 submit_unscheduled_batch(); 01372 }
void ast_cdr_discard | ( | struct ast_cdr * | cdr | ) |
Discard and free a CDR record.
cdr | ast_cdr structure to free Returns nothing -- same as free, but no checks or complaints |
Definition at line 487 of file cdr.c.
References ast_cdr_free_vars(), ast_free, ast_cdr_beitem::next, and ast_cdr::next.
Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_merge(), ast_channel_destructor(), and ast_dummy_channel_destructor().
00488 { 00489 while (cdr) { 00490 struct ast_cdr *next = cdr->next; 00491 00492 ast_cdr_free_vars(cdr, 0); 00493 ast_free(cdr); 00494 cdr = next; 00495 } 00496 }
char* ast_cdr_disp2str | ( | int | disposition | ) |
Disposition to a string.
disposition | input binary form Converts the binary form of a disposition to string form. |
Definition at line 958 of file cdr.c.
References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, AST_CDR_NOANSWER, and AST_CDR_NULL.
Referenced by ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), execute_cb(), manager_log(), and tds_log().
00959 { 00960 switch (disposition) { 00961 case AST_CDR_NULL: 00962 return "NO ANSWER"; /* by default, for backward compatibility */ 00963 case AST_CDR_NOANSWER: 00964 return "NO ANSWER"; 00965 case AST_CDR_FAILED: 00966 return "FAILED"; 00967 case AST_CDR_BUSY: 00968 return "BUSY"; 00969 case AST_CDR_ANSWERED: 00970 return "ANSWERED"; 00971 } 00972 return "UNKNOWN"; 00973 }
int ast_cdr_disposition | ( | struct ast_cdr * | cdr, | |
int | cause | |||
) |
Save the result of the call based on the AST_CAUSE_*.
cdr | the cdr you wish to associate with the call | |
cause | the AST_CAUSE_* Returns nothing |
Definition at line 789 of file cdr.c.
References AST_CAUSE_BUSY, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL, ast_cdr_busy(), ast_cdr_noanswer(), and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), clear_caller(), and findmeexec().
00790 { 00791 int res = 0; 00792 00793 for (; cdr; cdr = cdr->next) { 00794 switch (cause) { /* handle all the non failure, busy cases, return 0 not to set disposition, 00795 return -1 to set disposition to FAILED */ 00796 case AST_CAUSE_BUSY: 00797 ast_cdr_busy(cdr); 00798 break; 00799 case AST_CAUSE_NO_ANSWER: 00800 ast_cdr_noanswer(cdr); 00801 break; 00802 case AST_CAUSE_NORMAL: 00803 break; 00804 default: 00805 res = -1; 00806 } 00807 } 00808 return res; 00809 }
Duplicate a record.
Duplicate a CDR record
Definition at line 211 of file cdr.c.
References ast_cdr_alloc(), and ast_cdr_copy_vars().
Referenced by ast_async_goto(), ast_cdr_dup_unique(), ast_cdr_dup_unique_swap(), ast_cdr_merge(), custom_log(), manager_log(), syslog_log(), and write_cdr().
00212 { 00213 struct ast_cdr *newcdr; 00214 00215 if (!cdr) /* don't die if we get a null cdr pointer */ 00216 return NULL; 00217 newcdr = ast_cdr_alloc(); 00218 if (!newcdr) 00219 return NULL; 00220 00221 memcpy(newcdr, cdr, sizeof(*newcdr)); 00222 /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */ 00223 memset(&newcdr->varshead, 0, sizeof(newcdr->varshead)); 00224 ast_cdr_copy_vars(newcdr, cdr); 00225 newcdr->next = NULL; 00226 00227 return newcdr; 00228 }
Duplicate a record and increment the sequence number.
cdr | the record to duplicate |
a | malloc'd ast_cdr structure, | |
NULL | on error (malloc failure) |
Definition at line 188 of file cdr.c.
References ast_cdr_dup(), and cdr_seq_inc().
Referenced by ast_cdr_fork().
00189 { 00190 struct ast_cdr *newcdr = ast_cdr_dup(cdr); 00191 if (!newcdr) 00192 return NULL; 00193 00194 cdr_seq_inc(newcdr); 00195 return newcdr; 00196 }
Duplicate a record and increment the sequence number of the old record.
cdr | the record to duplicate |
a | malloc'd ast_cdr structure, | |
NULL | on error (malloc failure) |
Definition at line 198 of file cdr.c.
References ast_cdr_dup(), and cdr_seq_inc().
Referenced by ast_bridge_call(), and ast_cdr_reset().
00199 { 00200 struct ast_cdr *newcdr = ast_cdr_dup(cdr); 00201 if (!newcdr) 00202 return NULL; 00203 00204 cdr_seq_inc(cdr); 00205 return newcdr; 00206 }
void ast_cdr_end | ( | struct ast_cdr * | cdr | ) |
End a call.
cdr | the cdr you have associated the call with Registers the end of call time in the cdr structure. Returns nothing |
Definition at line 932 of file cdr.c.
References 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(), check_post(), LOG_WARNING, ast_cdr::next, and S_OR.
Referenced by __ast_request_and_dial(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_reset(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), clear_caller(), and findmeexec().
00933 { 00934 for ( ; cdr ; cdr = cdr->next) { 00935 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00936 continue; 00937 check_post(cdr); 00938 if (ast_tvzero(cdr->end)) 00939 cdr->end = ast_tvnow(); 00940 if (ast_tvzero(cdr->start)) { 00941 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>")); 00942 cdr->disposition = AST_CDR_FAILED; 00943 } else 00944 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec; 00945 if (ast_tvzero(cdr->answer)) { 00946 if (cdr->disposition == AST_CDR_ANSWERED) { 00947 ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>")); 00948 cdr->disposition = AST_CDR_FAILED; 00949 } 00950 } else { 00951 cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec; 00952 if (ast_test_flag(&ast_options, AST_OPT_FLAG_INITIATED_SECONDS)) 00953 cdr->billsec += cdr->end.tv_usec > cdr->answer.tv_usec ? 1 : 0; 00954 } 00955 } 00956 }
int ast_cdr_engine_init | ( | void | ) |
Load the configuration file cdr.conf and possibly start the CDR scheduling thread.
Definition at line 1613 of file cdr.c.
References ast_cli_register(), ast_log(), ast_mutex_lock, ast_mutex_unlock, cdr_batch_lock, cli_status, do_reload(), init_batch(), LOG_ERROR, and sched_context_create().
Referenced by main().
01614 { 01615 int res; 01616 01617 sched = sched_context_create(); 01618 if (!sched) { 01619 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 01620 return -1; 01621 } 01622 01623 ast_cli_register(&cli_status); 01624 01625 res = do_reload(0); 01626 if (res) { 01627 ast_mutex_lock(&cdr_batch_lock); 01628 res = init_batch(); 01629 ast_mutex_unlock(&cdr_batch_lock); 01630 } 01631 01632 return res; 01633 }
int ast_cdr_engine_reload | ( | void | ) |
Reload the configuration file cdr.conf and start/stop CDR scheduling thread.
Definition at line 1642 of file cdr.c.
References do_reload().
01643 { 01644 return do_reload(1); 01645 }
void ast_cdr_engine_term | ( | void | ) |
Submit any remaining CDRs and prepare for shutdown
Definition at line 1637 of file cdr.c.
References ast_cdr_submit_batch(), and batchsafeshutdown.
Referenced by can_safely_quit(), and do_reload().
01638 { 01639 ast_cdr_submit_batch(batchsafeshutdown); 01640 }
void ast_cdr_failed | ( | struct ast_cdr * | cdr | ) |
Fail a call.
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 763 of file cdr.c.
References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), clear_caller(), findmeexec(), handle_cause(), and wait_for_answer().
00764 { 00765 for (; cdr; cdr = cdr->next) { 00766 check_post(cdr); 00767 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00768 check_post(cdr); 00769 if (cdr->disposition < AST_CDR_FAILED) 00770 cdr->disposition = AST_CDR_FAILED; 00771 } 00772 } 00773 }
char* ast_cdr_flags2str | ( | int | flag | ) |
Converts AMA flag to printable string
Definition at line 976 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().
00977 { 00978 switch (flag) { 00979 case AST_CDR_OMIT: 00980 return "OMIT"; 00981 case AST_CDR_BILLING: 00982 return "BILLING"; 00983 case AST_CDR_DOCUMENTATION: 00984 return "DOCUMENTATION"; 00985 } 00986 return "Unknown"; 00987 }
void ast_cdr_free | ( | struct ast_cdr * | cdr | ) |
Free a CDR record.
cdr | ast_cdr structure to free Returns nothing |
Definition at line 474 of file cdr.c.
References ast_cdr_free_vars(), ast_free, ast_cdr_beitem::next, and ast_cdr::next.
Referenced by ast_cdr_detach(), and do_batch_backend_process().
00475 { 00476 00477 while (cdr) { 00478 struct ast_cdr *next = cdr->next; 00479 00480 ast_cdr_free_vars(cdr, 0); 00481 ast_free(cdr); 00482 cdr = next; 00483 } 00484 }
void ast_cdr_free_vars | ( | struct ast_cdr * | cdr, | |
int | recur | |||
) |
Definition at line 453 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().
00454 { 00455 00456 /* clear variables */ 00457 for (; cdr; cdr = recur ? cdr->next : NULL) { 00458 struct ast_var_t *vardata; 00459 struct varshead *headp = &cdr->varshead; 00460 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 00461 ast_var_delete(vardata); 00462 } 00463 }
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 262 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().
00263 { 00264 const char *fmt = "%Y-%m-%d %T"; 00265 const char *varbuf; 00266 00267 if (!cdr) /* don't die if the cdr is null */ 00268 return; 00269 00270 *ret = NULL; 00271 /* special vars (the ones from the struct ast_cdr when requested by name) 00272 I'd almost say we should convert all the stringed vals to vars */ 00273 00274 if (!strcasecmp(name, "clid")) 00275 ast_copy_string(workspace, cdr->clid, workspacelen); 00276 else if (!strcasecmp(name, "src")) 00277 ast_copy_string(workspace, cdr->src, workspacelen); 00278 else if (!strcasecmp(name, "dst")) 00279 ast_copy_string(workspace, cdr->dst, workspacelen); 00280 else if (!strcasecmp(name, "dcontext")) 00281 ast_copy_string(workspace, cdr->dcontext, workspacelen); 00282 else if (!strcasecmp(name, "channel")) 00283 ast_copy_string(workspace, cdr->channel, workspacelen); 00284 else if (!strcasecmp(name, "dstchannel")) 00285 ast_copy_string(workspace, cdr->dstchannel, workspacelen); 00286 else if (!strcasecmp(name, "lastapp")) 00287 ast_copy_string(workspace, cdr->lastapp, workspacelen); 00288 else if (!strcasecmp(name, "lastdata")) 00289 ast_copy_string(workspace, cdr->lastdata, workspacelen); 00290 else if (!strcasecmp(name, "start")) 00291 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen); 00292 else if (!strcasecmp(name, "answer")) 00293 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen); 00294 else if (!strcasecmp(name, "end")) 00295 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen); 00296 else if (!strcasecmp(name, "duration")) { 00297 snprintf(workspace, workspacelen, "%ld", cdr->end.tv_sec != 0 ? cdr->duration : (long)ast_tvdiff_ms(ast_tvnow(), cdr->start) / 1000); 00298 } else if (!strcasecmp(name, "billsec")) 00299 snprintf(workspace, workspacelen, "%ld", cdr->billsec || cdr->answer.tv_sec == 0 ? cdr->billsec : (long)ast_tvdiff_ms(ast_tvnow(), cdr->answer) / 1000); 00300 else if (!strcasecmp(name, "disposition")) { 00301 if (raw) { 00302 snprintf(workspace, workspacelen, "%ld", cdr->disposition); 00303 } else { 00304 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); 00305 } 00306 } else if (!strcasecmp(name, "amaflags")) { 00307 if (raw) { 00308 snprintf(workspace, workspacelen, "%ld", cdr->amaflags); 00309 } else { 00310 ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); 00311 } 00312 } else if (!strcasecmp(name, "accountcode")) 00313 ast_copy_string(workspace, cdr->accountcode, workspacelen); 00314 else if (!strcasecmp(name, "peeraccount")) 00315 ast_copy_string(workspace, cdr->peeraccount, workspacelen); 00316 else if (!strcasecmp(name, "uniqueid")) 00317 ast_copy_string(workspace, cdr->uniqueid, workspacelen); 00318 else if (!strcasecmp(name, "linkedid")) 00319 ast_copy_string(workspace, cdr->linkedid, workspacelen); 00320 else if (!strcasecmp(name, "userfield")) 00321 ast_copy_string(workspace, cdr->userfield, workspacelen); 00322 else if (!strcasecmp(name, "sequence")) 00323 snprintf(workspace, workspacelen, "%d", cdr->sequence); 00324 else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) 00325 ast_copy_string(workspace, varbuf, workspacelen); 00326 else 00327 workspace[0] = '\0'; 00328 00329 if (!ast_strlen_zero(workspace)) 00330 *ret = workspace; 00331 }
int ast_cdr_init | ( | struct ast_cdr * | cdr, | |
struct ast_channel * | chan | |||
) |
Initialize based on a channel.
cdr | Call Detail Record to use for channel | |
chan | Channel to bind CDR with Initializes a CDR and associates it with a particular channel |
Definition at line 896 of file cdr.c.
References ast_channel::_state, ast_channel::accountcode, ast_channel::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_copy_string(), AST_STATE_UP, ast_test_flag, cdr_seq_inc(), ast_cdr::channel, ast_channel::context, ast_channel::exten, ast_channel::linkedid, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::name, ast_cdr::next, ast_channel::peeraccount, S_OR, set_one_cid(), and ast_channel::uniqueid.
Referenced by __ast_channel_alloc_ap(), __ast_request_and_dial(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().
00897 { 00898 for ( ; cdr ; cdr = cdr->next) { 00899 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00900 ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); 00901 set_one_cid(cdr, c); 00902 cdr_seq_inc(cdr); 00903 00904 cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 00905 cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; 00906 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00907 ast_copy_string(cdr->peeraccount, c->peeraccount, sizeof(cdr->peeraccount)); 00908 /* Destination information */ 00909 ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst)); 00910 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext)); 00911 /* Unique call identifier */ 00912 ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid)); 00913 /* Linked call identifier */ 00914 ast_copy_string(cdr->linkedid, c->linkedid, sizeof(cdr->linkedid)); 00915 } 00916 } 00917 return 0; 00918 }
int ast_cdr_isset_unanswered | ( | void | ) |
Definition at line 183 of file cdr.c.
References unanswered.
Referenced by ring_entry().
00184 { 00185 return unanswered; 00186 }
Move the non-null data from the "from" cdr to the "to" cdr.
to | the cdr to get the goodies | |
from | the cdr to give the goodies |
Definition at line 542 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.
00543 { 00544 struct ast_cdr *zcdr; 00545 struct ast_cdr *lto = NULL; 00546 struct ast_cdr *lfrom = NULL; 00547 int discard_from = 0; 00548 00549 if (!to || !from) 00550 return; 00551 00552 /* don't merge into locked CDR's -- it's bad business */ 00553 if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { 00554 zcdr = to; /* safety valve? */ 00555 while (to->next) { 00556 lto = to; 00557 to = to->next; 00558 } 00559 00560 if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { 00561 ast_log(LOG_WARNING, "Merging into locked CDR... no choice.\n"); 00562 to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */ 00563 lto = NULL; 00564 } 00565 } 00566 00567 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) { 00568 struct ast_cdr *llfrom = NULL; 00569 discard_from = 1; 00570 if (lto) { 00571 /* insert the from stuff after lto */ 00572 lto->next = from; 00573 lfrom = from; 00574 while (lfrom && lfrom->next) { 00575 if (!lfrom->next->next) 00576 llfrom = lfrom; 00577 lfrom = lfrom->next; 00578 } 00579 /* rip off the last entry and put a copy of the to at the end */ 00580 if (llfrom) { 00581 llfrom->next = to; 00582 } 00583 from = lfrom; 00584 } else { 00585 /* save copy of the current *to cdr */ 00586 struct ast_cdr tcdr; 00587 memcpy(&tcdr, to, sizeof(tcdr)); 00588 /* copy in the locked from cdr */ 00589 memcpy(to, from, sizeof(*to)); 00590 lfrom = from; 00591 while (lfrom && lfrom->next) { 00592 if (!lfrom->next->next) 00593 llfrom = lfrom; 00594 lfrom = lfrom->next; 00595 } 00596 from->next = NULL; 00597 /* rip off the last entry and put a copy of the to at the end */ 00598 if (llfrom == from) { 00599 to = to->next = ast_cdr_dup(&tcdr); 00600 } else if (llfrom) { 00601 to = llfrom->next = ast_cdr_dup(&tcdr); 00602 } 00603 from = lfrom; 00604 } 00605 } 00606 00607 if (!ast_tvzero(from->start)) { 00608 if (!ast_tvzero(to->start)) { 00609 if (ast_tvcmp(to->start, from->start) > 0 ) { 00610 to->start = from->start; /* use the earliest time */ 00611 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00612 } 00613 /* else nothing to do */ 00614 } else { 00615 to->start = from->start; 00616 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00617 } 00618 } 00619 if (!ast_tvzero(from->answer)) { 00620 if (!ast_tvzero(to->answer)) { 00621 if (ast_tvcmp(to->answer, from->answer) > 0 ) { 00622 to->answer = from->answer; /* use the earliest time */ 00623 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00624 } 00625 /* we got the earliest answer time, so we'll settle for that? */ 00626 } else { 00627 to->answer = from->answer; 00628 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00629 } 00630 } 00631 if (!ast_tvzero(from->end)) { 00632 if (!ast_tvzero(to->end)) { 00633 if (ast_tvcmp(to->end, from->end) < 0 ) { 00634 to->end = from->end; /* use the latest time */ 00635 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00636 to->duration = to->end.tv_sec - to->start.tv_sec; /* don't forget to update the duration, billsec, when we set end */ 00637 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00638 } 00639 /* else, nothing to do */ 00640 } else { 00641 to->end = from->end; 00642 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00643 to->duration = to->end.tv_sec - to->start.tv_sec; 00644 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00645 } 00646 } 00647 if (to->disposition < from->disposition) { 00648 to->disposition = from->disposition; 00649 from->disposition = AST_CDR_NOANSWER; 00650 } 00651 if (ast_strlen_zero(to->lastapp) && !ast_strlen_zero(from->lastapp)) { 00652 ast_copy_string(to->lastapp, from->lastapp, sizeof(to->lastapp)); 00653 from->lastapp[0] = 0; /* theft */ 00654 } 00655 if (ast_strlen_zero(to->lastdata) && !ast_strlen_zero(from->lastdata)) { 00656 ast_copy_string(to->lastdata, from->lastdata, sizeof(to->lastdata)); 00657 from->lastdata[0] = 0; /* theft */ 00658 } 00659 if (ast_strlen_zero(to->dcontext) && !ast_strlen_zero(from->dcontext)) { 00660 ast_copy_string(to->dcontext, from->dcontext, sizeof(to->dcontext)); 00661 from->dcontext[0] = 0; /* theft */ 00662 } 00663 if (ast_strlen_zero(to->dstchannel) && !ast_strlen_zero(from->dstchannel)) { 00664 ast_copy_string(to->dstchannel, from->dstchannel, sizeof(to->dstchannel)); 00665 from->dstchannel[0] = 0; /* theft */ 00666 } 00667 if (!ast_strlen_zero(from->channel) && (ast_strlen_zero(to->channel) || !strncasecmp(from->channel, "Agent/", 6))) { 00668 ast_copy_string(to->channel, from->channel, sizeof(to->channel)); 00669 from->channel[0] = 0; /* theft */ 00670 } 00671 if (ast_strlen_zero(to->src) && !ast_strlen_zero(from->src)) { 00672 ast_copy_string(to->src, from->src, sizeof(to->src)); 00673 from->src[0] = 0; /* theft */ 00674 } 00675 if (ast_strlen_zero(to->clid) && !ast_strlen_zero(from->clid)) { 00676 ast_copy_string(to->clid, from->clid, sizeof(to->clid)); 00677 from->clid[0] = 0; /* theft */ 00678 } 00679 if (ast_strlen_zero(to->dst) && !ast_strlen_zero(from->dst)) { 00680 ast_copy_string(to->dst, from->dst, sizeof(to->dst)); 00681 from->dst[0] = 0; /* theft */ 00682 } 00683 if (!to->amaflags) 00684 to->amaflags = AST_CDR_DOCUMENTATION; 00685 if (!from->amaflags) 00686 from->amaflags = AST_CDR_DOCUMENTATION; /* make sure both amaflags are set to something (DOC is default) */ 00687 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) { 00688 to->amaflags = from->amaflags; 00689 } 00690 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) { 00691 ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode)); 00692 } 00693 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->peeraccount) && !ast_strlen_zero(from->peeraccount))) { 00694 ast_copy_string(to->peeraccount, from->peeraccount, sizeof(to->peeraccount)); 00695 } 00696 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) { 00697 ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield)); 00698 } 00699 /* flags, varsead, ? */ 00700 cdr_merge_vars(from, to); 00701 00702 if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS)) 00703 ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS); 00704 if (ast_test_flag(from, AST_CDR_FLAG_POSTED)) 00705 ast_set_flag(to, AST_CDR_FLAG_POSTED); 00706 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) 00707 ast_set_flag(to, AST_CDR_FLAG_LOCKED); 00708 if (ast_test_flag(from, AST_CDR_FLAG_CHILD)) 00709 ast_set_flag(to, AST_CDR_FLAG_CHILD); 00710 if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED)) 00711 ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED); 00712 00713 /* last, but not least, we need to merge any forked CDRs to the 'to' cdr */ 00714 while (from->next) { 00715 /* just rip 'em off the 'from' and insert them on the 'to' */ 00716 zcdr = from->next; 00717 from->next = zcdr->next; 00718 zcdr->next = NULL; 00719 /* zcdr is now ripped from the current list; */ 00720 ast_cdr_append(to, zcdr); 00721 } 00722 if (discard_from) 00723 ast_cdr_discard(from); 00724 }
void ast_cdr_noanswer | ( | struct ast_cdr * | cdr | ) |
A call wasn't answered.
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 775 of file cdr.c.
References AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_test_flag, check_post(), and ast_cdr::next.
Referenced by ast_cdr_disposition(), and handle_cause().
00776 { 00777 while (cdr) { 00778 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00779 check_post(cdr); 00780 cdr->disposition = AST_CDR_NOANSWER; 00781 } 00782 cdr = cdr->next; 00783 } 00784 }
int ast_cdr_register | ( | const char * | name, | |
const char * | desc, | |||
ast_cdrbe | be | |||
) |
Register a CDR handling engine.
0 | on success. | |
-1 | on error |
Definition at line 128 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::list, LOG_WARNING, and ast_cdr_beitem::name.
Referenced by load_config(), load_module(), odbc_load_module(), and unload_module().
00129 { 00130 struct ast_cdr_beitem *i = NULL; 00131 00132 if (!name) 00133 return -1; 00134 00135 if (!be) { 00136 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name); 00137 return -1; 00138 } 00139 00140 AST_RWLIST_WRLOCK(&be_list); 00141 AST_RWLIST_TRAVERSE(&be_list, i, list) { 00142 if (!strcasecmp(name, i->name)) { 00143 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name); 00144 AST_RWLIST_UNLOCK(&be_list); 00145 return -1; 00146 } 00147 } 00148 00149 if (!(i = ast_calloc(1, sizeof(*i)))) 00150 return -1; 00151 00152 i->be = be; 00153 ast_copy_string(i->name, name, sizeof(i->name)); 00154 ast_copy_string(i->desc, desc, sizeof(i->desc)); 00155 00156 AST_RWLIST_INSERT_HEAD(&be_list, i, list); 00157 AST_RWLIST_UNLOCK(&be_list); 00158 00159 return 0; 00160 }
Reset the detail record, optionally posting it first.
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 1148 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_flags::flags, ast_cdr::next, and ast_cdr::start.
Referenced by ast_cdr_fork(), dial_exec_full(), and pbx_builtin_resetcdr().
01149 { 01150 struct ast_cdr *duplicate; 01151 struct ast_flags flags = { 0 }; 01152 01153 if (_flags) 01154 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); 01155 01156 for ( ; cdr ; cdr = cdr->next) { 01157 /* Detach if post is requested */ 01158 if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01159 if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) { 01160 ast_cdr_end(cdr); 01161 if ((duplicate = ast_cdr_dup_unique_swap(cdr))) { 01162 ast_cdr_detach(duplicate); 01163 } 01164 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 01165 } 01166 01167 /* enable CDR only */ 01168 if (ast_test_flag(&flags, AST_CDR_FLAG_POST_ENABLE)) { 01169 ast_clear_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01170 continue; 01171 } 01172 01173 /* clear variables */ 01174 if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) { 01175 ast_cdr_free_vars(cdr, 0); 01176 } 01177 01178 /* Reset to initial state */ 01179 ast_clear_flag(cdr, AST_FLAGS_ALL); 01180 memset(&cdr->start, 0, sizeof(cdr->start)); 01181 memset(&cdr->end, 0, sizeof(cdr->end)); 01182 memset(&cdr->answer, 0, sizeof(cdr->answer)); 01183 cdr->billsec = 0; 01184 cdr->duration = 0; 01185 ast_cdr_start(cdr); 01186 cdr->disposition = AST_CDR_NOANSWER; 01187 } 01188 } 01189 }
int ast_cdr_serialize_variables | ( | struct ast_cdr * | cdr, | |
struct ast_str ** | buf, | |||
char | delim, | |||
char | sep, | |||
int | recur | |||
) |
Definition at line 408 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().
00409 { 00410 struct ast_var_t *variables; 00411 const char *var; 00412 char *tmp; 00413 char workspace[256]; 00414 int total = 0, x = 0, i; 00415 00416 ast_str_reset(*buf); 00417 00418 for (; cdr; cdr = recur ? cdr->next : NULL) { 00419 if (++x > 1) 00420 ast_str_append(buf, 0, "\n"); 00421 00422 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) { 00423 if (!(var = ast_var_name(variables))) { 00424 continue; 00425 } 00426 00427 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, var, delim, S_OR(ast_var_value(variables), ""), sep) < 0) { 00428 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00429 break; 00430 } 00431 00432 total++; 00433 } 00434 00435 for (i = 0; cdr_readonly_vars[i]; i++) { 00436 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 */ 00437 ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0); 00438 if (!tmp) 00439 continue; 00440 00441 if (ast_str_append(buf, 0, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep) < 0) { 00442 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00443 break; 00444 } else 00445 total++; 00446 } 00447 } 00448 00449 return total; 00450 }
int ast_cdr_setaccount | ( | struct ast_channel * | chan, | |
const char * | account | |||
) |
Set account code, will generate AMI event.
Definition at line 989 of file cdr.c.
References ast_channel::accountcode, accountcode, ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_manager_event, ast_strdupa, ast_string_field_set, 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(), and cdr_write().
00990 { 00991 struct ast_cdr *cdr = chan->cdr; 00992 const char *old_acct = ""; 00993 00994 if (!ast_strlen_zero(chan->accountcode)) { 00995 old_acct = ast_strdupa(chan->accountcode); 00996 } 00997 00998 ast_string_field_set(chan, accountcode, account); 00999 for ( ; cdr ; cdr = cdr->next) { 01000 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01001 ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode)); 01002 } 01003 } 01004 01005 ast_manager_event(chan, EVENT_FLAG_CALL, "NewAccountCode", 01006 "Channel: %s\r\n" 01007 "Uniqueid: %s\r\n" 01008 "AccountCode: %s\r\n" 01009 "OldAccountCode: %s\r\n", 01010 chan->name, chan->uniqueid, chan->accountcode, old_acct); 01011 01012 return 0; 01013 }
int ast_cdr_setamaflags | ( | struct ast_channel * | chan, | |
const char * | amaflags | |||
) |
Set AMA flags for channel.
Definition at line 1041 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().
01042 { 01043 struct ast_cdr *cdr; 01044 int newflag = ast_cdr_amaflags2int(flag); 01045 if (newflag) { 01046 for (cdr = chan->cdr; cdr; cdr = cdr->next) { 01047 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01048 cdr->amaflags = newflag; 01049 } 01050 } 01051 } 01052 01053 return 0; 01054 }
void ast_cdr_setanswer | ( | struct ast_cdr * | cdr, | |
struct timeval | t | |||
) |
Set the answer time for a call.
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 833 of file cdr.c.
References 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().
00834 { 00835 00836 for (; cdr; cdr = cdr->next) { 00837 if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 00838 continue; 00839 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00840 continue; 00841 check_post(cdr); 00842 cdr->answer = t; 00843 } 00844 }
void ast_cdr_setapp | ( | struct ast_cdr * | cdr, | |
const char * | app, | |||
const char * | data | |||
) |
Set the last executed application.
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 821 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, check_post(), ast_cdr::next, and S_OR.
Referenced by __ast_request_and_dial(), agi_handle_command(), clear_caller(), findmeexec(), and pbx_exec().
00822 { 00823 00824 for (; cdr; cdr = cdr->next) { 00825 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00826 check_post(cdr); 00827 ast_copy_string(cdr->lastapp, S_OR(app, ""), sizeof(cdr->lastapp)); 00828 ast_copy_string(cdr->lastdata, S_OR(data, ""), sizeof(cdr->lastdata)); 00829 } 00830 } 00831 }
int ast_cdr_setcid | ( | struct ast_cdr * | cdr, | |
struct ast_channel * | chan | |||
) |
Initialize based on a channel.
cdr | Call Detail Record to use for channel | |
chan | Channel to bind CDR with Initializes a CDR and associates it with a particular channel |
Definition at line 882 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().
00883 { 00884 for (; cdr; cdr = cdr->next) { 00885 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00886 set_one_cid(cdr, c); 00887 } 00888 return 0; 00889 }
void ast_cdr_setdestchan | ( | struct ast_cdr * | cdr, | |
const char * | chan | |||
) |
Set the destination channel, if there was one.
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 811 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, check_post(), and ast_cdr::next.
Referenced by dial_exec_full(), parked_call_exec(), and ring_entry().
00812 { 00813 for (; cdr; cdr = cdr->next) { 00814 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00815 check_post(cdr); 00816 ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel)); 00817 } 00818 } 00819 }
void ast_cdr_setdisposition | ( | struct ast_cdr * | cdr, | |
long int | disposition | |||
) |
Set the disposition for a call.
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 846 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), and ast_cdr::next.
Referenced by ast_bridge_call().
00847 { 00848 00849 for (; cdr; cdr = cdr->next) { 00850 if (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00851 continue; 00852 check_post(cdr); 00853 cdr->disposition = disposition; 00854 } 00855 }
int ast_cdr_setpeeraccount | ( | struct ast_channel * | chan, | |
const char * | account | |||
) |
Set the peer account.
Definition at line 1015 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_manager_event, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_channel::cdr, EVENT_FLAG_CALL, ast_cdr::next, ast_channel::peeraccount, and ast_cdr::peeraccount.
Referenced by cdr_write().
01016 { 01017 struct ast_cdr *cdr = chan->cdr; 01018 const char *old_acct = ""; 01019 01020 if (!ast_strlen_zero(chan->peeraccount)) { 01021 old_acct = ast_strdupa(chan->peeraccount); 01022 } 01023 01024 ast_string_field_set(chan, peeraccount, account); 01025 for ( ; cdr ; cdr = cdr->next) { 01026 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01027 ast_copy_string(cdr->peeraccount, chan->peeraccount, sizeof(cdr->peeraccount)); 01028 } 01029 } 01030 01031 ast_manager_event(chan, EVENT_FLAG_CALL, "NewPeerAccount", 01032 "Channel: %s\r\n" 01033 "Uniqueid: %s\r\n" 01034 "PeerAccount: %s\r\n" 01035 "OldPeerAccount: %s\r\n", 01036 chan->name, chan->uniqueid, chan->peeraccount, old_acct); 01037 01038 return 0; 01039 }
int ast_cdr_setuserfield | ( | struct ast_channel * | chan, | |
const char * | userfield | |||
) |
Set CDR user field for channel (stored in CDR).
Definition at line 1056 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().
01057 { 01058 struct ast_cdr *cdr = chan->cdr; 01059 01060 for ( ; cdr ; cdr = cdr->next) { 01061 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 01062 ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield)); 01063 } 01064 01065 return 0; 01066 }
int ast_cdr_setvar | ( | struct ast_cdr * | cdr, | |
const char * | name, | |||
const char * | value, | |||
int | recur | |||
) |
Set a CDR channel variable
Definition at line 341 of file cdr.c.
References AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_test_flag, ast_var_assign(), ast_var_delete(), ast_var_name(), cdr_readonly_vars, LOG_ERROR, and ast_cdr::next.
Referenced by ast_cdr_fork(), cdr_write(), and set_one_cid().
00342 { 00343 struct ast_var_t *newvariable; 00344 struct varshead *headp; 00345 int x; 00346 00347 for (x = 0; cdr_readonly_vars[x]; x++) { 00348 if (!strcasecmp(name, cdr_readonly_vars[x])) { 00349 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name); 00350 return -1; 00351 } 00352 } 00353 00354 if (!cdr) { 00355 ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n"); 00356 return -1; 00357 } 00358 00359 for (; cdr; cdr = recur ? cdr->next : NULL) { 00360 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00361 continue; 00362 headp = &cdr->varshead; 00363 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 00364 if (!strcasecmp(ast_var_name(newvariable), name)) { 00365 /* there is already such a variable, delete it */ 00366 AST_LIST_REMOVE_CURRENT(entries); 00367 ast_var_delete(newvariable); 00368 break; 00369 } 00370 } 00371 AST_LIST_TRAVERSE_SAFE_END; 00372 00373 if (value) { 00374 newvariable = ast_var_assign(name, value); 00375 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 00376 } 00377 } 00378 00379 return 0; 00380 }
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 1191 of file cdr.c.
References ast_cdr::answer, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NULL, ast_cdr_start(), ast_clear_flag, ast_copy_flags, AST_FLAGS_ALL, ast_set_flag, ast_test_flag, ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, ast_flags::flags, and ast_cdr::start.
Referenced by ast_bridge_call().
01192 { 01193 struct ast_flags flags = { 0 }; 01194 01195 if (_flags) 01196 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); 01197 01198 /* Reset to initial state */ 01199 if (ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) { /* But do NOT lose the NoCDR() setting */ 01200 ast_clear_flag(cdr, AST_FLAGS_ALL); 01201 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01202 } else { 01203 ast_clear_flag(cdr, AST_FLAGS_ALL); 01204 } 01205 01206 memset(&cdr->start, 0, sizeof(cdr->start)); 01207 memset(&cdr->end, 0, sizeof(cdr->end)); 01208 memset(&cdr->answer, 0, sizeof(cdr->answer)); 01209 cdr->billsec = 0; 01210 cdr->duration = 0; 01211 ast_cdr_start(cdr); 01212 cdr->disposition = AST_CDR_NULL; 01213 }
void ast_cdr_start | ( | struct ast_cdr * | cdr | ) |
Start a call.
cdr | the cdr you wish to associate with the call Starts all CDR stuff necessary for monitoring a call Returns nothing |
Definition at line 726 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_tvnow(), check_post(), and ast_cdr::next.
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().
00727 { 00728 for (; cdr; cdr = cdr->next) { 00729 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00730 check_post(cdr); 00731 cdr->start = ast_tvnow(); 00732 } 00733 } 00734 }
void ast_cdr_submit_batch | ( | int | shutdown | ) |
Spawns (possibly) a new thread to submit a batch of CDRs to the backend engines.
shutdown | Whether or not we are shutting down Blocks the asterisk shutdown procedures until the CDR data is submitted. Returns nothing |
Definition at line 1269 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().
01270 { 01271 struct ast_cdr_batch_item *oldbatchitems = NULL; 01272 pthread_t batch_post_thread = AST_PTHREADT_NULL; 01273 01274 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */ 01275 if (!batch || !batch->head) 01276 return; 01277 01278 /* move the old CDRs aside, and prepare a new CDR batch */ 01279 ast_mutex_lock(&cdr_batch_lock); 01280 oldbatchitems = batch->head; 01281 reset_batch(); 01282 ast_mutex_unlock(&cdr_batch_lock); 01283 01284 /* if configured, spawn a new thread to post these CDRs, 01285 also try to save as much as possible if we are shutting down safely */ 01286 if (batchscheduleronly || do_shutdown) { 01287 ast_debug(1, "CDR single-threaded batch processing begins now\n"); 01288 do_batch_backend_process(oldbatchitems); 01289 } else { 01290 if (ast_pthread_create_detached_background(&batch_post_thread, NULL, do_batch_backend_process, oldbatchitems)) { 01291 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n"); 01292 do_batch_backend_process(oldbatchitems); 01293 } else { 01294 ast_debug(1, "CDR multi-threaded batch processing begins now\n"); 01295 } 01296 } 01297 }
void ast_cdr_unregister | ( | const char * | name | ) |
Unregister a CDR handling engine.
unregister a CDR driver
Definition at line 163 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().
00164 { 00165 struct ast_cdr_beitem *i = NULL; 00166 00167 AST_RWLIST_WRLOCK(&be_list); 00168 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { 00169 if (!strcasecmp(name, i->name)) { 00170 AST_RWLIST_REMOVE_CURRENT(list); 00171 break; 00172 } 00173 } 00174 AST_RWLIST_TRAVERSE_SAFE_END; 00175 AST_RWLIST_UNLOCK(&be_list); 00176 00177 if (i) { 00178 ast_verb(2, "Unregistered '%s' CDR backend\n", name); 00179 ast_free(i); 00180 } 00181 }
int ast_cdr_update | ( | struct ast_channel * | chan | ) |
Update CDR on a channel.
Definition at line 1082 of file cdr.c.
References ast_channel::accountcode, AST_CDR_FLAG_LOCKED, ast_copy_string(), ast_test_flag, ast_channel::cdr, ast_channel::context, ast_channel::exten, ast_channel::linkedid, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, ast_channel::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().
01083 { 01084 struct ast_cdr *cdr = c->cdr; 01085 01086 for ( ; cdr ; cdr = cdr->next) { 01087 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01088 set_one_cid(cdr, c); 01089 01090 /* Copy account code et-al */ 01091 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 01092 ast_copy_string(cdr->peeraccount, c->peeraccount, sizeof(cdr->peeraccount)); 01093 ast_copy_string(cdr->linkedid, c->linkedid, sizeof(cdr->linkedid)); 01094 01095 /* Destination information */ /* XXX privilege macro* ? */ 01096 ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst)); 01097 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext)); 01098 } 01099 } 01100 01101 return 0; 01102 }
int check_cdr_enabled | ( | void | ) |
Return TRUE if CDR subsystem is enabled.
Definition at line 118 of file cdr.c.
References enabled.
Referenced by action_coresettings(), and handle_show_settings().
00119 { 00120 return enabled; 00121 }
char ast_default_accountcode[AST_MAX_ACCOUNT_CODE] |
Default AMA flag for billing records (CDR's)
Definition at line 59 of file cdr.c.
Referenced by __ast_channel_alloc_ap(), and ast_bridge_call().