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

Go to the source code of this file.
Data Structures | |
| struct | ast_cdr_batch |
| struct | ast_cdr_batch_item |
| struct | ast_cdr_beitem |
Defines | |
| #define | BATCH_SAFE_SHUTDOWN_DEFAULT 1 |
| #define | BATCH_SCHEDULER_ONLY_DEFAULT 0 |
| #define | BATCH_SIZE_DEFAULT 100 |
| #define | BATCH_TIME_DEFAULT 300 |
Functions | |
| ast_cdr * | ast_cdr_alloc (void) |
| Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure). | |
| int | ast_cdr_amaflags2int (const char *flag) |
| void | ast_cdr_answer (struct ast_cdr *cdr) |
| ast_cdr * | ast_cdr_append (struct ast_cdr *cdr, struct ast_cdr *newcdr) |
| int | ast_cdr_appenduserfield (struct ast_channel *chan, const char *userfield) |
| void | ast_cdr_busy (struct ast_cdr *cdr) |
| int | ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr) |
| void | ast_cdr_detach (struct ast_cdr *cdr) |
| void | ast_cdr_discard (struct ast_cdr *cdr) |
| Discard and free a CDR record. | |
| char * | ast_cdr_disp2str (int disposition) |
| int | ast_cdr_disposition (struct ast_cdr *cdr, int cause) |
| ast_cdr * | ast_cdr_dup (struct ast_cdr *cdr) |
| Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure). | |
| void | ast_cdr_end (struct ast_cdr *cdr) |
| int | ast_cdr_engine_init (void) |
| int | ast_cdr_engine_reload (void) |
| void | ast_cdr_engine_term (void) |
| void | ast_cdr_failed (struct ast_cdr *cdr) |
| char * | ast_cdr_flags2str (int flag) |
| void | ast_cdr_free (struct ast_cdr *cdr) |
| Free a CDR record. | |
| void | ast_cdr_free_vars (struct ast_cdr *cdr, int recur) |
| void | ast_cdr_getvar (struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw) |
| static const char * | ast_cdr_getvar_internal (struct ast_cdr *cdr, const char *name, int recur) |
| int | ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *c) |
| Initialize based on a channel. | |
| int | ast_cdr_isset_unanswered (void) |
| void | ast_cdr_merge (struct ast_cdr *to, struct ast_cdr *from) |
| void | ast_cdr_noanswer (struct ast_cdr *cdr) |
| int | ast_cdr_register (const char *name, const char *desc, ast_cdrbe be) |
| void | ast_cdr_reset (struct ast_cdr *cdr, struct ast_flags *_flags) |
| int | ast_cdr_serialize_variables (struct ast_cdr *cdr, char *buf, size_t size, char delim, char sep, int recur) |
| int | ast_cdr_setaccount (struct ast_channel *chan, const char *account) |
| int | ast_cdr_setamaflags (struct ast_channel *chan, const char *flag) |
| void | ast_cdr_setapp (struct ast_cdr *cdr, char *app, char *data) |
| int | ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *c) |
| void | ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chann) |
| int | ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield) |
| int | ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur) |
| void | ast_cdr_specialized_reset (struct ast_cdr *cdr, struct ast_flags *_flags) |
| void | ast_cdr_start (struct ast_cdr *cdr) |
| void | ast_cdr_submit_batch (int shutdown) |
| void | ast_cdr_unregister (const char *name) |
| int | ast_cdr_update (struct ast_channel *c) |
| static | AST_LIST_HEAD_STATIC (be_list, ast_cdr_beitem) |
| AST_MUTEX_DEFINE_STATIC (cdr_pending_lock) | |
| AST_MUTEX_DEFINE_STATIC (cdr_batch_lock) | |
| static void | cdr_get_tv (struct timeval tv, const char *fmt, char *buf, int bufsize) |
| static void | cdr_merge_vars (struct ast_cdr *to, struct ast_cdr *from) |
| static void | check_post (struct ast_cdr *cdr) |
| print a warning if cdr already posted | |
| static void * | do_batch_backend_process (void *data) |
| static void * | do_cdr (void *data) |
| static int | do_reload (void) |
| static int | handle_cli_status (int fd, int argc, char *argv[]) |
| static int | handle_cli_submit (int fd, int argc, char *argv[]) |
| static int | init_batch (void) |
| static void | post_cdr (struct ast_cdr *cdr) |
| static void | reset_batch (void) |
| static void | set_one_cid (struct ast_cdr *cdr, struct ast_channel *c) |
| static int | submit_scheduled_batch (const void *data) |
| static void | submit_unscheduled_batch (void) |
Variables | |
| char | ast_default_accountcode [AST_MAX_ACCOUNT_CODE] |
| int | ast_default_amaflags = AST_CDR_DOCUMENTATION |
| static struct ast_cdr_batch * | batch |
| static int | batchmode |
| static int | batchsafeshutdown |
| static int | batchscheduleronly |
| static int | batchsize |
| static int | batchtime |
| static ast_cond_t | cdr_pending_cond |
| static const char * | cdr_readonly_vars [] |
| static int | cdr_sched = -1 |
| static pthread_t | cdr_thread = AST_PTHREADT_NULL |
| static struct ast_cli_entry | cli_status |
| static struct ast_cli_entry | cli_submit |
| static int | enabled |
| static struct sched_context * | sched |
| static int | unanswered |
We do a lot of checking here in the CDR code to try to be sure we don't ever let a CDR slip through our fingers somehow. If someone allocates a CDR, it must be completely handled normally or a WARNING shall be logged, so that we can best keep track of any escape condition where the CDR isn't properly generated and posted.
Definition in file cdr.c.
| #define BATCH_SAFE_SHUTDOWN_DEFAULT 1 |
| #define BATCH_SCHEDULER_ONLY_DEFAULT 0 |
| #define BATCH_SIZE_DEFAULT 100 |
| #define BATCH_TIME_DEFAULT 300 |
| struct ast_cdr* ast_cdr_alloc | ( | void | ) |
Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
Definition at line 465 of file cdr.c.
References ast_calloc, ast_log(), and LOG_ERROR.
Referenced by __agent_start_monitoring(), __ast_request_and_dial(), ast_bridge_call(), ast_cdr_dup(), ast_channel_alloc(), builtin_blindtransfer(), clear_caller(), findmeexec(), and start_monitor_exec().
00466 { 00467 struct ast_cdr *x = ast_calloc(1, sizeof(struct ast_cdr)); 00468 if (!x) 00469 ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n"); 00470 return x; 00471 }
| int ast_cdr_amaflags2int | ( | const char * | flag | ) |
| flag | string form of flag Converts the string form of the flag to the binary form. Returns the binary form of the flag |
Definition at line 991 of file cdr.c.
References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
Referenced by ast_cdr_setamaflags(), build_device(), build_gateway(), build_peer(), build_user(), process_dahdi(), and set_config().
00992 { 00993 if (!strcasecmp(flag, "default")) 00994 return 0; 00995 if (!strcasecmp(flag, "omit")) 00996 return AST_CDR_OMIT; 00997 if (!strcasecmp(flag, "billing")) 00998 return AST_CDR_BILLING; 00999 if (!strcasecmp(flag, "documentation")) 01000 return AST_CDR_DOCUMENTATION; 01001 return -1; 01002 }
| void ast_cdr_answer | ( | struct ast_cdr * | cdr | ) |
| cdr | the cdr you wish to associate with the call Starts all CDR stuff necessary for doing CDR when answering a call NULL argument is just fine. |
Definition at line 701 of file cdr.c.
References AST_CDR_ANSWERED, AST_CDR_FLAG_ANSLOCKED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), and ast_cdr::next.
Referenced by ast_answer(), and ast_bridge_call().
00702 { 00703 00704 for (; cdr; cdr = cdr->next) { 00705 if (ast_test_flag(cdr, AST_CDR_FLAG_ANSLOCKED)) 00706 continue; 00707 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00708 continue; 00709 check_post(cdr); 00710 if (cdr->disposition < AST_CDR_ANSWERED) 00711 cdr->disposition = AST_CDR_ANSWERED; 00712 if (ast_tvzero(cdr->answer)) 00713 cdr->answer = ast_tvnow(); 00714 } 00715 }
Definition at line 1094 of file cdr.c.
References ast_cdr::next.
Referenced by ast_cdr_fork(), and ast_cdr_merge().
01095 { 01096 struct ast_cdr *ret; 01097 01098 if (cdr) { 01099 ret = cdr; 01100 01101 while (cdr->next) 01102 cdr = cdr->next; 01103 cdr->next = newcdr; 01104 } else { 01105 ret = newcdr; 01106 } 01107 01108 return ret; 01109 }
| int ast_cdr_appenduserfield | ( | struct ast_channel * | chan, | |
| const char * | userfield | |||
| ) |
Definition at line 957 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, len, ast_cdr::next, and ast_cdr::userfield.
Referenced by action_setcdruserfield(), and appendcdruserfield_exec().
00958 { 00959 struct ast_cdr *cdr = chan->cdr; 00960 00961 for ( ; cdr ; cdr = cdr->next) { 00962 int len = strlen(cdr->userfield); 00963 00964 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00965 ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len); 00966 } 00967 00968 return 0; 00969 }
| void ast_cdr_busy | ( | struct ast_cdr * | cdr | ) |
| cdr | the cdr you wish to associate with the call Marks the channel disposition as "BUSY" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. Returns nothing |
Definition at line 717 of file cdr.c.
References AST_CDR_BUSY, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), and ast_cdr::next.
Referenced by ast_cdr_disposition(), and ring_entry().
00718 { 00719 00720 for (; cdr; cdr = cdr->next) { 00721 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00722 check_post(cdr); 00723 if (cdr->disposition < AST_CDR_BUSY) 00724 cdr->disposition = AST_CDR_BUSY; 00725 } 00726 } 00727 }
Definition at line 342 of file cdr.c.
References AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_assign(), ast_var_name(), ast_var_value(), var, and ast_cdr::varshead.
Referenced by ast_cdr_dup().
00343 { 00344 struct ast_var_t *variables, *newvariable = NULL; 00345 struct varshead *headpa, *headpb; 00346 const char *var, *val; 00347 int x = 0; 00348 00349 if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */ 00350 return 0; 00351 00352 headpa = &from_cdr->varshead; 00353 headpb = &to_cdr->varshead; 00354 00355 AST_LIST_TRAVERSE(headpa,variables,entries) { 00356 if (variables && 00357 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00358 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00359 newvariable = ast_var_assign(var, val); 00360 AST_LIST_INSERT_HEAD(headpb, newvariable, entries); 00361 x++; 00362 } 00363 } 00364 00365 return x; 00366 }
| void ast_cdr_detach | ( | struct ast_cdr * | cdr | ) |
| cdr | Which CDR to detach from the channel thread Prevents the channel thread from blocking on the CDR handling Returns nothing |
Definition at line 1205 of file cdr.c.
References ast_calloc, AST_CDR_FLAG_POST_DISABLED, ast_cdr_free(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, batch, batchmode, batchsize, ast_cdr_batch_item::cdr, enabled, ast_cdr_batch::head, init_batch(), LOG_DEBUG, ast_cdr_batch_item::next, option_debug, post_cdr(), ast_cdr_batch::size, submit_unscheduled_batch(), and ast_cdr_batch::tail.
Referenced by ast_bridge_call(), ast_cdr_reset(), ast_hangup(), and ast_pbx_outgoing_cdr_failed().
01206 { 01207 struct ast_cdr_batch_item *newtail; 01208 int curr; 01209 01210 if (!cdr) 01211 return; 01212 01213 /* maybe they disabled CDR stuff completely, so just drop it */ 01214 if (!enabled) { 01215 if (option_debug) 01216 ast_log(LOG_DEBUG, "Dropping CDR !\n"); 01217 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01218 ast_cdr_free(cdr); 01219 return; 01220 } 01221 01222 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */ 01223 if (!batchmode) { 01224 post_cdr(cdr); 01225 ast_cdr_free(cdr); 01226 return; 01227 } 01228 01229 /* otherwise, each CDR gets put into a batch list (at the end) */ 01230 if (option_debug) 01231 ast_log(LOG_DEBUG, "CDR detaching from this thread\n"); 01232 01233 /* we'll need a new tail for every CDR */ 01234 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) { 01235 post_cdr(cdr); 01236 ast_cdr_free(cdr); 01237 return; 01238 } 01239 01240 /* don't traverse a whole list (just keep track of the tail) */ 01241 ast_mutex_lock(&cdr_batch_lock); 01242 if (!batch) 01243 init_batch(); 01244 if (!batch->head) { 01245 /* new batch is empty, so point the head at the new tail */ 01246 batch->head = newtail; 01247 } else { 01248 /* already got a batch with something in it, so just append a new tail */ 01249 batch->tail->next = newtail; 01250 } 01251 newtail->cdr = cdr; 01252 batch->tail = newtail; 01253 curr = batch->size++; 01254 ast_mutex_unlock(&cdr_batch_lock); 01255 01256 /* if we have enough stuff to post, then do it */ 01257 if (curr >= (batchsize - 1)) 01258 submit_unscheduled_batch(); 01259 }
| void ast_cdr_discard | ( | struct ast_cdr * | cdr | ) |
Discard and free a CDR record.
| cdr | ast_cdr structure to free Returns nothing -- same as free, but no checks or complaints |
Definition at line 454 of file cdr.c.
References ast_cdr_free_vars(), free, and ast_cdr::next.
Referenced by ast_async_goto(), ast_cdr_merge(), and ast_channel_free().
00455 { 00456 while (cdr) { 00457 struct ast_cdr *next = cdr->next; 00458 00459 ast_cdr_free_vars(cdr, 0); 00460 free(cdr); 00461 cdr = next; 00462 } 00463 }
| char* ast_cdr_disp2str | ( | int | disposition | ) |
| disposition | input binary form Converts the binary form of a disposition to string form. Returns a pointer to the string form |
Definition at line 886 of file cdr.c.
References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, AST_CDR_NOANSWER, and AST_CDR_NULL.
Referenced by ast_cdr_getvar(), build_csv_record(), build_query(), build_radius_record(), csv_log(), manager_log(), pgsql_log(), and tds_log().
00887 { 00888 switch (disposition) { 00889 case AST_CDR_NULL: 00890 return "NO ANSWER"; /* by default, for backward compatibility */ 00891 case AST_CDR_NOANSWER: 00892 return "NO ANSWER"; 00893 case AST_CDR_FAILED: 00894 return "FAILED"; 00895 case AST_CDR_BUSY: 00896 return "BUSY"; 00897 case AST_CDR_ANSWERED: 00898 return "ANSWERED"; 00899 } 00900 return "UNKNOWN"; 00901 }
| int ast_cdr_disposition | ( | struct ast_cdr * | cdr, | |
| int | cause | |||
| ) |
| cdr | the cdr you wish to associate with the call | |
| cause | the AST_CAUSE_* Returns nothing |
Definition at line 759 of file cdr.c.
References AST_CAUSE_BUSY, AST_CAUSE_NORMAL, ast_cdr_busy(), and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), clear_caller(), and findmeexec().
00760 { 00761 int res = 0; 00762 00763 for (; cdr; cdr = cdr->next) { 00764 switch(cause) { /* handle all the non failure, busy cases, return 0 not to set disposition, 00765 return -1 to set disposition to FAILED */ 00766 case AST_CAUSE_BUSY: 00767 ast_cdr_busy(cdr); 00768 break; 00769 case AST_CAUSE_NORMAL: 00770 break; 00771 default: 00772 res = -1; 00773 } 00774 } 00775 return res; 00776 }
Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
Duplicate a CDR record
Definition at line 173 of file cdr.c.
References ast_cdr_alloc(), and ast_cdr_copy_vars().
Referenced by ast_async_goto(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_merge(), and ast_cdr_reset().
00174 { 00175 struct ast_cdr *newcdr; 00176 00177 if (!cdr) /* don't die if we get a null cdr pointer */ 00178 return NULL; 00179 newcdr = ast_cdr_alloc(); 00180 if (!newcdr) 00181 return NULL; 00182 00183 memcpy(newcdr, cdr, sizeof(*newcdr)); 00184 /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */ 00185 memset(&newcdr->varshead, 0, sizeof(newcdr->varshead)); 00186 ast_cdr_copy_vars(newcdr, cdr); 00187 newcdr->next = NULL; 00188 00189 return newcdr; 00190 }
| void ast_cdr_end | ( | struct ast_cdr * | cdr | ) |
| cdr | the cdr you have associated the call with Registers the end of call time in the cdr structure. Returns nothing |
Definition at line 863 of file cdr.c.
References AST_CDR_ANSWERED, AST_CDR_FAILED, AST_CDR_FLAG_DONT_TOUCH, AST_CDR_FLAG_LOCKED, ast_log(), ast_test_flag, check_post(), LOG_WARNING, ast_cdr::next, and S_OR.
Referenced by __ast_request_and_dial(), ast_bridge_call(), ast_cdr_fork(), ast_cdr_reset(), ast_hangup(), ast_pbx_outgoing_cdr_failed(), clear_caller(), and findmeexec().
00864 { 00865 for ( ; cdr ; cdr = cdr->next) { 00866 if (ast_test_flag(cdr, AST_CDR_FLAG_DONT_TOUCH) && ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00867 continue; 00868 check_post(cdr); 00869 if (ast_tvzero(cdr->end)) 00870 cdr->end = ast_tvnow(); 00871 if (ast_tvzero(cdr->start)) { 00872 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>")); 00873 cdr->disposition = AST_CDR_FAILED; 00874 } else 00875 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec; 00876 if (ast_tvzero(cdr->answer)) { 00877 if (cdr->disposition == AST_CDR_ANSWERED) { 00878 ast_log(LOG_WARNING, "CDR on channel '%s' has no answer time but is 'ANSWERED'\n", S_OR(cdr->channel, "<unknown>")); 00879 cdr->disposition = AST_CDR_FAILED; 00880 } 00881 } else 00882 cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec; 00883 } 00884 }
| int ast_cdr_engine_init | ( | void | ) |
Load the configuration file cdr.conf and possibly start the CDR scheduling thread
Definition at line 1463 of file cdr.c.
References ast_cli_register(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cli_status, do_reload(), init_batch(), LOG_ERROR, and sched_context_create().
Referenced by main().
01464 { 01465 int res; 01466 01467 sched = sched_context_create(); 01468 if (!sched) { 01469 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 01470 return -1; 01471 } 01472 01473 ast_cli_register(&cli_status); 01474 01475 res = do_reload(); 01476 if (res) { 01477 ast_mutex_lock(&cdr_batch_lock); 01478 res = init_batch(); 01479 ast_mutex_unlock(&cdr_batch_lock); 01480 } 01481 01482 return res; 01483 }
| int ast_cdr_engine_reload | ( | void | ) |
Reload the configuration file cdr.conf and start/stop CDR scheduling thread
Definition at line 1492 of file cdr.c.
References do_reload().
01493 { 01494 return do_reload(); 01495 }
| void ast_cdr_engine_term | ( | void | ) |
Submit any remaining CDRs and prepare for shutdown
Definition at line 1487 of file cdr.c.
References ast_cdr_submit_batch(), and batchsafeshutdown.
Referenced by do_reload(), and quit_handler().
01488 { 01489 ast_cdr_submit_batch(batchsafeshutdown); 01490 }
| void ast_cdr_failed | ( | struct ast_cdr * | cdr | ) |
| cdr | the cdr you wish to associate with the call Marks the channel disposition as "FAILED" Will skip CDR's in chain with ANS_LOCK bit set. (see forkCDR() application. Returns nothing |
Definition at line 729 of file cdr.c.
References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), clear_caller(), and findmeexec().
00730 { 00731 for (; cdr; cdr = cdr->next) { 00732 check_post(cdr); 00733 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00734 if (cdr->disposition < AST_CDR_FAILED) 00735 cdr->disposition = AST_CDR_FAILED; 00736 } 00737 } 00738 }
| char* ast_cdr_flags2str | ( | int | flag | ) |
Converts AMA flag to printable string
Definition at line 904 of file cdr.c.
References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
Referenced by _sip_show_peer(), ast_cdr_getvar(), build_csv_record(), build_radius_record(), csv_log(), manager_log(), sip_show_user(), and tds_log().
00905 { 00906 switch(flag) { 00907 case AST_CDR_OMIT: 00908 return "OMIT"; 00909 case AST_CDR_BILLING: 00910 return "BILLING"; 00911 case AST_CDR_DOCUMENTATION: 00912 return "DOCUMENTATION"; 00913 } 00914 return "Unknown"; 00915 }
| void ast_cdr_free | ( | struct ast_cdr * | cdr | ) |
Free a CDR record.
| cdr | ast_cdr structure to free Returns nothing |
Definition at line 434 of file cdr.c.
References AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), ast_test_flag, ast_verbose(), ast_cdr::channel, ast_cdr::end, free, ast_cdr::next, option_verbose, S_OR, ast_cdr::start, and VERBOSE_PREFIX_2.
Referenced by ast_cdr_detach(), and do_batch_backend_process().
00435 { 00436 00437 while (cdr) { 00438 struct ast_cdr *next = cdr->next; 00439 char *chan = S_OR(cdr->channel, "<unknown>"); 00440 if (option_verbose > 1 && !ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) 00441 ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' not posted\n", chan); 00442 if (option_verbose > 1 && ast_tvzero(cdr->end)) 00443 ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' lacks end\n", chan); 00444 if (option_verbose > 1 && ast_tvzero(cdr->start)) 00445 ast_verbose(VERBOSE_PREFIX_2 "CDR on channel '%s' lacks start\n", chan); 00446 00447 ast_cdr_free_vars(cdr, 0); 00448 free(cdr); 00449 cdr = next; 00450 } 00451 }
| void ast_cdr_free_vars | ( | struct ast_cdr * | cdr, | |
| int | recur | |||
| ) |
Definition at line 413 of file cdr.c.
References AST_LIST_REMOVE_HEAD, ast_var_delete(), ast_cdr::next, and ast_cdr::varshead.
Referenced by ast_cdr_discard(), ast_cdr_fork(), ast_cdr_free(), and ast_cdr_reset().
00414 { 00415 00416 /* clear variables */ 00417 for (; cdr; cdr = recur ? cdr->next : NULL) { 00418 struct ast_var_t *vardata; 00419 struct varshead *headp = &cdr->varshead; 00420 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 00421 ast_var_delete(vardata); 00422 } 00423 }
| void ast_cdr_getvar | ( | struct ast_cdr * | cdr, | |
| const char * | name, | |||
| char ** | ret, | |||
| char * | workspace, | |||
| int | workspacelen, | |||
| int | recur, | |||
| int | raw | |||
| ) |
CDR channel variable retrieval
Definition at line 225 of file cdr.c.
References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, ast_cdr_disp2str(), ast_cdr_flags2str(), ast_cdr_getvar_internal(), ast_strlen_zero(), ast_cdr::billsec, cdr_get_tv(), ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, fmt, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.
Referenced by ast_cdr_serialize_variables(), and cdr_read().
00226 { 00227 const char *fmt = "%Y-%m-%d %T"; 00228 const char *varbuf; 00229 00230 if (!cdr) /* don't die if the cdr is null */ 00231 return; 00232 00233 *ret = NULL; 00234 /* special vars (the ones from the struct ast_cdr when requested by name) 00235 I'd almost say we should convert all the stringed vals to vars */ 00236 00237 if (!strcasecmp(name, "clid")) 00238 ast_copy_string(workspace, cdr->clid, workspacelen); 00239 else if (!strcasecmp(name, "src")) 00240 ast_copy_string(workspace, cdr->src, workspacelen); 00241 else if (!strcasecmp(name, "dst")) 00242 ast_copy_string(workspace, cdr->dst, workspacelen); 00243 else if (!strcasecmp(name, "dcontext")) 00244 ast_copy_string(workspace, cdr->dcontext, workspacelen); 00245 else if (!strcasecmp(name, "channel")) 00246 ast_copy_string(workspace, cdr->channel, workspacelen); 00247 else if (!strcasecmp(name, "dstchannel")) 00248 ast_copy_string(workspace, cdr->dstchannel, workspacelen); 00249 else if (!strcasecmp(name, "lastapp")) 00250 ast_copy_string(workspace, cdr->lastapp, workspacelen); 00251 else if (!strcasecmp(name, "lastdata")) 00252 ast_copy_string(workspace, cdr->lastdata, workspacelen); 00253 else if (!strcasecmp(name, "start")) 00254 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen); 00255 else if (!strcasecmp(name, "answer")) 00256 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen); 00257 else if (!strcasecmp(name, "end")) 00258 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen); 00259 else if (!strcasecmp(name, "duration")) 00260 snprintf(workspace, workspacelen, "%ld", cdr->duration); 00261 else if (!strcasecmp(name, "billsec")) 00262 snprintf(workspace, workspacelen, "%ld", cdr->billsec); 00263 else if (!strcasecmp(name, "disposition")) { 00264 if (raw) { 00265 snprintf(workspace, workspacelen, "%ld", cdr->disposition); 00266 } else { 00267 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); 00268 } 00269 } else if (!strcasecmp(name, "amaflags")) { 00270 if (raw) { 00271 snprintf(workspace, workspacelen, "%ld", cdr->amaflags); 00272 } else { 00273 ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); 00274 } 00275 } else if (!strcasecmp(name, "accountcode")) 00276 ast_copy_string(workspace, cdr->accountcode, workspacelen); 00277 else if (!strcasecmp(name, "uniqueid")) 00278 ast_copy_string(workspace, cdr->uniqueid, workspacelen); 00279 else if (!strcasecmp(name, "userfield")) 00280 ast_copy_string(workspace, cdr->userfield, workspacelen); 00281 else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) 00282 ast_copy_string(workspace, varbuf, workspacelen); 00283 else 00284 workspace[0] = '\0'; 00285 00286 if (!ast_strlen_zero(workspace)) 00287 *ret = workspace; 00288 }
| static const char* ast_cdr_getvar_internal | ( | struct ast_cdr * | cdr, | |
| const char * | name, | |||
| int | recur | |||
| ) | [static] |
Definition at line 192 of file cdr.c.
References AST_LIST_TRAVERSE, ast_strlen_zero(), ast_var_name(), ast_var_value(), ast_cdr::next, and ast_cdr::varshead.
Referenced by ast_cdr_getvar().
00193 { 00194 if (ast_strlen_zero(name)) 00195 return NULL; 00196 00197 for (; cdr; cdr = recur ? cdr->next : NULL) { 00198 struct ast_var_t *variables; 00199 struct varshead *headp = &cdr->varshead; 00200 AST_LIST_TRAVERSE(headp, variables, entries) { 00201 if (!strcasecmp(name, ast_var_name(variables))) 00202 return ast_var_value(variables); 00203 } 00204 } 00205 00206 return NULL; 00207 }
| int ast_cdr_init | ( | struct ast_cdr * | cdr, | |
| struct ast_channel * | chan | |||
| ) |
Initialize based on a channel.
| cdr | Call Detail Record to use for channel | |
| chan | Channel to bind CDR with Initializes a CDR and associates it with a particular channel Return is negligible. (returns 0 by default) |
Definition at line 828 of file cdr.c.
References ast_channel::_state, ast_channel::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NULL, AST_STATE_UP, ast_test_flag, ast_cdr::channel, ast_channel::context, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, S_OR, and set_one_cid().
Referenced by __ast_request_and_dial(), ast_channel_alloc(), ast_pbx_outgoing_cdr_failed(), builtin_blindtransfer(), clear_caller(), and findmeexec().
00829 { 00830 char *chan; 00831 00832 for ( ; cdr ; cdr = cdr->next) { 00833 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00834 chan = S_OR(cdr->channel, "<unknown>"); 00835 ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); 00836 set_one_cid(cdr, c); 00837 00838 cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL; 00839 cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; 00840 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00841 /* Destination information */ 00842 ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst)); 00843 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext)); 00844 /* Unique call identifier */ 00845 ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid)); 00846 } 00847 } 00848 return 0; 00849 }
| int ast_cdr_isset_unanswered | ( | void | ) |
Definition at line 165 of file cdr.c.
References unanswered.
00166 { 00167 return unanswered; 00168 }