#include <asterisk/channel.h>#include <sys/time.h>Go to the source code of this file.
Data Structures | |
| struct | ast_cdr |
| Responsible for call detail data. More... | |
Defines | |
| #define | AST_CDR_NOANSWER (1 << 0) |
| #define | AST_CDR_BUSY (1 << 1) |
| #define | AST_CDR_ANSWERED (1 << 2) |
| #define | AST_CDR_FAILED (1 << 3) |
| #define | AST_CDR_OMIT (1) |
| AMA Flags. | |
| #define | AST_CDR_BILLING (2) |
| #define | AST_CDR_DOCUMENTATION (3) |
| #define | AST_MAX_USER_FIELD 256 |
Typedefs | |
| typedef int(* | ast_cdrbe )(struct ast_cdr *cdr) |
Functions | |
| ast_cdr * | ast_cdr_alloc (void) |
| Allocate a record. | |
| void | ast_cdr_free (struct ast_cdr *cdr) |
| Free a record. | |
| int | ast_cdr_init (struct ast_cdr *cdr, struct ast_channel *chan) |
| Initialize based on a channel. | |
| int | ast_cdr_setcid (struct ast_cdr *cdr, struct ast_channel *chan) |
| Initialize based on a channel. | |
| int | ast_cdr_register (char *name, char *desc, ast_cdrbe be) |
| Register a CDR handling engine. | |
| void | ast_cdr_unregister (char *name) |
| Unregister a CDR handling engine. | |
| void | ast_cdr_start (struct ast_cdr *cdr) |
| Start a call. | |
| void | ast_cdr_answer (struct ast_cdr *cdr) |
| Answer a call. | |
| void | ast_cdr_busy (struct ast_cdr *cdr) |
| Busy a call. | |
| void | ast_cdr_failed (struct ast_cdr *cdr) |
| Fail a call. | |
| int | ast_cdr_disposition (struct ast_cdr *cdr, int cause) |
| Save the result of the call based on the AST_CAUSE_*. | |
| void | ast_cdr_end (struct ast_cdr *cdr) |
| End a call. | |
| void | ast_cdr_post (struct ast_cdr *cdr) |
| Post the detail record. | |
| void | ast_cdr_setdestchan (struct ast_cdr *cdr, char *chan) |
| Set the destination channel, if there was one. | |
| void | ast_cdr_setapp (struct ast_cdr *cdr, char *app, char *data) |
| Set the last executed application. | |
| int | ast_cdr_amaflags2int (char *flag) |
| Convert a string to a detail record AMA flag. | |
| char * | ast_cdr_disp2str (int disposition) |
| Disposition to a string. | |
| void | ast_cdr_reset (struct ast_cdr *cdr, int post) |
| Reset the detail record, optionally posting it first. | |
| char * | ast_cdr_flags2str (int flags) |
| Flags to a string. | |
| int | ast_cdr_setaccount (struct ast_channel *chan, char *account) |
| int | ast_cdr_setuserfield (struct ast_channel *chan, char *userfield) |
| int | ast_cdr_appenduserfield (struct ast_channel *chan, char *userfield) |
| int | ast_cdr_update (struct ast_channel *chan) |
Variables | |
| int | ast_default_amaflags |
| char | ast_default_accountcode [20] |
|
|
Definition at line 25 of file cdr.h. Referenced by ast_cdr_answer(), ast_cdr_disp2str(), and ast_cdr_init(). |
|
|
Definition at line 30 of file cdr.h. Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str(). |
|
|
Definition at line 24 of file cdr.h. Referenced by ast_cdr_busy(), and ast_cdr_disp2str(). |
|
|
Definition at line 31 of file cdr.h. Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str(). |
|
|
Definition at line 26 of file cdr.h. Referenced by ast_cdr_disp2str(), and ast_cdr_failed(). |
|
|
Definition at line 23 of file cdr.h. Referenced by ast_cdr_disp2str(), ast_cdr_init(), and ast_cdr_reset(). |
|
|
AMA Flags.
Definition at line 29 of file cdr.h. Referenced by ast_cdr_amaflags2int(), and ast_cdr_flags2str(). |
|
|
|
|
|
Definition at line 79 of file cdr.h. Referenced by ast_cdr_register(). |
|
|
Allocate a record. Returns a malloc'd ast_cdr structure, returns NULL on error (malloc failure) Definition at line 117 of file cdr.c. References malloc. Referenced by __ast_request_and_dial(), and ast_pbx_run().
|
|
|
Convert a string to a detail record AMA flag.
Definition at line 400 of file cdr.c. References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
00401 {
00402 if (!strcasecmp(flag, "default"))
00403 return 0;
00404 if (!strcasecmp(flag, "omit"))
00405 return AST_CDR_OMIT;
00406 if (!strcasecmp(flag, "billing"))
00407 return AST_CDR_BILLING;
00408 if (!strcasecmp(flag, "documentation"))
00409 return AST_CDR_DOCUMENTATION;
00410 return -1;
00411 }
|
|
|
Answer a call.
Definition at line 140 of file cdr.c. References ast_cdr::answer, AST_CDR_ANSWERED, ast_log(), ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::posted. Referenced by ast_answer(), and ast_read().
00141 {
00142 char *chan;
00143 if (cdr) {
00144 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00145 if (cdr->posted)
00146 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00147 if (cdr->disposition < AST_CDR_ANSWERED)
00148 cdr->disposition = AST_CDR_ANSWERED;
00149 if (!cdr->answer.tv_sec && !cdr->answer.tv_usec) {
00150 gettimeofday(&cdr->answer, NULL);
00151 }
00152 }
00153 }
|
|
||||||||||||
|
Definition at line 357 of file cdr.c. References ast_channel::cdr.
|
|
|
Busy a call.
Definition at line 155 of file cdr.c. References AST_CDR_BUSY, ast_log(), ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::posted. Referenced by ast_cdr_disposition().
00156 {
00157 char *chan;
00158 if (cdr) {
00159 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00160 if (cdr->posted)
00161 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00162 if (cdr->disposition < AST_CDR_BUSY)
00163 cdr->disposition = AST_CDR_BUSY;
00164 }
00165 }
|
|
|
Disposition to a string.
Definition at line 309 of file cdr.c. References AST_CDR_ANSWERED, AST_CDR_BUSY, AST_CDR_FAILED, and AST_CDR_NOANSWER.
00310 {
00311 switch (disposition) {
00312 case AST_CDR_NOANSWER:
00313 return "NO ANSWER";
00314 case AST_CDR_FAILED:
00315 return "FAILED";
00316 case AST_CDR_BUSY:
00317 return "BUSY";
00318 case AST_CDR_ANSWERED:
00319 return "ANSWERED";
00320 default:
00321 return "UNKNOWN";
00322 }
00323 }
|
|
||||||||||||
|
Save the result of the call based on the AST_CAUSE_*.
Definition at line 178 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(), and LOG_WARNING. Referenced by __ast_request_and_dial().
00179 {
00180 int res = 0;
00181 if (cdr) {
00182 switch(cause) {
00183 case AST_CAUSE_BUSY:
00184 ast_cdr_busy(cdr);
00185 break;
00186 case AST_CAUSE_FAILURE:
00187 ast_cdr_failed(cdr);
00188 break;
00189 case AST_CAUSE_NORMAL:
00190 break;
00191 case AST_CAUSE_NOTDEFINED:
00192 res = -1;
00193 break;
00194 default:
00195 res = -1;
00196 ast_log(LOG_WARNING, "We don't handle that cause yet\n");
00197 }
00198 }
00199 return res;
00200 }
|
|
|
End a call.
Definition at line 295 of file cdr.c. References ast_log(), ast_cdr::channel, ast_cdr::end, LOG_WARNING, ast_cdr::posted, and ast_cdr::start. Referenced by __ast_request_and_dial(), ast_cdr_reset(), ast_hangup(), and ast_read().
00296 {
00297 char *chan;
00298 if (cdr) {
00299 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00300 if (cdr->posted)
00301 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00302 if (!cdr->start.tv_sec && !cdr->start.tv_usec)
00303 ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", chan);
00304 if (!cdr->end.tv_sec && !cdr->end.tv_usec)
00305 gettimeofday(&cdr->end, NULL);
00306 }
00307 }
|
|
|
Fail a call.
Definition at line 167 of file cdr.c. References AST_CDR_FAILED, ast_log(), ast_cdr::channel, ast_cdr::disposition, LOG_WARNING, and ast_cdr::posted. Referenced by __ast_request_and_dial(), and ast_cdr_disposition().
00168 {
00169 char *chan;
00170 if (cdr) {
00171 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00172 if (cdr->posted)
00173 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00174 cdr->disposition = AST_CDR_FAILED;
00175 }
00176 }
|
|
|
Flags to a string.
Definition at line 325 of file cdr.c. References AST_CDR_BILLING, AST_CDR_DOCUMENTATION, and AST_CDR_OMIT.
00326 {
00327 switch(flag) {
00328 case AST_CDR_OMIT:
00329 return "OMIT";
00330 case AST_CDR_BILLING:
00331 return "BILLING";
00332 case AST_CDR_DOCUMENTATION:
00333 return "DOCUMENTATION";
00334 }
00335 return "Unknown";
00336 }
|
|
|
Free a record.
Definition at line 102 of file cdr.c. References ast_log(), ast_cdr::channel, ast_cdr::end, free, LOG_WARNING, ast_cdr::posted, and ast_cdr::start. Referenced by ast_hangup().
00103 {
00104 char *chan;
00105 if (cdr) {
00106 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00107 if (!cdr->posted)
00108 ast_log(LOG_WARNING, "CDR on channel '%s' not posted\n", chan);
00109 if (!cdr->end.tv_sec && !cdr->end.tv_usec)
00110 ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
00111 if (!cdr->start.tv_sec && !cdr->start.tv_usec)
00112 ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
00113 free(cdr);
00114 }
00115 }
|
|
||||||||||||
|
Initialize based on a channel.
Definition at line 252 of file cdr.c. References ast_channel::_state, ast_channel::accountcode, ast_cdr::accountcode, ast_cdr::amaflags, ast_channel::amaflags, ast_channel::ani, ast_callerid_parse(), AST_CDR_ANSWERED, AST_CDR_NOANSWER, ast_default_amaflags, ast_log(), AST_MAX_EXTENSION, ast_shrink_phone_number(), AST_STATE_UP, ast_channel::callerid, ast_cdr::channel, ast_cdr::clid, ast_channel::context, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_channel::exten, LOG_WARNING, ast_channel::name, ast_cdr::src, ast_channel::uniqueid, and ast_cdr::uniqueid. Referenced by __ast_request_and_dial(), and ast_pbx_run().
00253 {
00254 char *chan;
00255 char *num, *name;
00256 char tmp[AST_MAX_EXTENSION] = "";
00257 if (cdr) {
00258 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00259 if (strlen(cdr->channel))
00260 ast_log(LOG_WARNING, "CDR already initialized on '%s'\n", chan);
00261 strncpy(cdr->channel, c->name, sizeof(cdr->channel) - 1);
00262 /* Grab source from ANI or normal Caller*ID */
00263 if (c->ani)
00264 strncpy(tmp, c->ani, sizeof(tmp) - 1);
00265 else if (c->callerid)
00266 strncpy(tmp, c->callerid, sizeof(tmp) - 1);
00267 if (c->callerid)
00268 strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
00269 name = NULL;
00270 num = NULL;
00271 ast_callerid_parse(tmp, &name, &num);
00272 if (num) {
00273 ast_shrink_phone_number(num);
00274 strncpy(cdr->src, num, sizeof(cdr->src) - 1);
00275 }
00276
00277 if (c->_state == AST_STATE_UP)
00278 cdr->disposition = AST_CDR_ANSWERED;
00279 else
00280 cdr->disposition = AST_CDR_NOANSWER;
00281 if (c->amaflags)
00282 cdr->amaflags = c->amaflags;
00283 else
00284 cdr->amaflags = ast_default_amaflags;
00285 strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
00286 /* Destination information */
00287 strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
00288 strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
00289 /* Unique call identifier */
00290 strncpy(cdr->uniqueid, c->uniqueid, sizeof(cdr->uniqueid) - 1);
00291 }
00292 return 0;
00293 }
|
|
|
Post the detail record.
Definition at line 413 of file cdr.c. References ast_cdr::answer, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_cdr::billsec, ast_cdr::channel, ast_cdr::duration, ast_cdr::end, LOG_WARNING, ast_cdr::posted, and ast_cdr::start. Referenced by ast_cdr_reset(), and ast_hangup().
00414 {
00415 char *chan;
00416 struct ast_cdr_beitem *i;
00417 if (cdr) {
00418 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00419 if (cdr->posted)
00420 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00421 if (!cdr->end.tv_sec && !cdr->end.tv_usec)
00422 ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
00423 if (!cdr->start.tv_sec && !cdr->start.tv_usec)
00424 ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
00425 cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec + (cdr->end.tv_usec - cdr->start.tv_usec) / 1000000;
00426 if (cdr->answer.tv_sec || cdr->answer.tv_usec) {
00427 cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec + (cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000;
00428 } else
00429 cdr->billsec = 0;
00430 cdr->posted = 1;
00431 ast_mutex_lock(&cdrlock);
00432 i = bes;
00433 while(i) {
00434 i->be(cdr);
00435 i = i->next;
00436 }
00437 ast_mutex_unlock(&cdrlock);
00438 }
00439 }
|
|
||||||||||||||||
|
Register a CDR handling engine.
Definition at line 47 of file cdr.c. References ast_cdrbe, ast_log(), ast_mutex_lock, ast_mutex_unlock, LOG_WARNING, and malloc.
00048 {
00049 struct ast_cdr_beitem *i;
00050 if (!name)
00051 return -1;
00052 if (!be) {
00053 ast_log(LOG_WARNING, "CDR engine '%s' lacks backend\n", name);
00054 return -1;
00055 }
00056 ast_mutex_lock(&cdrlock);
00057 i = bes;
00058 while(i) {
00059 if (!strcasecmp(name, i->name))
00060 break;
00061 i = i->next;
00062 }
00063 ast_mutex_unlock(&cdrlock);
00064 if (i) {
00065 ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
00066 return -1;
00067 }
00068 i = malloc(sizeof(struct ast_cdr_beitem));
00069 if (!i)
00070 return -1;
00071 memset(i, 0, sizeof(struct ast_cdr_beitem));
00072 strncpy(i->name, name, sizeof(i->name) - 1);
00073 strncpy(i->desc, desc, sizeof(i->desc) - 1);
00074 i->be = be;
00075 ast_mutex_lock(&cdrlock);
00076 i->next = bes;
00077 bes = i;
00078 ast_mutex_unlock(&cdrlock);
00079 return 0;
00080 }
|
|
||||||||||||
|
Reset the detail record, optionally posting it first.
Definition at line 441 of file cdr.c. References ast_cdr::answer, ast_cdr_end(), AST_CDR_NOANSWER, ast_cdr_post(), ast_cdr_start(), ast_cdr::billsec, ast_cdr::disposition, ast_cdr::duration, ast_cdr::end, ast_cdr::posted, and ast_cdr::start.
00442 {
00443 if (cdr) {
00444 /* Post if requested */
00445 if (post) {
00446 ast_cdr_end(cdr);
00447 ast_cdr_post(cdr);
00448 }
00449 /* Reset to initial state */
00450 cdr->posted = 0;
00451 memset(&cdr->start, 0, sizeof(cdr->start));
00452 memset(&cdr->end, 0, sizeof(cdr->end));
00453 memset(&cdr->answer, 0, sizeof(cdr->answer));
00454 cdr->billsec = 0;
00455 cdr->duration = 0;
00456 ast_cdr_start(cdr);
00457 cdr->disposition = AST_CDR_NOANSWER;
00458 }
00459 }
|
|
||||||||||||
|
Definition at line 338 of file cdr.c. References ast_channel::accountcode, and ast_channel::cdr. Referenced by __ast_request_and_dial().
00339 {
00340 struct ast_cdr *cdr = chan->cdr;
00341
00342 strncpy(chan->accountcode, account, sizeof(chan->accountcode) - 1);
00343 if (cdr)
00344 strncpy(cdr->accountcode, chan->accountcode, sizeof(cdr->accountcode) - 1);
00345 return 0;
00346 }
|
|
||||||||||||||||
|
Set the last executed application.
Definition at line 213 of file cdr.c. References ast_log(), ast_cdr::channel, ast_cdr::lastapp, ast_cdr::lastdata, LOG_WARNING, and ast_cdr::posted. Referenced by __ast_request_and_dial(), and pbx_exec().
00214 {
00215 char *chan;
00216 if (cdr) {
00217 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00218 if (cdr->posted)
00219 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00220 if (!app)
00221 app = "";
00222 strncpy(cdr->lastapp, app, sizeof(cdr->lastapp) - 1);
00223 if (!data)
00224 data = "";
00225 strncpy(cdr->lastdata, data, sizeof(cdr->lastdata) - 1);
00226 }
00227 }
|
|
||||||||||||
|
Initialize based on a channel.
Definition at line 229 of file cdr.c. References ast_channel::ani, ast_callerid_parse(), AST_MAX_EXTENSION, ast_shrink_phone_number(), ast_channel::callerid, ast_cdr::clid, and ast_cdr::src. Referenced by ast_set_callerid().
00230 {
00231 char tmp[AST_MAX_EXTENSION] = "";
00232 char *num, *name;
00233 if (cdr) {
00234 /* Grab source from ANI or normal Caller*ID */
00235 if (c->ani)
00236 strncpy(tmp, c->ani, sizeof(tmp) - 1);
00237 else if (c->callerid)
00238 strncpy(tmp, c->callerid, sizeof(tmp) - 1);
00239 if (c->callerid)
00240 strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
00241 name = NULL;
00242 num = NULL;
00243 ast_callerid_parse(tmp, &name, &num);
00244 if (num) {
00245 ast_shrink_phone_number(num);
00246 strncpy(cdr->src, num, sizeof(cdr->src) - 1);
00247 }
00248 }
00249 return 0;
00250 }
|
|
||||||||||||
|
Set the destination channel, if there was one.
Definition at line 202 of file cdr.c. References ast_log(), ast_cdr::channel, ast_cdr::dstchannel, LOG_WARNING, and ast_cdr::posted.
00203 {
00204 char *chan;
00205 if (cdr) {
00206 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00207 if (cdr->posted)
00208 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00209 strncpy(cdr->dstchannel, chann, sizeof(cdr->dstchannel) - 1);
00210 }
00211 }
|
|
||||||||||||
|
Definition at line 348 of file cdr.c. References ast_channel::cdr.
|
|
|
Start a call.
Definition at line 127 of file cdr.c. References ast_log(), ast_cdr::channel, LOG_WARNING, ast_cdr::posted, and ast_cdr::start. Referenced by __ast_request_and_dial(), ast_cdr_reset(), and ast_pbx_run().
00128 {
00129 char *chan;
00130 if (cdr) {
00131 chan = strlen(cdr->channel) ? cdr->channel : "<unknown>";
00132 if (cdr->posted)
00133 ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
00134 if (cdr->start.tv_sec || cdr->start.tv_usec)
00135 ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan);
00136 gettimeofday(&cdr->start, NULL);
00137 }
00138 }
|
|
|
Unregister a CDR handling engine.
Definition at line 82 of file cdr.c. References ast_mutex_lock, ast_mutex_unlock, and free.
00083 {
00084 struct ast_cdr_beitem *i, *prev = NULL;
00085 ast_mutex_lock(&cdrlock);
00086 i = bes;
00087 while(i) {
00088 if (!strcasecmp(name, i->name)) {
00089 if (prev)
00090 prev->next = i->next;
00091 else
00092 bes = i->next;
00093 break;
00094 }
00095 i = i->next;
00096 }
00097 ast_mutex_unlock(&cdrlock);
00098 if (i)
00099 free(i);
00100 }
|
|
|
Definition at line 369 of file cdr.c. References ast_channel::accountcode, ast_channel::ani, ast_callerid_parse(), AST_MAX_EXTENSION, ast_shrink_phone_number(), ast_channel::callerid, ast_channel::cdr, ast_channel::context, and ast_channel::exten. Referenced by __ast_request_and_dial(), and ast_pbx_run().
00370 {
00371 struct ast_cdr *cdr = c->cdr;
00372 char *name, *num;
00373 char tmp[AST_MAX_EXTENSION] = "";
00374 /* Grab source from ANI or normal Caller*ID */
00375 if (cdr) {
00376 if (c->ani)
00377 strncpy(tmp, c->ani, sizeof(tmp) - 1);
00378 else if (c->callerid && strlen(c->callerid))
00379 strncpy(tmp, c->callerid, sizeof(tmp) - 1);
00380 if (c->callerid && strlen(c->callerid))
00381 strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
00382 else
00383 strcpy(cdr->clid, "");
00384 name = NULL;
00385 num = NULL;
00386 ast_callerid_parse(tmp, &name, &num);
00387 if (num) {
00388 ast_shrink_phone_number(num);
00389 strncpy(cdr->src, num, sizeof(cdr->src) - 1);
00390 }
00391 /* Copy account code et-al */
00392 strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
00393 /* Destination information */
00394 strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
00395 strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
00396 }
00397 return 0;
00398 }
|
|
|
Definition at line 243 of file cdr.h. Referenced by ast_channel_alloc(). |
|
|
Definition at line 241 of file cdr.h. Referenced by ast_cdr_init(), and ast_channel_alloc(). |
1.3.5