#include <sys/time.h>
#include "asterisk/channel.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Data Structures | |
struct | ast_cdr |
Defines | |
#define | AST_CDR_ANSWERED (1 << 3) |
#define | AST_CDR_BILLING (2) |
#define | AST_CDR_BUSY (1 << 1) |
#define | AST_CDR_DOCUMENTATION (3) |
#define | AST_CDR_FAILED (1 << 0) |
#define | AST_CDR_FLAG_CHILD (1 << 3) |
#define | AST_CDR_FLAG_KEEP_VARS (1 << 0) |
#define | AST_CDR_FLAG_LOCKED (1 << 2) |
#define | AST_CDR_FLAG_POST_DISABLED (1 << 4) |
#define | AST_CDR_FLAG_POSTED (1 << 1) |
#define | AST_CDR_NOANSWER (1 << 2) |
#define | AST_CDR_NULL 0 |
#define | AST_CDR_OMIT (1) |
#define | AST_MAX_ACCOUNT_CODE 20 |
#define | AST_MAX_USER_FIELD 256 |
Typedefs | |
typedef int(* | ast_cdrbe )(struct ast_cdr *cdr) |
Functions | |
struct ast_cdr * | ast_cdr_alloc (void) |
Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure). | |
int | ast_cdr_amaflags2int (const char *flag) |
void | ast_cdr_answer (struct ast_cdr *cdr) |
struct ast_cdr * | ast_cdr_append (struct ast_cdr *cdr, struct ast_cdr *newcdr) |
int | ast_cdr_appenduserfield (struct ast_channel *chan, const char *userfield) |
void | ast_cdr_busy (struct ast_cdr *cdr) |
int | ast_cdr_copy_vars (struct ast_cdr *to_cdr, struct ast_cdr *from_cdr) |
void | ast_cdr_detach (struct ast_cdr *cdr) |
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) |
struct ast_cdr * | ast_cdr_dup (struct ast_cdr *cdr) |
Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure). | |
void | ast_cdr_end (struct ast_cdr *cdr) |
int | ast_cdr_engine_init (void) |
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 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. | |
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 *amaflags) |
void | ast_cdr_setapp (struct ast_cdr *cdr, char *app, char *data) |
int | ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *chan) |
void | ast_cdr_setdestchan (struct ast_cdr *cdr, const char *chan) |
int | ast_cdr_setuserfield (struct ast_channel *chan, const char *userfield) |
int | ast_cdr_setvar (struct ast_cdr *cdr, const char *name, const char *value, int recur) |
void | ast_cdr_start (struct ast_cdr *cdr) |
void | ast_cdr_submit_batch (int shutdown) |
void | ast_cdr_unregister (const char *name) |
int | ast_cdr_update (struct ast_channel *chan) |
Variables | |
char | ast_default_accountcode [AST_MAX_ACCOUNT_CODE] |
int | ast_default_amaflags |
Definition in file cdr.h.
#define AST_CDR_ANSWERED (1 << 3) |
Definition at line 37 of file cdr.h.
Referenced by ast_cdr_answer(), ast_cdr_disp2str(), and ast_cdr_init().
#define AST_CDR_BILLING (2) |
#define AST_CDR_BUSY (1 << 1) |
#define AST_CDR_DOCUMENTATION (3) |
Definition at line 42 of file cdr.h.
Referenced by ast_cdr_amaflags2int(), ast_cdr_flags2str(), and ast_cdr_merge().
#define AST_CDR_FAILED (1 << 0) |
Definition at line 34 of file cdr.h.
Referenced by ast_cdr_disp2str(), ast_cdr_end(), and ast_cdr_failed().
#define AST_CDR_FLAG_CHILD (1 << 3) |
#define AST_CDR_FLAG_KEEP_VARS (1 << 0) |
Definition at line 27 of file cdr.h.
Referenced by ast_cdr_fork(), ast_cdr_merge(), ast_cdr_reset(), and forkcdr_exec().
#define AST_CDR_FLAG_LOCKED (1 << 2) |
Definition at line 29 of file cdr.h.
Referenced by ast_bridge_call(), ast_cdr_appenduserfield(), ast_cdr_busy(), ast_cdr_failed(), ast_cdr_fork(), ast_cdr_init(), ast_cdr_merge(), ast_cdr_noanswer(), ast_cdr_reset(), ast_cdr_setaccount(), ast_cdr_setamaflags(), ast_cdr_setapp(), ast_cdr_setcid(), ast_cdr_setdestchan(), ast_cdr_setuserfield(), ast_cdr_start(), and ast_cdr_update().
#define AST_CDR_FLAG_POST_DISABLED (1 << 4) |
Definition at line 31 of file cdr.h.
Referenced by ast_cdr_detach(), ast_cdr_free(), ast_cdr_merge(), nocdr_exec(), and post_cdr().
#define AST_CDR_FLAG_POSTED (1 << 1) |
Definition at line 28 of file cdr.h.
Referenced by ast_cdr_free(), ast_cdr_merge(), ast_cdr_noanswer(), ast_cdr_reset(), check_post(), disa_exec(), and post_cdr().
#define AST_CDR_NOANSWER (1 << 2) |
Definition at line 36 of file cdr.h.
Referenced by ast_cdr_disp2str(), ast_cdr_merge(), and ast_cdr_noanswer().
#define AST_CDR_NULL 0 |
Definition at line 33 of file cdr.h.
Referenced by ast_cdr_disp2str(), ast_cdr_init(), and ast_cdr_reset().
#define AST_CDR_OMIT (1) |
AMA Flags
Definition at line 40 of file cdr.h.
Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str().
struct ast_cdr* ast_cdr_alloc | ( | void | ) | [read] |
Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
Definition at line 456 of file cdr.c.
References ast_calloc, ast_log(), and LOG_ERROR.
00457 { 00458 struct ast_cdr *x = ast_calloc(1, sizeof(struct ast_cdr)); 00459 if (!x) 00460 ast_log(LOG_ERROR,"Allocation Failure for a CDR!\n"); 00461 return x; 00462 }
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. Returns the binary form of the flag |
Definition at line 967 of file cdr.c.
References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
00968 { 00969 if (!strcasecmp(flag, "default")) 00970 return 0; 00971 if (!strcasecmp(flag, "omit")) 00972 return AST_CDR_OMIT; 00973 if (!strcasecmp(flag, "billing")) 00974 return AST_CDR_BILLING; 00975 if (!strcasecmp(flag, "documentation")) 00976 return AST_CDR_DOCUMENTATION; 00977 return -1; 00978 }
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 NULL argument is just fine. |
Definition at line 692 of file cdr.c.
References ast_cdr::answer, AST_CDR_ANSWERED, check_post(), ast_cdr::disposition, and ast_cdr::next.
00693 { 00694 00695 for (; cdr; cdr = cdr->next) { 00696 check_post(cdr); 00697 if (cdr->disposition < AST_CDR_ANSWERED) 00698 cdr->disposition = AST_CDR_ANSWERED; 00699 if (ast_tvzero(cdr->answer)) 00700 cdr->answer = ast_tvnow(); 00701 } 00702 }
int ast_cdr_appenduserfield | ( | struct ast_channel * | chan, | |
const char * | userfield | |||
) |
Definition at line 933 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, len, ast_cdr::next, and ast_cdr::userfield.
00934 { 00935 struct ast_cdr *cdr = chan->cdr; 00936 00937 for ( ; cdr ; cdr = cdr->next) { 00938 int len = strlen(cdr->userfield); 00939 00940 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00941 ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len); 00942 } 00943 00944 return 0; 00945 }
void ast_cdr_busy | ( | struct ast_cdr * | cdr | ) |
Busy a call
cdr | the cdr you wish to associate with the call Returns nothing |
Definition at line 704 of file cdr.c.
References AST_CDR_BUSY, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
00705 { 00706 00707 for (; cdr; cdr = cdr->next) { 00708 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00709 check_post(cdr); 00710 if (cdr->disposition < AST_CDR_BUSY) 00711 cdr->disposition = AST_CDR_BUSY; 00712 } 00713 } 00714 }
Definition at line 334 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.
00335 { 00336 struct ast_var_t *variables, *newvariable = NULL; 00337 struct varshead *headpa, *headpb; 00338 const char *var, *val; 00339 int x = 0; 00340 00341 if (!to_cdr || !from_cdr) /* don't die if one of the pointers is null */ 00342 return 0; 00343 00344 headpa = &from_cdr->varshead; 00345 headpb = &to_cdr->varshead; 00346 00347 AST_LIST_TRAVERSE(headpa,variables,entries) { 00348 if (variables && 00349 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00350 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00351 newvariable = ast_var_assign(var, val); 00352 AST_LIST_INSERT_HEAD(headpb, newvariable, entries); 00353 x++; 00354 } 00355 } 00356 00357 return x; 00358 }
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 1152 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.
01153 { 01154 struct ast_cdr_batch_item *newtail; 01155 int curr; 01156 01157 if (!cdr) 01158 return; 01159 01160 /* maybe they disabled CDR stuff completely, so just drop it */ 01161 if (!enabled) { 01162 if (option_debug) 01163 ast_log(LOG_DEBUG, "Dropping CDR !\n"); 01164 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 01165 ast_cdr_free(cdr); 01166 return; 01167 } 01168 01169 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */ 01170 if (!batchmode) { 01171 post_cdr(cdr); 01172 ast_cdr_free(cdr); 01173 return; 01174 } 01175 01176 /* otherwise, each CDR gets put into a batch list (at the end) */ 01177 if (option_debug) 01178 ast_log(LOG_DEBUG, "CDR detaching from this thread\n"); 01179 01180 /* we'll need a new tail for every CDR */ 01181 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) { 01182 post_cdr(cdr); 01183 ast_cdr_free(cdr); 01184 return; 01185 } 01186 01187 /* don't traverse a whole list (just keep track of the tail) */ 01188 ast_mutex_lock(&cdr_batch_lock); 01189 if (!batch) 01190 init_batch(); 01191 if (!batch->head) { 01192 /* new batch is empty, so point the head at the new tail */ 01193 batch->head = newtail; 01194 } else { 01195 /* already got a batch with something in it, so just append a new tail */ 01196 batch->tail->next = newtail; 01197 } 01198 newtail->cdr = cdr; 01199 batch->tail = newtail; 01200 curr = batch->size++; 01201 ast_mutex_unlock(&cdr_batch_lock); 01202 01203 /* if we have enough stuff to post, then do it */ 01204 if (curr >= (batchsize - 1)) 01205 submit_unscheduled_batch(); 01206 }
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 445 of file cdr.c.
References ast_cdr_free_vars(), free, and ast_cdr::next.
00446 { 00447 while (cdr) { 00448 struct ast_cdr *next = cdr->next; 00449 00450 ast_cdr_free_vars(cdr, 0); 00451 free(cdr); 00452 cdr = next; 00453 } 00454 }
char* ast_cdr_disp2str | ( | int | disposition | ) |
Disposition to a string
disposition | input binary form Converts the binary form of a disposition to string form. Returns a pointer to the string form |
Definition at line 862 of file cdr.c.
References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, AST_CDR_NOANSWER, and AST_CDR_NULL.
00863 { 00864 switch (disposition) { 00865 case AST_CDR_NULL: 00866 return "NO ANSWER"; /* by default, for backward compatibility */ 00867 case AST_CDR_NOANSWER: 00868 return "NO ANSWER"; 00869 case AST_CDR_FAILED: 00870 return "FAILED"; 00871 case AST_CDR_BUSY: 00872 return "BUSY"; 00873 case AST_CDR_ANSWERED: 00874 return "ANSWERED"; 00875 } 00876 return "UNKNOWN"; 00877 }
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 Returns nothing | |
cause | the AST_CAUSE_* |
Definition at line 743 of file cdr.c.
References AST_CAUSE_BUSY, AST_CAUSE_FAILURE, AST_CAUSE_NORMAL, AST_CAUSE_NOTDEFINED, ast_cdr_busy(), ast_cdr_failed(), ast_log(), LOG_WARNING, and ast_cdr::next.
00744 { 00745 int res = 0; 00746 00747 for (; cdr; cdr = cdr->next) { 00748 switch(cause) { 00749 case AST_CAUSE_BUSY: 00750 ast_cdr_busy(cdr); 00751 break; 00752 case AST_CAUSE_FAILURE: 00753 ast_cdr_failed(cdr); 00754 break; 00755 case AST_CAUSE_NORMAL: 00756 break; 00757 case AST_CAUSE_NOTDEFINED: 00758 res = -1; 00759 break; 00760 default: 00761 res = -1; 00762 ast_log(LOG_WARNING, "Cause not handled\n"); 00763 } 00764 } 00765 return res; 00766 }
Duplicate a record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
Duplicate a CDR record
Definition at line 167 of file cdr.c.
References ast_cdr_alloc(), ast_cdr_copy_vars(), ast_cdr::next, and ast_cdr::varshead.
00168 { 00169 struct ast_cdr *newcdr; 00170 00171 if (!cdr) /* don't die if we get a null cdr pointer */ 00172 return NULL; 00173 newcdr = ast_cdr_alloc(); 00174 if (!newcdr) 00175 return NULL; 00176 00177 memcpy(newcdr, cdr, sizeof(*newcdr)); 00178 /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */ 00179 memset(&newcdr->varshead, 0, sizeof(newcdr->varshead)); 00180 ast_cdr_copy_vars(newcdr, cdr); 00181 newcdr->next = NULL; 00182 00183 return newcdr; 00184 }
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 847 of file cdr.c.
References ast_cdr::answer, AST_CDR_FAILED, ast_log(), 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.
00848 { 00849 for ( ; cdr ; cdr = cdr->next) { 00850 check_post(cdr); 00851 if (ast_tvzero(cdr->end)) 00852 cdr->end = ast_tvnow(); 00853 if (ast_tvzero(cdr->start)) { 00854 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>")); 00855 cdr->disposition = AST_CDR_FAILED; 00856 } else 00857 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec; 00858 cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec; 00859 } 00860 }
int ast_cdr_engine_init | ( | void | ) |
Load the configuration file cdr.conf and possibly start the CDR scheduling thread
Definition at line 1406 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().
01407 { 01408 int res; 01409 01410 sched = sched_context_create(); 01411 if (!sched) { 01412 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 01413 return -1; 01414 } 01415 01416 ast_cli_register(&cli_status); 01417 01418 res = do_reload(); 01419 if (res) { 01420 ast_mutex_lock(&cdr_batch_lock); 01421 res = init_batch(); 01422 ast_mutex_unlock(&cdr_batch_lock); 01423 } 01424 01425 return res; 01426 }
int ast_cdr_engine_reload | ( | void | ) |
Reload the configuration file cdr.conf and start/stop CDR scheduling thread
Definition at line 1435 of file cdr.c.
References do_reload().
01436 { 01437 return do_reload(); 01438 }
void ast_cdr_engine_term | ( | void | ) |
Submit any remaining CDRs and prepare for shutdown
Definition at line 1430 of file cdr.c.
References ast_cdr_submit_batch(), and batchsafeshutdown.
01431 { 01432 ast_cdr_submit_batch(batchsafeshutdown); 01433 }
void ast_cdr_failed | ( | struct ast_cdr * | cdr | ) |
Fail a call
cdr | the cdr you wish to associate with the call Returns nothing |
Definition at line 716 of file cdr.c.
References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next.
00717 { 00718 for (; cdr; cdr = cdr->next) { 00719 check_post(cdr); 00720 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00721 if (cdr->disposition < AST_CDR_FAILED) 00722 cdr->disposition = AST_CDR_FAILED; 00723 } 00724 } 00725 }
char* ast_cdr_flags2str | ( | int | flag | ) |
Flags to a string
flags | binary flag Converts binary flags to string flags Returns string with flag name |
Definition at line 880 of file cdr.c.
References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
00881 { 00882 switch(flag) { 00883 case AST_CDR_OMIT: 00884 return "OMIT"; 00885 case AST_CDR_BILLING: 00886 return "BILLING"; 00887 case AST_CDR_DOCUMENTATION: 00888 return "DOCUMENTATION"; 00889 } 00890 return "Unknown"; 00891 }
void ast_cdr_free | ( | struct ast_cdr * | cdr | ) |
Free a CDR record.
cdr | ast_cdr structure to free Returns nothing |
Definition at line 425 of file cdr.c.
References AST_CDR_FLAG_POST_DISABLED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), ast_log(), ast_test_flag, ast_cdr::channel, ast_cdr::end, free, LOG_NOTICE, ast_cdr::next, S_OR, and ast_cdr::start.
00426 { 00427 00428 while (cdr) { 00429 struct ast_cdr *next = cdr->next; 00430 char *chan = S_OR(cdr->channel, "<unknown>"); 00431 if (!ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) 00432 ast_log(LOG_NOTICE, "CDR on channel '%s' not posted\n", chan); 00433 if (ast_tvzero(cdr->end)) 00434 ast_log(LOG_NOTICE, "CDR on channel '%s' lacks end\n", chan); 00435 if (ast_tvzero(cdr->start)) 00436 ast_log(LOG_NOTICE, "CDR on channel '%s' lacks start\n", chan); 00437 00438 ast_cdr_free_vars(cdr, 0); 00439 free(cdr); 00440 cdr = next; 00441 } 00442 }
void ast_cdr_free_vars | ( | struct ast_cdr * | cdr, | |
int | recur | |||
) |
Definition at line 404 of file cdr.c.
References AST_LIST_REMOVE_HEAD, ast_var_delete(), ast_cdr::next, and ast_cdr::varshead.
00405 { 00406 00407 /* clear variables */ 00408 for (; cdr; cdr = recur ? cdr->next : NULL) { 00409 struct ast_var_t *vardata; 00410 struct varshead *headp = &cdr->varshead; 00411 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 00412 ast_var_delete(vardata); 00413 } 00414 }
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 219 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.
00220 { 00221 const char *fmt = "%Y-%m-%d %T"; 00222 const char *varbuf; 00223 00224 if (!cdr) /* don't die if the cdr is null */ 00225 return; 00226 00227 *ret = NULL; 00228 /* special vars (the ones from the struct ast_cdr when requested by name) 00229 I'd almost say we should convert all the stringed vals to vars */ 00230 00231 if (!strcasecmp(name, "clid")) 00232 ast_copy_string(workspace, cdr->clid, workspacelen); 00233 else if (!strcasecmp(name, "src")) 00234 ast_copy_string(workspace, cdr->src, workspacelen); 00235 else if (!strcasecmp(name, "dst")) 00236 ast_copy_string(workspace, cdr->dst, workspacelen); 00237 else if (!strcasecmp(name, "dcontext")) 00238 ast_copy_string(workspace, cdr->dcontext, workspacelen); 00239 else if (!strcasecmp(name, "channel")) 00240 ast_copy_string(workspace, cdr->channel, workspacelen); 00241 else if (!strcasecmp(name, "dstchannel")) 00242 ast_copy_string(workspace, cdr->dstchannel, workspacelen); 00243 else if (!strcasecmp(name, "lastapp")) 00244 ast_copy_string(workspace, cdr->lastapp, workspacelen); 00245 else if (!strcasecmp(name, "lastdata")) 00246 ast_copy_string(workspace, cdr->lastdata, workspacelen); 00247 else if (!strcasecmp(name, "start")) 00248 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen); 00249 else if (!strcasecmp(name, "answer")) 00250 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen); 00251 else if (!strcasecmp(name, "end")) 00252 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen); 00253 else if (!strcasecmp(name, "duration")) 00254 snprintf(workspace, workspacelen, "%ld", cdr->duration); 00255 else if (!strcasecmp(name, "billsec")) 00256 snprintf(workspace, workspacelen, "%ld", cdr->billsec); 00257 else if (!strcasecmp(name, "disposition")) { 00258 if (raw) { 00259 snprintf(workspace, workspacelen, "%ld", cdr->disposition); 00260 } else { 00261 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); 00262 } 00263 } else if (!strcasecmp(name, "amaflags")) { 00264 if (raw) { 00265 snprintf(workspace, workspacelen, "%ld", cdr->amaflags); 00266 } else { 00267 ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); 00268 } 00269 } else if (!strcasecmp(name, "accountcode")) 00270 ast_copy_string(workspace, cdr->accountcode, workspacelen); 00271 else if (!strcasecmp(name, "uniqueid")) 00272 ast_copy_string(workspace, cdr->uniqueid, workspacelen); 00273 else if (!strcasecmp(name, "userfield")) 00274 ast_copy_string(workspace, cdr->userfield, workspacelen); 00275 else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) 00276 ast_copy_string(workspace, varbuf, workspacelen); 00277 else 00278 workspace[0] = '\0'; 00279 00280 if (!ast_strlen_zero(workspace)) 00281 *ret = workspace; 00282 }
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 822 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_NULL, ast_log(), AST_STATE_UP, ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, LOG_WARNING, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, S_OR, set_one_cid(), and ast_cdr::uniqueid.
00823 { 00824 char *chan; 00825 00826 for ( ; cdr ; cdr = cdr->next) { 00827 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00828 chan = S_OR(cdr->channel, "<unknown>"); 00829 if (!ast_strlen_zero(cdr->channel)) 00830 ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan); 00831 ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); 00832 set_one_cid(cdr, c); 00833 00834 cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NULL; 00835 cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; 00836 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00837 /* Destination information */ 00838 ast_copy_string(cdr->dst, S_OR(c->macroexten,c->exten), sizeof(cdr->dst)); 00839 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext,c->context), sizeof(cdr->dcontext)); 00840 /* Unique call identifier */ 00841 ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid)); 00842 } 00843 } 00844 return 0; 00845 }
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 500 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_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, 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::src, ast_cdr::start, and ast_cdr::userfield.
00501 { 00502 struct ast_cdr *zcdr; 00503 struct ast_cdr *lto = NULL; 00504 struct ast_cdr *lfrom = NULL; 00505 int discard_from = 0; 00506 00507 if (!to || !from) 00508 return; 00509 00510 /* don't merge into locked CDR's -- it's bad business */ 00511 if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { 00512 zcdr = to; /* safety valve? */ 00513 while (to->next) { 00514 lto = to; 00515 to = to->next; 00516 } 00517 00518 if (ast_test_flag(to, AST_CDR_FLAG_LOCKED)) { 00519 ast_log(LOG_WARNING, "Merging into locked CDR... no choice."); 00520 to = zcdr; /* safety-- if all there are is locked CDR's, then.... ?? */ 00521 lto = NULL; 00522 } 00523 } 00524 00525 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) { 00526 discard_from = 1; 00527 if (lto) { 00528 struct ast_cdr *llfrom = NULL; 00529 /* insert the from stuff after lto */ 00530 lto->next = from; 00531 lfrom = from; 00532 while (lfrom && lfrom->next) { 00533 if (!lfrom->next->next) 00534 llfrom = lfrom; 00535 lfrom = lfrom->next; 00536 } 00537 /* rip off the last entry and put a copy of the to at the end */ 00538 llfrom->next = to; 00539 from = lfrom; 00540 } else { 00541 /* save copy of the current *to cdr */ 00542 struct ast_cdr tcdr; 00543 struct ast_cdr *llfrom = NULL; 00544 memcpy(&tcdr, to, sizeof(tcdr)); 00545 /* copy in the locked from cdr */ 00546 memcpy(to, from, sizeof(*to)); 00547 lfrom = from; 00548 while (lfrom && lfrom->next) { 00549 if (!lfrom->next->next) 00550 llfrom = lfrom; 00551 lfrom = lfrom->next; 00552 } 00553 from->next = NULL; 00554 /* rip off the last entry and put a copy of the to at the end */ 00555 if (llfrom == from) 00556 to = to->next = ast_cdr_dup(&tcdr); 00557 else 00558 to = llfrom->next = ast_cdr_dup(&tcdr); 00559 from = lfrom; 00560 } 00561 } 00562 00563 if (!ast_tvzero(from->start)) { 00564 if (!ast_tvzero(to->start)) { 00565 if (ast_tvcmp(to->start, from->start) > 0 ) { 00566 to->start = from->start; /* use the earliest time */ 00567 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00568 } 00569 /* else nothing to do */ 00570 } else { 00571 to->start = from->start; 00572 from->start = ast_tv(0,0); /* we actively "steal" these values */ 00573 } 00574 } 00575 if (!ast_tvzero(from->answer)) { 00576 if (!ast_tvzero(to->answer)) { 00577 if (ast_tvcmp(to->answer, from->answer) > 0 ) { 00578 to->answer = from->answer; /* use the earliest time */ 00579 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00580 } 00581 /* we got the earliest answer time, so we'll settle for that? */ 00582 } else { 00583 to->answer = from->answer; 00584 from->answer = ast_tv(0,0); /* we actively "steal" these values */ 00585 } 00586 } 00587 if (!ast_tvzero(from->end)) { 00588 if (!ast_tvzero(to->end)) { 00589 if (ast_tvcmp(to->end, from->end) < 0 ) { 00590 to->end = from->end; /* use the latest time */ 00591 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00592 to->duration = to->end.tv_sec - to->start.tv_sec; /* don't forget to update the duration, billsec, when we set end */ 00593 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00594 } 00595 /* else, nothing to do */ 00596 } else { 00597 to->end = from->end; 00598 from->end = ast_tv(0,0); /* we actively "steal" these values */ 00599 to->duration = to->end.tv_sec - to->start.tv_sec; 00600 to->billsec = ast_tvzero(to->answer) ? 0 : to->end.tv_sec - to->answer.tv_sec; 00601 } 00602 } 00603 if (to->disposition < from->disposition) { 00604 to->disposition = from->disposition; 00605 from->disposition = AST_CDR_NOANSWER; 00606 } 00607 if (ast_strlen_zero(to->lastapp) && !ast_strlen_zero(from->lastapp)) { 00608 ast_copy_string(to->lastapp, from->lastapp, sizeof(to->lastapp)); 00609 from->lastapp[0] = 0; /* theft */ 00610 } 00611 if (ast_strlen_zero(to->lastdata) && !ast_strlen_zero(from->lastdata)) { 00612 ast_copy_string(to->lastdata, from->lastdata, sizeof(to->lastdata)); 00613 from->lastdata[0] = 0; /* theft */ 00614 } 00615 if (ast_strlen_zero(to->dcontext) && !ast_strlen_zero(from->dcontext)) { 00616 ast_copy_string(to->dcontext, from->dcontext, sizeof(to->dcontext)); 00617 from->dcontext[0] = 0; /* theft */ 00618 } 00619 if (ast_strlen_zero(to->dstchannel) && !ast_strlen_zero(from->dstchannel)) { 00620 ast_copy_string(to->dstchannel, from->dstchannel, sizeof(to->dstchannel)); 00621 from->dstchannel[0] = 0; /* theft */ 00622 } 00623 if (!ast_strlen_zero(from->channel) && (ast_strlen_zero(to->channel) || !strncasecmp(from->channel, "Agent/", 6))) { 00624 ast_copy_string(to->channel, from->channel, sizeof(to->channel)); 00625 from->channel[0] = 0; /* theft */ 00626 } 00627 if (ast_strlen_zero(to->src) && !ast_strlen_zero(from->src)) { 00628 ast_copy_string(to->src, from->src, sizeof(to->src)); 00629 from->src[0] = 0; /* theft */ 00630 } 00631 if (ast_strlen_zero(to->clid) && !ast_strlen_zero(from->clid)) { 00632 ast_copy_string(to->clid, from->clid, sizeof(to->clid)); 00633 from->clid[0] = 0; /* theft */ 00634 } 00635 if (ast_strlen_zero(to->dst) && !ast_strlen_zero(from->dst)) { 00636 ast_copy_string(to->dst, from->dst, sizeof(to->dst)); 00637 from->dst[0] = 0; /* theft */ 00638 } 00639 if (!to->amaflags) 00640 to->amaflags = AST_CDR_DOCUMENTATION; 00641 if (!from->amaflags) 00642 from->amaflags = AST_CDR_DOCUMENTATION; /* make sure both amaflags are set to something (DOC is default) */ 00643 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (to->amaflags == AST_CDR_DOCUMENTATION && from->amaflags != AST_CDR_DOCUMENTATION)) { 00644 to->amaflags = from->amaflags; 00645 } 00646 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->accountcode) && !ast_strlen_zero(from->accountcode))) { 00647 ast_copy_string(to->accountcode, from->accountcode, sizeof(to->accountcode)); 00648 } 00649 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED) || (ast_strlen_zero(to->userfield) && !ast_strlen_zero(from->userfield))) { 00650 ast_copy_string(to->userfield, from->userfield, sizeof(to->userfield)); 00651 } 00652 /* flags, varsead, ? */ 00653 cdr_merge_vars(from, to); 00654 00655 if (ast_test_flag(from, AST_CDR_FLAG_KEEP_VARS)) 00656 ast_set_flag(to, AST_CDR_FLAG_KEEP_VARS); 00657 if (ast_test_flag(from, AST_CDR_FLAG_POSTED)) 00658 ast_set_flag(to, AST_CDR_FLAG_POSTED); 00659 if (ast_test_flag(from, AST_CDR_FLAG_LOCKED)) 00660 ast_set_flag(to, AST_CDR_FLAG_LOCKED); 00661 if (ast_test_flag(from, AST_CDR_FLAG_CHILD)) 00662 ast_set_flag(to, AST_CDR_FLAG_CHILD); 00663 if (ast_test_flag(from, AST_CDR_FLAG_POST_DISABLED)) 00664 ast_set_flag(to, AST_CDR_FLAG_POST_DISABLED); 00665 00666 /* last, but not least, we need to merge any forked CDRs to the 'to' cdr */ 00667 while (from->next) { 00668 /* just rip 'em off the 'from' and insert them on the 'to' */ 00669 zcdr = from->next; 00670 from->next = zcdr->next; 00671 zcdr->next = NULL; 00672 /* zcdr is now ripped from the current list; */ 00673 ast_cdr_append(to, zcdr); 00674 } 00675 if (discard_from) 00676 ast_cdr_discard(from); 00677 }
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" |
Definition at line 727 of file cdr.c.
References AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, AST_CDR_NOANSWER, ast_log(), ast_strlen_zero(), ast_test_flag, ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::next.
00728 { 00729 char *chan; 00730 00731 while (cdr) { 00732 chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>"; 00733 if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED)) 00734 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan); 00735 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00736 if (cdr->disposition < AST_CDR_NOANSWER) 00737 cdr->disposition = AST_CDR_NOANSWER; 00738 } 00739 cdr = cdr->next; 00740 } 00741 }
int ast_cdr_register | ( | const char * | name, | |
const char * | desc, | |||
ast_cdrbe | be | |||
) |
Register a CDR handling engine
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. Returns -1 on error, 0 on success. |
Definition at line 108 of file cdr.c.
References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_cdr_beitem::be, ast_cdr_beitem::desc, LOG_WARNING, and ast_cdr_beitem::name.
00109 { 00110 struct ast_cdr_beitem *i; 00111 00112 if (!name) 00113 return -1; 00114 if (!be) { 00115 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name); 00116 return -1; 00117 } 00118 00119 AST_LIST_LOCK(&be_list); 00120 AST_LIST_TRAVERSE(&be_list, i, list) { 00121 if (!strcasecmp(name, i->name)) 00122 break; 00123 } 00124 AST_LIST_UNLOCK(&be_list); 00125 00126 if (i) { 00127 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name); 00128 return -1; 00129 } 00130 00131 if (!(i = ast_calloc(1, sizeof(*i)))) 00132 return -1; 00133 00134 i->be = be; 00135 ast_copy_string(i->name, name, sizeof(i->name)); 00136 ast_copy_string(i->desc, desc, sizeof(i->desc)); 00137 00138 AST_LIST_LOCK(&be_list); 00139 AST_LIST_INSERT_HEAD(&be_list, i, list); 00140 AST_LIST_UNLOCK(&be_list); 00141 00142 return 0; 00143 }
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 1003 of file cdr.c.
References ast_cdr::answer, ast_cdr_detach(), ast_cdr_dup(), ast_cdr_end(), AST_CDR_FLAG_KEEP_VARS, AST_CDR_FLAG_LOCKED, AST_CDR_FLAG_POSTED, ast_cdr_free_vars(), AST_CDR_NULL, ast_cdr_start(), ast_clear_flag, ast_copy_flags, AST_FLAGS_ALL, ast_set_flag, ast_test_flag, ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, ast_cdr::next, and ast_cdr::start.
01004 { 01005 struct ast_cdr *dup; 01006 struct ast_flags flags = { 0 }; 01007 01008 if (_flags) 01009 ast_copy_flags(&flags, _flags, AST_FLAGS_ALL); 01010 01011 for ( ; cdr ; cdr = cdr->next) { 01012 /* Detach if post is requested */ 01013 if (ast_test_flag(&flags, AST_CDR_FLAG_LOCKED) || !ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 01014 if (ast_test_flag(&flags, AST_CDR_FLAG_POSTED)) { 01015 ast_cdr_end(cdr); 01016 if ((dup = ast_cdr_dup(cdr))) { 01017 ast_cdr_detach(dup); 01018 } 01019 ast_set_flag(cdr, AST_CDR_FLAG_POSTED); 01020 } 01021 01022 /* clear variables */ 01023 if (!ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) { 01024 ast_cdr_free_vars(cdr, 0); 01025 } 01026 01027 /* Reset to initial state */ 01028 ast_clear_flag(cdr, AST_FLAGS_ALL); 01029 memset(&cdr->start, 0, sizeof(cdr->start)); 01030 memset(&cdr->end, 0, sizeof(cdr->end)); 01031 memset(&cdr->answer, 0, sizeof(cdr->answer)); 01032 cdr->billsec = 0; 01033 cdr->duration = 0; 01034 ast_cdr_start(cdr); 01035 cdr->disposition = AST_CDR_NULL; 01036 } 01037 } 01038 }
int ast_cdr_serialize_variables | ( | struct ast_cdr * | cdr, | |
char * | buf, | |||
size_t | size, | |||
char | delim, | |||
char | sep, | |||
int | recur | |||
) |
Definition at line 360 of file cdr.c.
References ast_build_string(), ast_cdr_getvar(), AST_LIST_TRAVERSE, ast_log(), ast_strlen_zero(), ast_var_name(), ast_var_value(), cdr_readonly_vars, LOG_ERROR, ast_cdr::next, total, var, and ast_cdr::varshead.
00361 { 00362 struct ast_var_t *variables; 00363 const char *var, *val; 00364 char *tmp; 00365 char workspace[256]; 00366 int total = 0, x = 0, i; 00367 00368 memset(buf, 0, size); 00369 00370 for (; cdr; cdr = recur ? cdr->next : NULL) { 00371 if (++x > 1) 00372 ast_build_string(&buf, &size, "\n"); 00373 00374 AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) { 00375 if (variables && 00376 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00377 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00378 if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, var, delim, val, sep)) { 00379 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00380 break; 00381 } else 00382 total++; 00383 } else 00384 break; 00385 } 00386 00387 for (i = 0; cdr_readonly_vars[i]; i++) { 00388 ast_cdr_getvar(cdr, cdr_readonly_vars[i], &tmp, workspace, sizeof(workspace), 0, 0); 00389 if (!tmp) 00390 continue; 00391 00392 if (ast_build_string(&buf, &size, "level %d: %s%c%s%c", x, cdr_readonly_vars[i], delim, tmp, sep)) { 00393 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n"); 00394 break; 00395 } else 00396 total++; 00397 } 00398 } 00399 00400 return total; 00401 }
int ast_cdr_setaccount | ( | struct ast_channel * | chan, | |
const char * | account | |||
) |
Definition at line 893 of file cdr.c.
References ast_cdr::accountcode, accountcode, AST_CDR_FLAG_LOCKED, ast_string_field_set, ast_test_flag, ast_channel::cdr, and ast_cdr::next.
00894 { 00895 struct ast_cdr *cdr = chan->cdr; 00896 00897 ast_string_field_set(chan, accountcode, account); 00898 for ( ; cdr ; cdr = cdr->next) { 00899 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00900 ast_copy_string(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode)); 00901 } 00902 } 00903 return 0; 00904 }
int ast_cdr_setamaflags | ( | struct ast_channel * | chan, | |
const char * | amaflags | |||
) |
Definition at line 906 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.
00907 { 00908 struct ast_cdr *cdr; 00909 int newflag = ast_cdr_amaflags2int(flag); 00910 if (newflag) { 00911 for (cdr = chan->cdr; cdr; cdr = cdr->next) { 00912 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00913 cdr->amaflags = newflag; 00914 } 00915 } 00916 } 00917 00918 return 0; 00919 }
void ast_cdr_setapp | ( | struct ast_cdr * | cdr, | |
char * | app, | |||
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 777 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::lastapp, ast_cdr::lastdata, and ast_cdr::next.
00778 { 00779 00780 for (; cdr; cdr = cdr->next) { 00781 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00782 check_post(cdr); 00783 if (!app) 00784 app = ""; 00785 ast_copy_string(cdr->lastapp, app, sizeof(cdr->lastapp)); 00786 if (!data) 00787 data = ""; 00788 ast_copy_string(cdr->lastdata, data, sizeof(cdr->lastdata)); 00789 } 00790 } 00791 }
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 Return is negligible. (returns 0 by default) |
Definition at line 813 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_cdr::next, and set_one_cid().
00814 { 00815 for (; cdr; cdr = cdr->next) { 00816 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00817 set_one_cid(cdr, c); 00818 } 00819 return 0; 00820 }
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 768 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::dstchannel, and ast_cdr::next.
00769 { 00770 for (; cdr; cdr = cdr->next) { 00771 check_post(cdr); 00772 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00773 ast_copy_string(cdr->dstchannel, chann, sizeof(cdr->dstchannel)); 00774 } 00775 }
int ast_cdr_setuserfield | ( | struct ast_channel * | chan, | |
const char * | userfield | |||
) |
Definition at line 921 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, ast_cdr::next, and ast_cdr::userfield.
00922 { 00923 struct ast_cdr *cdr = chan->cdr; 00924 00925 for ( ; cdr ; cdr = cdr->next) { 00926 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00927 ast_copy_string(cdr->userfield, userfield, sizeof(cdr->userfield)); 00928 } 00929 00930 return 0; 00931 }
int ast_cdr_setvar | ( | struct ast_cdr * | cdr, | |
const char * | name, | |||
const char * | value, | |||
int | recur | |||
) |
Set a CDR channel variable
Definition at line 292 of file cdr.c.
References AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_var_assign(), ast_var_delete(), ast_var_name(), cdr_readonly_vars, LOG_ERROR, ast_cdr::next, and ast_cdr::varshead.
00293 { 00294 struct ast_var_t *newvariable; 00295 struct varshead *headp; 00296 int x; 00297 00298 if (!cdr) /* don't die if the cdr is null */ 00299 return -1; 00300 00301 for(x = 0; cdr_readonly_vars[x]; x++) { 00302 if (!strcasecmp(name, cdr_readonly_vars[x])) { 00303 ast_log(LOG_ERROR, "Attempt to set the '%s' read-only variable!.\n", name); 00304 return -1; 00305 } 00306 } 00307 00308 if (!cdr) { 00309 ast_log(LOG_ERROR, "Attempt to set a variable on a nonexistent CDR record.\n"); 00310 return -1; 00311 } 00312 00313 for (; cdr; cdr = recur ? cdr->next : NULL) { 00314 headp = &cdr->varshead; 00315 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) { 00316 if (!strcasecmp(ast_var_name(newvariable), name)) { 00317 /* there is already such a variable, delete it */ 00318 AST_LIST_REMOVE_CURRENT(headp, entries); 00319 ast_var_delete(newvariable); 00320 break; 00321 } 00322 } 00323 AST_LIST_TRAVERSE_SAFE_END; 00324 00325 if (value) { 00326 newvariable = ast_var_assign(name, value); 00327 AST_LIST_INSERT_HEAD(headp, newvariable, entries); 00328 } 00329 } 00330 00331 return 0; 00332 }
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 679 of file cdr.c.
References AST_CDR_FLAG_LOCKED, ast_test_flag, ast_cdr::channel, check_post(), ast_cdr::next, S_OR, and ast_cdr::start.
00680 { 00681 char *chan; 00682 00683 for (; cdr; cdr = cdr->next) { 00684 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00685 chan = S_OR(cdr->channel, "<unknown>"); 00686 check_post(cdr); 00687 cdr->start = ast_tvnow(); 00688 } 00689 } 00690 }
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 1094 of file cdr.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, batch, batchscheduleronly, do_batch_backend_process(), ast_cdr_batch::head, LOG_DEBUG, LOG_WARNING, option_debug, and reset_batch().
01095 { 01096 struct ast_cdr_batch_item *oldbatchitems = NULL; 01097 pthread_attr_t attr; 01098 pthread_t batch_post_thread = AST_PTHREADT_NULL; 01099 01100 /* if there's no batch, or no CDRs in the batch, then there's nothing to do */ 01101 if (!batch || !batch->head) 01102 return; 01103 01104 /* move the old CDRs aside, and prepare a new CDR batch */ 01105 ast_mutex_lock(&cdr_batch_lock); 01106 oldbatchitems = batch->head; 01107 reset_batch(); 01108 ast_mutex_unlock(&cdr_batch_lock); 01109 01110 /* if configured, spawn a new thread to post these CDRs, 01111 also try to save as much as possible if we are shutting down safely */ 01112 if (batchscheduleronly || shutdown) { 01113 if (option_debug) 01114 ast_log(LOG_DEBUG, "CDR single-threaded batch processing begins now\n"); 01115 do_batch_backend_process(oldbatchitems); 01116 } else { 01117 pthread_attr_init(&attr); 01118 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01119 if (ast_pthread_create_background(&batch_post_thread, &attr, do_batch_backend_process, oldbatchitems)) { 01120 ast_log(LOG_WARNING, "CDR processing thread could not detach, now trying in this thread\n"); 01121 do_batch_backend_process(oldbatchitems); 01122 } else { 01123 if (option_debug) 01124 ast_log(LOG_DEBUG, "CDR multi-threaded batch processing begins now\n"); 01125 } 01126 pthread_attr_destroy(&attr); 01127 } 01128 }
void ast_cdr_unregister | ( | const char * | name | ) |
Unregister a CDR handling engine
name | name of CDR handler to unregister Unregisters a CDR by it's name |
Definition at line 146 of file cdr.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), free, ast_cdr_beitem::name, option_verbose, and VERBOSE_PREFIX_2.
00147 { 00148 struct ast_cdr_beitem *i = NULL; 00149 00150 AST_LIST_LOCK(&be_list); 00151 AST_LIST_TRAVERSE_SAFE_BEGIN(&be_list, i, list) { 00152 if (!strcasecmp(name, i->name)) { 00153 AST_LIST_REMOVE_CURRENT(&be_list, list); 00154 if (option_verbose > 1) 00155 ast_verbose(VERBOSE_PREFIX_2 "Unregistered '%s' CDR backend\n", name); 00156 free(i); 00157 break; 00158 } 00159 } 00160 AST_LIST_TRAVERSE_SAFE_END; 00161 AST_LIST_UNLOCK(&be_list); 00162 }
int ast_cdr_update | ( | struct ast_channel * | chan | ) |
Definition at line 947 of file cdr.c.
References ast_cdr::accountcode, AST_CDR_FLAG_LOCKED, ast_test_flag, ast_channel::cdr, ast_channel::context, ast_cdr::dcontext, ast_cdr::dst, ast_channel::exten, ast_channel::macrocontext, ast_channel::macroexten, ast_cdr::next, S_OR, and set_one_cid().
00948 { 00949 struct ast_cdr *cdr = c->cdr; 00950 00951 for ( ; cdr ; cdr = cdr->next) { 00952 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00953 set_one_cid(cdr, c); 00954 00955 /* Copy account code et-al */ 00956 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00957 00958 /* Destination information */ /* XXX privilege macro* ? */ 00959 ast_copy_string(cdr->dst, S_OR(c->macroexten, c->exten), sizeof(cdr->dst)); 00960 ast_copy_string(cdr->dcontext, S_OR(c->macrocontext, c->context), sizeof(cdr->dcontext)); 00961 } 00962 } 00963 00964 return 0; 00965 }
char ast_default_accountcode[AST_MAX_ACCOUNT_CODE] |