![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
cdr.c File Reference
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.
#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) |
| 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_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, struct ast_str **buf, 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_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 | check_post (struct ast_cdr *cdr) |
| print a warning if cdr already posted | |
| static void | check_start (struct ast_cdr *cdr) |
| print a warning if cdr already started | |
| 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 (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 |
|
|
Definition at line 89 of file cdr.c. Referenced by do_reload(). |
|
|
Definition at line 88 of file cdr.c. Referenced by do_reload(). |
|
|
Definition at line 86 of file cdr.c. Referenced by do_reload(). |
|
|
Definition at line 87 of file cdr.c. Referenced by do_reload(). |
|
|
Allocate a CDR record Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure).
Definition at line 437 of file cdr.c. References ast_calloc. Referenced by __agent_start_monitoring(), __ast_pbx_run(), __ast_request_and_dial(), ast_cdr_dup(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), ast_pbx_outgoing_exten(), and start_monitor_exec(). 00438 { 00439 return ast_calloc(1, sizeof(struct ast_cdr)); 00440 }
|
|
|
Definition at line 707 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(), and set_config(). 00708 { 00709 if (!strcasecmp(flag, "default")) 00710 return 0; 00711 if (!strcasecmp(flag, "omit")) 00712 return AST_CDR_OMIT; 00713 if (!strcasecmp(flag, "billing")) 00714 return AST_CDR_BILLING; 00715 if (!strcasecmp(flag, "documentation")) 00716 return AST_CDR_DOCUMENTATION; 00717 return -1; 00718 }
|
|
|
Definition at line 456 of file cdr.c. References ast_cdr::answer, AST_CDR_ANSWERED, check_post(), ast_cdr::disposition, and ast_cdr::next. Referenced by __ast_answer(), and __ast_read(). 00457 { 00458 00459 for (; cdr; cdr = cdr->next) { 00460 check_post(cdr); 00461 if (cdr->disposition < AST_CDR_ANSWERED) 00462 cdr->disposition = AST_CDR_ANSWERED; 00463 if (ast_tvzero(cdr->answer)) 00464 cdr->answer = ast_tvnow(); 00465 } 00466 }
|
|
||||||||||||
|
Definition at line 778 of file cdr.c. References ast_cdr::next. Referenced by attempt_transfer(). 00779 { 00780 struct ast_cdr *ret; 00781 00782 if (cdr) { 00783 ret = cdr; 00784 00785 while (cdr->next) 00786 cdr = cdr->next; 00787 cdr->next = newcdr; 00788 } else { 00789 ret = newcdr; 00790 } 00791 00792 return ret; 00793 }
|
|
||||||||||||
|
Definition at line 674 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 ast_bridge_call(). 00675 { 00676 struct ast_cdr *cdr = chan->cdr; 00677 00678 for ( ; cdr ; cdr = cdr->next) { 00679 int len = strlen(cdr->userfield); 00680 00681 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) 00682 ast_copy_string(cdr->userfield + len, userfield, sizeof(cdr->userfield) - len); 00683 } 00684 00685 return 0; 00686 }
|
|
|
Definition at line 468 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(). 00469 { 00470 00471 for (; cdr; cdr = cdr->next) { 00472 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00473 check_post(cdr); 00474 if (cdr->disposition < AST_CDR_BUSY) 00475 cdr->disposition = AST_CDR_BUSY; 00476 } 00477 } 00478 }
|
|
||||||||||||
|
Definition at line 324 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(). 00325 { 00326 struct ast_var_t *variables, *newvariable = NULL; 00327 struct varshead *headpa, *headpb; 00328 const char *var, *val; 00329 int x = 0; 00330 00331 headpa = &from_cdr->varshead; 00332 headpb = &to_cdr->varshead; 00333 00334 AST_LIST_TRAVERSE(headpa,variables,entries) { 00335 if (variables && 00336 (var = ast_var_name(variables)) && (val = ast_var_value(variables)) && 00337 !ast_strlen_zero(var) && !ast_strlen_zero(val)) { 00338 newvariable = ast_var_assign(var, val); 00339 AST_LIST_INSERT_HEAD(headpb, newvariable, entries); 00340 x++; 00341 } 00342 } 00343 00344 return x; 00345 }
|
|
|
Definition at line 890 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_cdr_reset(), ast_hangup(), and ast_pbx_outgoing_cdr_failed(). 00891 { 00892 struct ast_cdr_batch_item *newtail; 00893 int curr; 00894 00895 /* maybe they disabled CDR stuff completely, so just drop it */ 00896 if (!enabled) { 00897 if (option_debug) 00898 ast_log(LOG_DEBUG, "Dropping CDR !\n"); 00899 ast_set_flag(cdr, AST_CDR_FLAG_POST_DISABLED); 00900 ast_cdr_free(cdr); 00901 return; 00902 } 00903 00904 /* post stuff immediately if we are not in batch mode, this is legacy behaviour */ 00905 if (!batchmode) { 00906 post_cdr(cdr); 00907 ast_cdr_free(cdr); 00908 return; 00909 } 00910 00911 /* otherwise, each CDR gets put into a batch list (at the end) */ 00912 if (option_debug) 00913 ast_log(LOG_DEBUG, "CDR detaching from this thread\n"); 00914 00915 /* we'll need a new tail for every CDR */ 00916 if (!(newtail = ast_calloc(1, sizeof(*newtail)))) { 00917 post_cdr(cdr); 00918 ast_cdr_free(cdr); 00919 return; 00920 } 00921 00922 /* don't traverse a whole list (just keep track of the tail) */ 00923 ast_mutex_lock(&cdr_batch_lock); 00924 if (!batch) 00925 init_batch(); 00926 if (!batch->head) { 00927 /* new batch is empty, so point the head at the new tail */ 00928 batch->head = newtail; 00929 } else { 00930 /* already got a batch with something in it, so just append a new tail */ 00931 batch->tail->next = newtail; 00932 } 00933 newtail->cdr = cdr; 00934 batch->tail = newtail; 00935 curr = batch->size++; 00936 ast_mutex_unlock(&cdr_batch_lock); 00937 00938 /* if we have enough stuff to post, then do it */ 00939 if (curr >= (batchsize - 1)) 00940 submit_unscheduled_batch(); 00941 }
|
|
|
Definition at line 609 of file cdr.c. References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, and AST_CDR_NOANSWER. Referenced by ast_cdr_getvar(). 00610 { 00611 switch (disposition) { 00612 case AST_CDR_NOANSWER: 00613 return "NO ANSWER"; 00614 case AST_CDR_FAILED: 00615 return "FAILED"; 00616 case AST_CDR_BUSY: 00617 return "BUSY"; 00618 case AST_CDR_ANSWERED: 00619 return "ANSWERED"; 00620 } 00621 return "UNKNOWN"; 00622 }
|
|
||||||||||||
|
Definition at line 491 of file cdr.c. References AST_CAUSE_BUSY, AST_CAUSE_FAILURE, AST_CAUSE_NORMAL, AST_CAUSE_NOTDEFINED, ast_cdr_busy(), ast_cdr_failed(), ast_log(), LOG_WARNING, and ast_cdr::next. Referenced by __ast_request_and_dial(), ast_pbx_outgoing_app(), and ast_pbx_outgoing_exten(). 00492 { 00493 int res = 0; 00494 00495 for (; cdr; cdr = cdr->next) { 00496 switch (cause) { 00497 case AST_CAUSE_BUSY: 00498 ast_cdr_busy(cdr); 00499 break; 00500 case AST_CAUSE_FAILURE: 00501 ast_cdr_failed(cdr); 00502 break; 00503 case AST_CAUSE_NORMAL: 00504 break; 00505 case AST_CAUSE_NOTDEFINED: 00506 res = -1; 00507 break; 00508 default: 00509 res = -1; 00510 ast_log(LOG_WARNING, "Cause not handled\n"); 00511 } 00512 } 00513 return res; 00514 }
|
|
|
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(), and ast_cdr_copy_vars(). Referenced by ast_cdr_reset(). 00168 { 00169 struct ast_cdr *newcdr = ast_cdr_alloc(); 00170 00171 if (!newcdr) 00172 return NULL; 00173 00174 memcpy(newcdr, cdr, sizeof(*newcdr)); 00175 /* The varshead is unusable, volatile even, after the memcpy so we take care of that here */ 00176 memset(&newcdr->varshead, 0, sizeof(newcdr->varshead)); 00177 ast_cdr_copy_vars(newcdr, cdr); 00178 newcdr->next = NULL; 00179 00180 return newcdr; 00181 }
|
|
|
Definition at line 594 of file cdr.c. References AST_CDR_FAILED, ast_log(), ast_cdr::channel, check_post(), ast_cdr::disposition, ast_cdr::end, LOG_WARNING, ast_cdr::next, S_OR, and ast_cdr::start. Referenced by __ast_read(), __ast_request_and_dial(), ast_cdr_reset(), ast_hangup(), and ast_pbx_outgoing_cdr_failed(). 00595 { 00596 for ( ; cdr ; cdr = cdr->next) { 00597 check_post(cdr); 00598 if (ast_tvzero(cdr->end)) 00599 cdr->end = ast_tvnow(); 00600 if (ast_tvzero(cdr->start)) { 00601 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", S_OR(cdr->channel, "<unknown>")); 00602 cdr->disposition = AST_CDR_FAILED; 00603 } else 00604 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec; 00605 cdr->billsec = ast_tvzero(cdr->answer) ? 0 : cdr->end.tv_sec - cdr->answer.tv_sec; 00606 } 00607 }
|
|
|
Load the configuration file cdr.conf and possibly start the CDR scheduling thread Definition at line 1141 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(). 01142 { 01143 int res; 01144 01145 sched = sched_context_create(); 01146 if (!sched) { 01147 ast_log(LOG_ERROR, "Unable to create schedule context.\n"); 01148 return -1; 01149 } 01150 01151 ast_cli_register(&cli_status); 01152 01153 res = do_reload(); 01154 if (res) { 01155 ast_mutex_lock(&cdr_batch_lock); 01156 res = init_batch(); 01157 ast_mutex_unlock(&cdr_batch_lock); 01158 } 01159 01160 return res; 01161 }
|
|
|
Reload the configuration file cdr.conf and start/stop CDR scheduling thread Definition at line 1170 of file cdr.c. References do_reload(). 01171 { 01172 return do_reload(); 01173 }
|
|
|
Submit any remaining CDRs and prepare for shutdown Definition at line 1165 of file cdr.c. References ast_cdr_submit_batch(), and batchsafeshutdown. Referenced by do_reload(), and quit_handler(). 01166 { 01167 ast_cdr_submit_batch(batchsafeshutdown); 01168 }
|
|
|
Definition at line 480 of file cdr.c. References AST_CDR_FAILED, AST_CDR_FLAG_LOCKED, ast_test_flag, check_post(), ast_cdr::disposition, and ast_cdr::next. Referenced by __ast_request_and_dial(), ast_cdr_disposition(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), and ast_pbx_outgoing_exten(). 00481 { 00482 for (; cdr; cdr = cdr->next) { 00483 check_post(cdr); 00484 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00485 if (cdr->disposition < AST_CDR_FAILED) 00486 cdr->disposition = AST_CDR_FAILED; 00487 } 00488 } 00489 }
|
|
|
Converts AMA flag to printable string Definition at line 625 of file cdr.c. References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT. Referenced by _sip_show_device(), _sip_show_peer(), ast_cdr_getvar(), and sip_show_user(). 00626 { 00627 switch (flag) { 00628 case AST_CDR_OMIT: 00629 return "OMIT"; 00630 case AST_CDR_BILLING: 00631 return "BILLING"; 00632 case AST_CDR_DOCUMENTATION: 00633 return "DOCUMENTATION"; 00634 } 00635 return "Unknown"; 00636 }
|
|
|
Free a CDR record.
Definition at line 418 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. Referenced by ast_cdr_detach(), and do_batch_backend_process(). 00419 { 00420 00421 while (cdr) { 00422 struct ast_cdr *next = cdr->next; 00423 char *chan = S_OR(cdr->channel, "<unknown>"); 00424 if (!ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED)) 00425 ast_log(LOG_NOTICE, "CDR on channel '%s' not posted\n", chan); 00426 if (ast_tvzero(cdr->end)) 00427 ast_log(LOG_NOTICE, "CDR on channel '%s' lacks end\n", chan); 00428 if (ast_tvzero(cdr->start)) 00429 ast_log(LOG_NOTICE, "CDR on channel '%s' lacks start\n", chan); 00430 00431 ast_cdr_free_vars(cdr, 0); 00432 free(cdr); 00433 cdr = next; 00434 } 00435 }
|
|
||||||||||||
|
Definition at line 392 of file cdr.c. References AST_LIST_REMOVE_HEAD, ast_var_delete(), ast_cdr::next, and ast_cdr::varshead. Referenced by ast_cdr_free(). 00393 { 00394 00395 /* clear variables */ 00396 for (; cdr; cdr = recur ? cdr->next : NULL) { 00397 struct ast_var_t *vardata; 00398 struct varshead *headp = &cdr->varshead; 00399 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries))) 00400 ast_var_delete(vardata); 00401 } 00402 }
|
|
||||||||||||||||||||||||||||||||
|
CDR channel variable retrieval Definition at line 215 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(). 00216 { 00217 const char *fmt = "%Y-%m-%d %T"; 00218 const char *varbuf; 00219 00220 *ret = NULL; 00221 /* special vars (the ones from the struct ast_cdr when requested by name) 00222 I'd almost say we should convert all the stringed vals to vars */ 00223 00224 if (!strcasecmp(name, "clid")) 00225 ast_copy_string(workspace, cdr->clid, workspacelen); 00226 else if (!strcasecmp(name, "src")) 00227 ast_copy_string(workspace, cdr->src, workspacelen); 00228 else if (!strcasecmp(name, "dst")) 00229 ast_copy_string(workspace, cdr->dst, workspacelen); 00230 else if (!strcasecmp(name, "dcontext")) 00231 ast_copy_string(workspace, cdr->dcontext, workspacelen); 00232 else if (!strcasecmp(name, "channel")) 00233 ast_copy_string(workspace, cdr->channel, workspacelen); 00234 else if (!strcasecmp(name, "dstchannel")) 00235 ast_copy_string(workspace, cdr->dstchannel, workspacelen); 00236 else if (!strcasecmp(name, "lastapp")) 00237 ast_copy_string(workspace, cdr->lastapp, workspacelen); 00238 else if (!strcasecmp(name, "lastdata")) 00239 ast_copy_string(workspace, cdr->lastdata, workspacelen); 00240 else if (!strcasecmp(name, "start")) 00241 cdr_get_tv(cdr->start, raw ? NULL : fmt, workspace, workspacelen); 00242 else if (!strcasecmp(name, "answer")) 00243 cdr_get_tv(cdr->answer, raw ? NULL : fmt, workspace, workspacelen); 00244 else if (!strcasecmp(name, "end")) 00245 cdr_get_tv(cdr->end, raw ? NULL : fmt, workspace, workspacelen); 00246 else if (!strcasecmp(name, "duration")) 00247 snprintf(workspace, workspacelen, "%ld", cdr->duration); 00248 else if (!strcasecmp(name, "billsec")) 00249 snprintf(workspace, workspacelen, "%ld", cdr->billsec); 00250 else if (!strcasecmp(name, "disposition")) { 00251 if (raw) { 00252 snprintf(workspace, workspacelen, "%ld", cdr->disposition); 00253 } else { 00254 ast_copy_string(workspace, ast_cdr_disp2str(cdr->disposition), workspacelen); 00255 } 00256 } else if (!strcasecmp(name, "amaflags")) { 00257 if (raw) { 00258 snprintf(workspace, workspacelen, "%ld", cdr->amaflags); 00259 } else { 00260 ast_copy_string(workspace, ast_cdr_flags2str(cdr->amaflags), workspacelen); 00261 } 00262 } else if (!strcasecmp(name, "accountcode")) 00263 ast_copy_string(workspace, cdr->accountcode, workspacelen); 00264 else if (!strcasecmp(name, "uniqueid")) 00265 ast_copy_string(workspace, cdr->uniqueid, workspacelen); 00266 else if (!strcasecmp(name, "userfield")) 00267 ast_copy_string(workspace, cdr->userfield, workspacelen); 00268 else if ((varbuf = ast_cdr_getvar_internal(cdr, name, recur))) 00269 ast_copy_string(workspace, varbuf, workspacelen); 00270 else 00271 workspace[0] = '\0'; 00272 00273 if (!ast_strlen_zero(workspace)) 00274 *ret = workspace; 00275 }
|
|
||||||||||||||||
|
Definition at line 183 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(). 00184 { 00185 if (ast_strlen_zero(name)) 00186 return NULL; 00187 00188 for (; cdr; cdr = recur ? cdr->next : NULL) { 00189 struct ast_var_t *variables; 00190 struct varshead *headp = &cdr->varshead; 00191 AST_LIST_TRAVERSE(headp, variables, entries) { 00192 if (!strcasecmp(name, ast_var_name(variables))) 00193 return ast_var_value(variables); 00194 } 00195 } 00196 00197 return NULL; 00198 }
|
|
||||||||||||
|
Initialize based on a channel.
Definition at line 569 of file cdr.c. References ast_channel::_state, ast_cdr::accountcode, ast_cdr::amaflags, ast_channel::amaflags, AST_CDR_ANSWERED, AST_CDR_FLAG_LOCKED, AST_CDR_NOANSWER, ast_default_amaflags, 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_cdr::next, S_OR, set_one_cid(), and ast_cdr::uniqueid. Referenced by __ast_pbx_run(), __ast_request_and_dial(), ast_pbx_outgoing_app(), ast_pbx_outgoing_cdr_failed(), and ast_pbx_outgoing_exten(). 00570 { 00571 char *chan; 00572 00573 for ( ; cdr ; cdr = cdr->next) { 00574 if (!ast_test_flag(cdr, AST_CDR_FLAG_LOCKED)) { 00575 chan = S_OR(cdr->channel, "<unknown>"); 00576 if (!ast_strlen_zero(cdr->channel)) 00577 ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan); 00578 ast_copy_string(cdr->channel, c->name, sizeof(cdr->channel)); 00579 set_one_cid(cdr, c); 00580 00581 cdr->disposition = (c->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 00582 cdr->amaflags = c->amaflags ? c->amaflags : ast_default_amaflags; 00583 ast_copy_string(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode)); 00584 /* Destination information */ 00585 ast_copy_string(cdr->dst, c->exten, sizeof(cdr->dst)); 00586 ast_copy_string(cdr->dcontext, c->context, sizeof(cdr->dcontext)); 00587 /* Unique call identifier */ 00588 ast_copy_string(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid)); 00589 } 00590 } 00591 return 0; 00592 }
|
|
||||||||||||||||
|
Register a CDR driver. Each registered CDR driver generates a CDR
|