diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/app_authenticate.c | 8 | ||||
-rw-r--r-- | apps/app_cdr.c | 105 | ||||
-rw-r--r-- | apps/app_dial.c | 76 | ||||
-rw-r--r-- | apps/app_disa.c | 8 | ||||
-rw-r--r-- | apps/app_dumpchan.c | 13 | ||||
-rw-r--r-- | apps/app_followme.c | 46 | ||||
-rw-r--r-- | apps/app_forkcdr.c | 222 | ||||
-rw-r--r-- | apps/app_osplookup.c | 23 | ||||
-rw-r--r-- | apps/app_queue.c | 127 |
9 files changed, 209 insertions, 419 deletions
diff --git a/apps/app_authenticate.c b/apps/app_authenticate.c index fbb430089..a8370588b 100644 --- a/apps/app_authenticate.c +++ b/apps/app_authenticate.c @@ -213,9 +213,9 @@ static int auth_exec(struct ast_channel *chan, const char *data) continue; ast_md5_hash(md5passwd, passwd); if (!strcmp(md5passwd, md5secret)) { - if (ast_test_flag(&flags,OPT_ACCOUNT)) { + if (ast_test_flag(&flags, OPT_ACCOUNT)) { ast_channel_lock(chan); - ast_cdr_setaccount(chan, buf); + ast_channel_accountcode_set(chan, buf); ast_channel_unlock(chan); } break; @@ -224,7 +224,7 @@ static int auth_exec(struct ast_channel *chan, const char *data) if (!strcmp(passwd, buf)) { if (ast_test_flag(&flags, OPT_ACCOUNT)) { ast_channel_lock(chan); - ast_cdr_setaccount(chan, buf); + ast_channel_accountcode_set(chan, buf); ast_channel_unlock(chan); } break; @@ -250,7 +250,7 @@ static int auth_exec(struct ast_channel *chan, const char *data) if ((retries < 3) && !res) { if (ast_test_flag(&flags,OPT_ACCOUNT) && !ast_test_flag(&flags,OPT_MULTIPLE)) { ast_channel_lock(chan); - ast_cdr_setaccount(chan, passwd); + ast_channel_accountcode_set(chan, passwd); ast_channel_unlock(chan); } if (!(res = ast_streamfile(chan, "auth-thankyou", ast_channel_language(chan)))) diff --git a/apps/app_cdr.c b/apps/app_cdr.c index 3c244712b..ba7139cf1 100644 --- a/apps/app_cdr.c +++ b/apps/app_cdr.c @@ -35,25 +35,114 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/channel.h" #include "asterisk/module.h" +#include "asterisk/app.h" /*** DOCUMENTATION <application name="NoCDR" language="en_US"> <synopsis> - Tell Asterisk to not maintain a CDR for the current call + Tell Asterisk to not maintain a CDR for this channel. </synopsis> <syntax /> <description> - <para>This application will tell Asterisk not to maintain a CDR for the current call.</para> + <para>This application will tell Asterisk not to maintain a CDR for + the current channel. This does <emphasis>NOT</emphasis> mean that + information is not tracked; rather, if the channel is hung up no + CDRs will be created for that channel.</para> + <para>If a subsequent call to ResetCDR occurs, all non-finalized + CDRs created for the channel will be enabled.</para> + <note><para>This application is deprecated. Please use the CDR_PROP + function to disable CDRs on a channel.</para></note> </description> + <see-also> + <ref type="application">ResetCDR</ref> + <ref type="function">CDR_PROP</ref> + </see-also> + </application> + <application name="ResetCDR" language="en_US"> + <synopsis> + Resets the Call Data Record. + </synopsis> + <syntax> + <parameter name="options"> + <optionlist> + <option name="v"> + <para>Save the CDR variables during the reset.</para> + </option> + <option name="e"> + <para>Enable the CDRs for this channel only (negate + effects of NoCDR).</para> + </option> + </optionlist> + </parameter> + </syntax> + <description> + <para>This application causes the Call Data Record to be reset. + Depending on the flags passed in, this can have several effects. + With no options, a reset does the following:</para> + <para>1. The <literal>start</literal> time is set to the current time.</para> + <para>2. If the channel is answered, the <literal>answer</literal> time is set to the + current time.</para> + <para>3. All variables are wiped from the CDR. Note that this step + can be prevented with the <literal>v</literal> option.</para> + <para>On the other hand, if the <literal>e</literal> option is + specified, the effects of the NoCDR application will be lifted. CDRs + will be re-enabled for this channel.</para> + <note><para>The <literal>e</literal> option is deprecated. Please + use the CDR_PROP function instead.</para></note> + </description> + <see-also> + <ref type="application">ForkCDR</ref> + <ref type="application">NoCDR</ref> + <ref type="function">CDR_PROP</ref> + </see-also> </application> ***/ static const char nocdr_app[] = "NoCDR"; +static const char resetcdr_app[] = "ResetCDR"; + +enum reset_cdr_options { + OPT_DISABLE_DISPATCH = (1 << 0), + OPT_KEEP_VARS = (1 << 1), + OPT_ENABLE = (1 << 2), +}; + +AST_APP_OPTIONS(resetcdr_opts, { + AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS), + AST_APP_OPTION('e', AST_CDR_FLAG_DISABLE_ALL), +}); + +static int resetcdr_exec(struct ast_channel *chan, const char *data) +{ + char *args; + struct ast_flags flags = { 0 }; + int res = 0; + + if (!ast_strlen_zero(data)) { + args = ast_strdupa(data); + ast_app_parse_options(resetcdr_opts, &flags, NULL, args); + } + + if (ast_test_flag(&flags, AST_CDR_FLAG_DISABLE_ALL)) { + if (ast_cdr_clear_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE_ALL)) { + res = 1; + } + } + if (ast_cdr_reset(ast_channel_name(chan), &flags)) { + res = 1; + } + + if (res) { + ast_log(AST_LOG_WARNING, "Failed to reset CDR for channel %s\n", ast_channel_name(chan)); + } + return res; +} static int nocdr_exec(struct ast_channel *chan, const char *data) { - if (ast_channel_cdr(chan)) - ast_set_flag(ast_channel_cdr(chan), AST_CDR_FLAG_POST_DISABLED); + if (ast_cdr_set_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE_ALL)) { + ast_log(AST_LOG_WARNING, "Failed to disable CDR for channel %s\n", ast_channel_name(chan)); + } return 0; } @@ -65,8 +154,14 @@ static int unload_module(void) static int load_module(void) { - if (ast_register_application_xml(nocdr_app, nocdr_exec)) + int res = 0; + + res |= ast_register_application_xml(nocdr_app, nocdr_exec); + res |= ast_register_application_xml(resetcdr_app, resetcdr_exec); + + if (res) { return AST_MODULE_LOAD_FAILURE; + } return AST_MODULE_LOAD_SUCCESS; } diff --git a/apps/app_dial.c b/apps/app_dial.c index b0caa5c6b..c75eb2d3a 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -55,7 +55,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/app.h" #include "asterisk/causes.h" #include "asterisk/rtp_engine.h" -#include "asterisk/cdr.h" #include "asterisk/manager.h" #include "asterisk/privacy.h" #include "asterisk/stringfields.h" @@ -753,36 +752,20 @@ struct cause_args { static void handle_cause(int cause, struct cause_args *num) { - struct ast_cdr *cdr = ast_channel_cdr(num->chan); - switch(cause) { case AST_CAUSE_BUSY: - if (cdr) - ast_cdr_busy(cdr); num->busy++; break; - case AST_CAUSE_CONGESTION: - if (cdr) - ast_cdr_failed(cdr); num->congestion++; break; - case AST_CAUSE_NO_ROUTE_DESTINATION: case AST_CAUSE_UNREGISTERED: - if (cdr) - ast_cdr_failed(cdr); num->nochan++; break; - case AST_CAUSE_NO_ANSWER: - if (cdr) { - ast_cdr_noanswer(cdr); - } - break; case AST_CAUSE_NORMAL_CLEARING: break; - default: num->nochan++; break; @@ -974,7 +957,7 @@ static void do_forward(struct chanlist *o, struct cause_args *num, ast_channel_appl_set(c, "AppDial"); ast_channel_data_set(c, "(Outgoing Line)"); - ast_publish_channel_state(c); + ast_channel_publish_snapshot(c); ast_channel_unlock(in); if (single && !ast_test_flag64(o, OPT_IGNORE_CONNECTEDLINE)) { @@ -1096,7 +1079,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, */ *to = -1; strcpy(pa->status, "CONGESTION"); - ast_cdr_failed(ast_channel_cdr(in)); ast_channel_publish_dial(in, outgoing->chan, NULL, pa->status); return NULL; } @@ -1301,10 +1283,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, peer = c; ast_channel_publish_dial(in, peer, NULL, "ANSWER"); publish_dial_end_event(in, out_chans, peer, "CANCEL"); - if (ast_channel_cdr(peer)) { - ast_channel_cdr(peer)->answer = ast_tvnow(); - ast_channel_cdr(peer)->disposition = AST_CDR_ANSWERED; - } ast_copy_flags64(peerflags, o, OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP | @@ -1326,7 +1304,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, case AST_CONTROL_BUSY: ast_verb(3, "%s is busy\n", ast_channel_name(c)); ast_channel_hangupcause_set(in, ast_channel_hangupcause(c)); - ast_channel_publish_dial(in, c, NULL, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(c))); + ast_channel_publish_dial(in, c, NULL, "BUSY"); ast_hangup(c); c = o->chan = NULL; ast_clear_flag64(o, DIAL_STILLGOING); @@ -1335,7 +1313,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, case AST_CONTROL_CONGESTION: ast_verb(3, "%s is circuit-busy\n", ast_channel_name(c)); ast_channel_hangupcause_set(in, ast_channel_hangupcause(c)); - ast_channel_publish_dial(in, c, NULL, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(c))); + ast_channel_publish_dial(in, c, NULL, "CONGESTION"); ast_hangup(c); c = o->chan = NULL; ast_clear_flag64(o, DIAL_STILLGOING); @@ -1542,7 +1520,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, /* Got hung up */ *to = -1; strcpy(pa->status, "CANCEL"); - ast_cdr_noanswer(ast_channel_cdr(in)); publish_dial_end_event(in, out_chans, NULL, pa->status); if (f) { if (f->data.uint32) { @@ -1565,7 +1542,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, if (onedigit_goto(in, context, (char) f->subclass.integer, 1)) { ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer); *to = 0; - ast_cdr_noanswer(ast_channel_cdr(in)); *result = f->subclass.integer; strcpy(pa->status, "CANCEL"); publish_dial_end_event(in, out_chans, NULL, pa->status); @@ -1584,7 +1560,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, ast_verb(3, "User requested call disconnect.\n"); *to = 0; strcpy(pa->status, "CANCEL"); - ast_cdr_noanswer(ast_channel_cdr(in)); publish_dial_end_event(in, out_chans, NULL, pa->status); ast_frfree(f); if (is_cc_recall) { @@ -1679,13 +1654,10 @@ skip_frame:; } } - if (!*to) { + if (!*to || ast_check_hangup(in)) { ast_verb(3, "Nobody picked up in %d ms\n", orig); publish_dial_end_event(in, out_chans, NULL, "NOANSWER"); } - if (!*to || ast_check_hangup(in)) { - ast_cdr_noanswer(ast_channel_cdr(in)); - } #ifdef HAVE_EPOLL AST_LIST_TRAVERSE(out_chans, epollo, node) { @@ -1985,22 +1957,13 @@ static void end_bridge_callback(void *data) time_t end; struct ast_channel *chan = data; - if (!ast_channel_cdr(chan)) { - return; - } - time(&end); ast_channel_lock(chan); - if (ast_channel_cdr(chan)->answer.tv_sec) { - snprintf(buf, sizeof(buf), "%ld", (long) end - ast_channel_cdr(chan)->answer.tv_sec); - pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); - } - - if (ast_channel_cdr(chan)->start.tv_sec) { - snprintf(buf, sizeof(buf), "%ld", (long) end - ast_channel_cdr(chan)->start.tv_sec); - pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); - } + snprintf(buf, sizeof(buf), "%d", ast_channel_get_up_time(chan)); + pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); + snprintf(buf, sizeof(buf), "%d", ast_channel_get_duration(chan)); + pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); ast_channel_unlock(chan); } @@ -2294,8 +2257,9 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast ast_channel_unlock(chan); } - if (ast_test_flag64(&opts, OPT_RESETCDR) && ast_channel_cdr(chan)) - ast_cdr_reset(ast_channel_cdr(chan), NULL); + if (ast_test_flag64(&opts, OPT_RESETCDR)) { + ast_cdr_reset(ast_channel_name(chan), 0); + } if (ast_test_flag64(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY])) opt_args[OPT_ARG_PRIVACY] = ast_strdupa(ast_channel_exten(chan)); @@ -2489,7 +2453,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast ast_channel_appl_set(tc, "AppDial"); ast_channel_data_set(tc, "(Outgoing Line)"); - ast_publish_channel_state(tc); + ast_channel_publish_snapshot(tc); memset(ast_channel_whentohangup(tc), 0, sizeof(*ast_channel_whentohangup(tc))); @@ -2620,10 +2584,6 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast res = ast_call(tmp->chan, tmp->number, 0); /* Place the call, but don't wait on the answer */ ast_channel_lock(chan); - /* Save the info in cdr's that we called them */ - if (ast_channel_cdr(chan)) - ast_cdr_setdestchan(ast_channel_cdr(chan), ast_channel_name(tmp->chan)); - /* check the results of ast_call */ if (res) { /* Again, keep going even if there's an error */ @@ -2738,10 +2698,6 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast conversation. */ hanguptree(&out_chans, peer, 1); /* If appropriate, log that we have a destination channel and set the answer time */ - if (ast_channel_cdr(chan)) { - ast_cdr_setdestchan(ast_channel_cdr(chan), ast_channel_name(peer)); - ast_cdr_setanswer(ast_channel_cdr(chan), ast_channel_cdr(peer)->answer); - } if (ast_channel_name(peer)) pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ast_channel_name(peer)); @@ -2836,10 +2792,10 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast } if (chan && peer && ast_test_flag64(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) { - /* chan and peer are going into the PBX, they both - * should probably get CDR records. */ - ast_clear_flag(ast_channel_cdr(chan), AST_CDR_FLAG_DIALED); - ast_clear_flag(ast_channel_cdr(peer), AST_CDR_FLAG_DIALED); + /* chan and peer are going into the PBX; as such neither are considered + * outgoing channels any longer */ + ast_clear_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING); + ast_clear_flag(ast_channel_flags(peer), AST_FLAG_OUTGOING); ast_replace_subargument_delimiter(opt_args[OPT_ARG_GOTO]); ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]); diff --git a/apps/app_disa.c b/apps/app_disa.c index c43370c95..fe53772f1 100644 --- a/apps/app_disa.c +++ b/apps/app_disa.c @@ -362,7 +362,7 @@ static int disa_exec(struct ast_channel *chan, const char *data) if (k == 3) { int recheck = 0; - struct ast_flags cdr_flags = { AST_CDR_FLAG_POSTED }; + struct ast_flags cdr_flags = { AST_CDR_FLAG_DISABLE, }; if (!ast_exists_extension(chan, args.context, exten, 1, S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) { @@ -384,8 +384,10 @@ static int disa_exec(struct ast_channel *chan, const char *data) if (!ast_strlen_zero(acctcode)) ast_channel_accountcode_set(chan, acctcode); - if (special_noanswer) cdr_flags.flags = 0; - ast_cdr_reset(ast_channel_cdr(chan), &cdr_flags); + if (special_noanswer) { + ast_clear_flag(&cdr_flags, AST_CDR_FLAG_DISABLE); + } + ast_cdr_reset(ast_channel_name(chan), &cdr_flags); ast_explicit_goto(chan, args.context, exten, 1); return 0; } diff --git a/apps/app_dumpchan.c b/apps/app_dumpchan.c index 722f15541..7613832d4 100644 --- a/apps/app_dumpchan.c +++ b/apps/app_dumpchan.c @@ -70,7 +70,6 @@ static const char app[] = "DumpChan"; static int serialize_showchan(struct ast_channel *c, char *buf, size_t size) { - struct timeval now; long elapsed_seconds = 0; int hour = 0, min = 0, sec = 0; char nf[256]; @@ -80,21 +79,19 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size) struct ast_str *read_transpath = ast_str_alloca(256); struct ast_bridge *bridge; - now = ast_tvnow(); memset(buf, 0, size); if (!c) return 0; - if (ast_channel_cdr(c)) { - elapsed_seconds = now.tv_sec - ast_channel_cdr(c)->start.tv_sec; - hour = elapsed_seconds / 3600; - min = (elapsed_seconds % 3600) / 60; - sec = elapsed_seconds % 60; - } + elapsed_seconds = ast_channel_get_duration(c); + hour = elapsed_seconds / 3600; + min = (elapsed_seconds % 3600) / 60; + sec = elapsed_seconds % 60; ast_channel_lock(c); bridge = ast_channel_get_bridge(c); ast_channel_unlock(c); + snprintf(buf,size, "Name= %s\n" "Type= %s\n" diff --git a/apps/app_followme.c b/apps/app_followme.c index 66980009d..d12de3c1a 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -578,29 +578,6 @@ static void clear_caller(struct findme_user *tmpuser) } outbound = tmpuser->ochan; - ast_channel_lock(outbound); - if (!ast_channel_cdr(outbound)) { - ast_channel_cdr_set(outbound, ast_cdr_alloc()); - if (ast_channel_cdr(outbound)) { - ast_cdr_init(ast_channel_cdr(outbound), outbound); - } - } - if (ast_channel_cdr(outbound)) { - char tmp[256]; - - snprintf(tmp, sizeof(tmp), "Local/%s", tmpuser->dialarg); - ast_cdr_setapp(ast_channel_cdr(outbound), "FollowMe", tmp); - ast_cdr_update(outbound); - ast_cdr_start(ast_channel_cdr(outbound)); - ast_cdr_end(ast_channel_cdr(outbound)); - /* If the cause wasn't handled properly */ - if (ast_cdr_disposition(ast_channel_cdr(outbound), ast_channel_hangupcause(outbound))) { - ast_cdr_failed(ast_channel_cdr(outbound)); - } - } else { - ast_log(LOG_WARNING, "Unable to create Call Detail Record\n"); - } - ast_channel_unlock(outbound); ast_hangup(outbound); tmpuser->ochan = NULL; } @@ -1127,11 +1104,6 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel * Destoy all new outgoing calls. */ while ((tmpuser = AST_LIST_REMOVE_HEAD(&new_user_list, entry))) { - ast_channel_lock(tmpuser->ochan); - if (ast_channel_cdr(tmpuser->ochan)) { - ast_cdr_init(ast_channel_cdr(tmpuser->ochan), tmpuser->ochan); - } - ast_channel_unlock(tmpuser->ochan); destroy_calling_node(tmpuser); } @@ -1153,11 +1125,6 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel AST_LIST_REMOVE_CURRENT(entry); /* Destroy this failed new outgoing call. */ - ast_channel_lock(tmpuser->ochan); - if (ast_channel_cdr(tmpuser->ochan)) { - ast_cdr_init(ast_channel_cdr(tmpuser->ochan), tmpuser->ochan); - } - ast_channel_unlock(tmpuser->ochan); destroy_calling_node(tmpuser); continue; } @@ -1310,15 +1277,10 @@ static void end_bridge_callback(void *data) time(&end); ast_channel_lock(chan); - if (ast_channel_cdr(chan)->answer.tv_sec) { - snprintf(buf, sizeof(buf), "%ld", (long) end - ast_channel_cdr(chan)->answer.tv_sec); - pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); - } - - if (ast_channel_cdr(chan)->start.tv_sec) { - snprintf(buf, sizeof(buf), "%ld", (long) end - ast_channel_cdr(chan)->start.tv_sec); - pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); - } + snprintf(buf, sizeof(buf), "%d", ast_channel_get_up_time(chan)); + pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf); + snprintf(buf, sizeof(buf), "%d", ast_channel_get_duration(chan)); + pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf); ast_channel_unlock(chan); } diff --git a/apps/app_forkcdr.c b/apps/app_forkcdr.c index 354792fb9..6231d381f 100644 --- a/apps/app_forkcdr.c +++ b/apps/app_forkcdr.c @@ -44,98 +44,46 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") /*** DOCUMENTATION <application name="ForkCDR" language="en_US"> <synopsis> - Forks the Call Data Record. + Forks the current Call Data Record for this channel. </synopsis> <syntax> <parameter name="options"> <optionlist> <option name="a"> - <para>Update the answer time on the NEW CDR just after it's been inited. - The new CDR may have been answered already. The reset that forkcdr does - will erase the answer time. This will bring it back, but the answer time - will be a copy of the fork/start time. It will only do this if the initial - cdr was indeed already answered.</para> - </option> - <option name="A"> - <para>Lock the original CDR against the answer time being updated. This - will allow the disposition on the original CDR to remain the same.</para> - </option> - <option name="d"> - <para>Copy the disposition forward from the old cdr, after the init.</para> - </option> - <option name="D"> - <para>Clear the <literal>dstchannel</literal> on the new CDR after - reset.</para> + <para>If the channel is answered, set the answer time on + the forked CDR to the current time. If this option is + not used, the answer time on the forked CDR will be the + answer time on the original CDR. If the channel is not + answered, this option has no effect.</para> + <para>Note that this option is implicitly assumed if the + <literal>r</literal> option is used.</para> </option> <option name="e"> - <para>End the original CDR. Do this after all the necessary data is copied - from the original CDR to the new forked CDR.</para> + <para>End (finalize) the original CDR.</para> </option> <option name="r"> - <para>Do <emphasis>NOT</emphasis> reset the new cdr.</para> - </option> - <option name="s(name=val)"> - <para>Set the CDR var <replaceable>name</replaceable> in the original CDR, - with value <replaceable>val</replaceable>.</para> - </option> - <option name="T"> - <para>Mark the original CDR with a DONT_TOUCH flag. setvar, answer, and end - cdr funcs will obey this flag; normally they don't honor the LOCKED flag - set on the original CDR record.</para> - <note><para>Using this flag may cause CDR's not to have their end times - updated! It is suggested that if you specify this flag, you might wish - to use the <literal>e</literal> flag as well!.</para></note> + <para>Reset the start and answer times on the forked CDR. + This will set the start and answer times (if the channel + is answered) to be set to the current time.</para> + <para>Note that this option implicitly assumes the + <literal>a</literal> option.</para> </option> <option name="v"> - <para>When the new CDR is forked, it gets a copy of the vars attached to - the current CDR. The vars attached to the original CDR are removed unless - this option is specified.</para> + <para>Do not copy CDR variables and attributes from the + original CDR to the forked CDR.</para> + <warning><para>This option has changed. Previously, the + variables were removed from the original CDR. This no + longer occurs - this option now controls whether or not + a forked CDR inherits the variables from the original + CDR.</para></warning> </option> </optionlist> </parameter> </syntax> <description> - <para> Causes the Call Data Record to fork an additional cdr record starting from the time - of the fork call. This new cdr record will be linked to end of the list of cdr records attached - to the channel. The original CDR has a LOCKED flag set, which forces most cdr operations to skip - it, except for the functions that set the answer and end times, which ignore the LOCKED flag. This - allows all the cdr records in the channel to be 'ended' together when the channel is closed.</para> - <para>The CDR() func (when setting CDR values) normally ignores the LOCKED flag also, but has options - to vary its behavior. The 'T' option (described below), can override this behavior, but beware - the risks.</para> - <para>First, this app finds the last cdr record in the list, and makes a copy of it. This new copy - will be the newly forked cdr record. Next, this new record is linked to the end of the cdr record list. - Next, The new cdr record is RESET (unless you use an option to prevent this)</para> - <para>This means that:</para> - <para> 1. All flags are unset on the cdr record</para> - <para> 2. the start, end, and answer times are all set to zero.</para> - <para> 3. the billsec and duration fields are set to zero.</para> - <para> 4. the start time is set to the current time.</para> - <para> 5. the disposition is set to NULL.</para> - <para>Next, unless you specified the <literal>v</literal> option, all variables will be removed from - the original cdr record. Thus, the <literal>v</literal> option allows any CDR variables to be replicated - to all new forked cdr records. Without the <literal>v</literal> option, the variables on the original - are effectively moved to the new forked cdr record.</para> - <para>Next, if the <literal>s</literal> option is set, the provided variable and value are set on the - original cdr record.</para> - <para>Next, if the <literal>a</literal> option is given, and the original cdr record has an answer time - set, then the new forked cdr record will have its answer time set to its start time. If the old answer - time were carried forward, the answer time would be earlier than the start time, giving strange - duration and billsec times.</para> - <para>If the <literal>d</literal> option was specified, the disposition is copied from - the original cdr record to the new forked cdr. If the <literal>D</literal> option was specified, - the destination channel field in the new forked CDR is erased. If the <literal>e</literal> option - was specified, the 'end' time for the original cdr record is set to the current time. Future hang-up or - ending events will not override this time stamp. If the <literal>A</literal> option is specified, - the original cdr record will have it ANS_LOCKED flag set, which prevent future answer events from updating - the original cdr record's disposition. Normally, an <literal>ANSWERED</literal> event would mark all cdr - records in the chain as <literal>ANSWERED</literal>. If the <literal>T</literal> option is specified, - the original cdr record will have its <literal>DONT_TOUCH</literal> flag set, which will force the - cdr_answer, cdr_end, and cdr_setvar functions to leave that cdr record alone.</para> - <para>And, last but not least, the original cdr record has its LOCKED flag set. Almost all internal - CDR functions (except for the funcs that set the end, and answer times, and set a variable) will honor - this flag and leave a LOCKED cdr record alone. This means that the newly created forked cdr record - will be affected by events transpiring within Asterisk, with the previously noted exceptions.</para> + <para>Causes the Call Data Record engine to fork a new CDR starting + from the time the application is executed. The forked CDR will be + linked to the end of the CDRs associated with the channel.</para> </description> <see-also> <ref type="function">CDR</ref> @@ -147,126 +95,34 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") static char *app = "ForkCDR"; -enum { - OPT_SETANS = (1 << 0), - OPT_SETDISP = (1 << 1), - OPT_RESETDEST = (1 << 2), - OPT_ENDCDR = (1 << 3), - OPT_NORESET = (1 << 4), - OPT_KEEPVARS = (1 << 5), - OPT_VARSET = (1 << 6), - OPT_ANSLOCK = (1 << 7), - OPT_DONTOUCH = (1 << 8), -}; - -enum { - OPT_ARG_VARSET = 0, - /* note: this entry _MUST_ be the last one in the enum */ - OPT_ARG_ARRAY_SIZE, -}; - AST_APP_OPTIONS(forkcdr_exec_options, { - AST_APP_OPTION('a', OPT_SETANS), - AST_APP_OPTION('A', OPT_ANSLOCK), - AST_APP_OPTION('d', OPT_SETDISP), - AST_APP_OPTION('D', OPT_RESETDEST), - AST_APP_OPTION('e', OPT_ENDCDR), - AST_APP_OPTION('R', OPT_NORESET), - AST_APP_OPTION_ARG('s', OPT_VARSET, OPT_ARG_VARSET), - AST_APP_OPTION('T', OPT_DONTOUCH), - AST_APP_OPTION('v', OPT_KEEPVARS), + AST_APP_OPTION('a', AST_CDR_FLAG_SET_ANSWER), + AST_APP_OPTION('e', AST_CDR_FLAG_FINALIZE), + AST_APP_OPTION('r', AST_CDR_FLAG_RESET), + AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS), }); -static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set) -{ - struct ast_cdr *cdr; - struct ast_cdr *newcdr; - struct ast_flags flags = { AST_CDR_FLAG_KEEP_VARS }; - - cdr = ast_channel_cdr(chan); - - while (cdr->next) - cdr = cdr->next; - - if (!(newcdr = ast_cdr_dup_unique(cdr))) - return; - - /* - * End the original CDR if requested BEFORE appending the new CDR - * otherwise we incorrectly end the new CDR also. - */ - if (ast_test_flag(&optflags, OPT_ENDCDR)) { - ast_cdr_end(cdr); - } - - ast_cdr_append(cdr, newcdr); - - if (!ast_test_flag(&optflags, OPT_NORESET)) - ast_cdr_reset(newcdr, &flags); - - if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS)) - ast_cdr_free_vars(cdr, 0); - - if (!ast_strlen_zero(set)) { - char *varname = ast_strdupa(set), *varval; - varval = strchr(varname,'='); - if (varval) { - *varval = 0; - varval++; - ast_cdr_setvar(cdr, varname, varval, 0); - } - } - - if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer)) - newcdr->answer = newcdr->start; - - if (ast_test_flag(&optflags, OPT_SETDISP)) - newcdr->disposition = cdr->disposition; - - if (ast_test_flag(&optflags, OPT_RESETDEST)) - newcdr->dstchannel[0] = 0; - - if (ast_test_flag(&optflags, OPT_ANSLOCK)) - ast_set_flag(cdr, AST_CDR_FLAG_ANSLOCKED); - - if (ast_test_flag(&optflags, OPT_DONTOUCH)) - ast_set_flag(cdr, AST_CDR_FLAG_DONT_TOUCH); - - ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED); -} - static int forkcdr_exec(struct ast_channel *chan, const char *data) { - int res = 0; - char *argcopy = NULL; - struct ast_flags flags = {0}; - char *opts[OPT_ARG_ARRAY_SIZE]; - AST_DECLARE_APP_ARGS(arglist, + char *parse; + struct ast_flags flags = { 0, }; + AST_DECLARE_APP_ARGS(args, AST_APP_ARG(options); ); - if (!ast_channel_cdr(chan)) { - ast_log(LOG_WARNING, "Channel does not have a CDR\n"); - return 0; - } - - argcopy = ast_strdupa(data); + parse = ast_strdupa(data); - AST_STANDARD_APP_ARGS(arglist, argcopy); + AST_STANDARD_APP_ARGS(args, parse); - opts[OPT_ARG_VARSET] = 0; - - if (!ast_strlen_zero(arglist.options)) - ast_app_parse_options(forkcdr_exec_options, &flags, opts, arglist.options); + if (!ast_strlen_zero(args.options)) { + ast_app_parse_options(forkcdr_exec_options, &flags, NULL, args.options); + } - if (!ast_strlen_zero(data)) { - int keepvars = ast_test_flag(&flags, OPT_KEEPVARS) ? 1 : 0; - ast_set2_flag(ast_channel_cdr(chan), keepvars, AST_CDR_FLAG_KEEP_VARS); + if (ast_cdr_fork(ast_channel_name(chan), &flags)) { + ast_log(AST_LOG_WARNING, "Failed to fork CDR for channel %s\n", ast_channel_name(chan)); } - - ast_cdr_fork(chan, flags, opts[OPT_ARG_VARSET]); - return res; + return 0; } static int unload_module(void) diff --git a/apps/app_osplookup.c b/apps/app_osplookup.c index b37a2ae63..5ab497f5e 100644 --- a/apps/app_osplookup.c +++ b/apps/app_osplookup.c @@ -2814,7 +2814,7 @@ static int ospfinished_exec( int inhandle = OSP_INVALID_HANDLE; int outhandle = OSP_INVALID_HANDLE; int recorded = 0; - time_t start, connect, end; + time_t start = 0, connect = 0, end = 0; unsigned int release; char buffer[OSP_SIZE_INTSTR]; char inqos[OSP_SIZE_QOSSTR] = { 0 }; @@ -2866,19 +2866,18 @@ static int ospfinished_exec( } ast_debug(1, "OSPFinish: cause '%d'\n", cause); - if (ast_channel_cdr(chan)) { - start = ast_channel_cdr(chan)->start.tv_sec; - connect = ast_channel_cdr(chan)->answer.tv_sec; - if (connect) { - end = time(NULL); - } else { - end = connect; - } + if (!ast_tvzero(ast_channel_creationtime(chan))) { + start = ast_channel_creationtime(chan).tv_sec; + } + if (!ast_tvzero(ast_channel_answertime(chan))) { + connect = ast_channel_answertime(chan).tv_sec; + } + if (connect) { + end = time(NULL); } else { - start = 0; - connect = 0; - end = 0; + end = connect; } + ast_debug(1, "OSPFinish: start '%ld'\n", start); ast_debug(1, "OSPFinish: connect '%ld'\n", connect); ast_debug(1, "OSPFinish: end '%ld'\n", end); diff --git a/apps/app_queue.c b/apps/app_queue.c index 4c9658313..724ea47ff 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -3666,10 +3666,10 @@ static void publish_dial_end_event(struct ast_channel *in, struct callattempt *o struct callattempt *cur; for (cur = outgoing; cur; cur = cur->q_next) { - if (cur->chan && cur->chan != exception) { + if (cur->chan && cur->chan != exception) { ast_channel_publish_dial(in, cur->chan, NULL, status); - } - } + } + } } /*! \brief Hang up a list of outgoing calls */ @@ -3931,9 +3931,7 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies member_call_pending_clear(tmp->member); - if (ast_channel_cdr(qe->chan)) { - ast_cdr_busy(ast_channel_cdr(qe->chan)); - } + /* BUGBUG: Raise a BUSY dial end message here */ tmp->stillgoing = 0; ++*busies; return 0; @@ -3987,21 +3985,6 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies } else { ast_channel_exten_set(tmp->chan, ast_channel_exten(qe->chan)); } - if (ast_cdr_isset_unanswered()) { - /* they want to see the unanswered dial attempts! */ - /* set up the CDR fields on all the CDRs to give sensical information */ - ast_cdr_setdestchan(ast_channel_cdr(tmp->chan), ast_channel_name(tmp->chan)); - strcpy(ast_channel_cdr(tmp->chan)->clid, ast_channel_cdr(qe->chan)->clid); - strcpy(ast_channel_cdr(tmp->chan)->channel, ast_channel_cdr(qe->chan)->channel); - strcpy(ast_channel_cdr(tmp->chan)->src, ast_channel_cdr(qe->chan)->src); - strcpy(ast_channel_cdr(tmp->chan)->dst, ast_channel_exten(qe->chan)); - strcpy(ast_channel_cdr(tmp->chan)->dcontext, ast_channel_context(qe->chan)); - strcpy(ast_channel_cdr(tmp->chan)->lastapp, ast_channel_cdr(qe->chan)->lastapp); - strcpy(ast_channel_cdr(tmp->chan)->lastdata, ast_channel_cdr(qe->chan)->lastdata); - ast_channel_cdr(tmp->chan)->amaflags = ast_channel_cdr(qe->chan)->amaflags; - strcpy(ast_channel_cdr(tmp->chan)->accountcode, ast_channel_cdr(qe->chan)->accountcode); - strcpy(ast_channel_cdr(tmp->chan)->userfield, ast_channel_cdr(qe->chan)->userfield); - } ast_channel_unlock(tmp->chan); ast_channel_unlock(qe->chan); @@ -4371,14 +4354,14 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte if (pos == 1 /* not found */) { if (numlines == (numbusies + numnochan)) { ast_debug(1, "Everyone is busy at this time\n"); - if (ast_channel_cdr(in) && ast_channel_state(in) != AST_STATE_UP) { - ast_cdr_busy(ast_channel_cdr(in)); - } + /* BUGBUG: We shouldn't have to set anything here, as each + * individual dial attempt should have set that CDR to busy + */ } else { ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan); - if (ast_channel_cdr(in) && ast_channel_state(in) != AST_STATE_UP) { - ast_cdr_failed(ast_channel_cdr(in)); - } + /* BUGBUG: We shouldn't have to set anything here, as each + * individual dial attempt should have set that CDR to busy + */ } *to = 0; return NULL; @@ -4609,9 +4592,6 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte break; case AST_CONTROL_BUSY: ast_verb(3, "%s is busy\n", ochan_name); - if (ast_channel_cdr(in)) { - ast_cdr_busy(ast_channel_cdr(in)); - } ast_channel_publish_dial(qe->chan, o->chan, on, "BUSY"); do_hang(o); endtime = (long) time(NULL); @@ -4631,9 +4611,6 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte break; case AST_CONTROL_CONGESTION: ast_verb(3, "%s is circuit-busy\n", ochan_name); - if (ast_channel_cdr(in)) { - ast_cdr_failed(ast_channel_cdr(in)); - } ast_channel_publish_dial(qe->chan, o->chan, on, "CONGESTION"); endtime = (long) time(NULL); endtime -= starttime; @@ -4769,9 +4746,6 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte *to = 0; publish_dial_end_event(in, outgoing, NULL, "CANCEL"); ast_frfree(f); - if (ast_channel_cdr(in) && ast_channel_state(in) != AST_STATE_UP) { - ast_cdr_noanswer(ast_channel_cdr(in)); - } return NULL; } if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) { @@ -4780,9 +4754,6 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte publish_dial_end_event(in, outgoing, NULL, "CANCEL"); *digit = f->subclass.integer; ast_frfree(f); - if (ast_channel_cdr(in) && ast_channel_state(in) != AST_STATE_UP) { - ast_cdr_noanswer(ast_channel_cdr(in)); - } return NULL; } @@ -4839,11 +4810,6 @@ skip_frame:; } publish_dial_end_event(qe->chan, outgoing, NULL, "NOANSWER"); - if (ast_channel_cdr(in) - && ast_channel_state(in) != AST_STATE_UP - && (!*to || ast_check_hangup(in))) { - ast_cdr_noanswer(ast_channel_cdr(in)); - } } #ifdef HAVE_EPOLL @@ -5678,20 +5644,6 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a if (res == -1) { ast_debug(1, "%s: Nobody answered.\n", ast_channel_name(qe->chan)); } - if (ast_cdr_isset_unanswered()) { - /* channel contains the name of one of the outgoing channels - in its CDR; zero out this CDR to avoid a dual-posting */ - struct callattempt *o; - for (o = outgoing; o; o = o->q_next) { - if (!o->chan) { - continue; - } - if (strcmp(ast_channel_cdr(o->chan)->dstchannel, ast_channel_cdr(qe->chan)->dstchannel) == 0) { - ast_set_flag(ast_channel_cdr(o->chan), AST_CDR_FLAG_POST_DISABLED); - break; - } - } - } } else { /* peer is valid */ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); /* Ah ha! Someone answered within the desired timeframe. Of course after this @@ -5785,17 +5737,14 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a } else { ast_moh_stop(qe->chan); } - /* If appropriate, log that we have a destination channel */ - if (ast_channel_cdr(qe->chan)) { - ast_cdr_setdestchan(ast_channel_cdr(qe->chan), ast_channel_name(peer)); - } + /* Make sure channels are compatible */ res = ast_channel_make_compatible(qe->chan, peer); if (res < 0) { ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "SYSCOMPAT", "%s", ""); ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", ast_channel_name(qe->chan), ast_channel_name(peer)); record_abandoned(qe); - ast_cdr_failed(ast_channel_cdr(qe->chan)); + ast_channel_publish_dial(qe->chan, peer, member->interface, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(peer))); ast_autoservice_chan_hangup_peer(qe->chan, peer); ao2_ref(member, -1); return -1; @@ -5855,10 +5804,10 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a ast_channel_unlock(qe->chan); if (monitorfilename) { ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT); - } else if (ast_channel_cdr(qe->chan)) { - ast_monitor_start(which, qe->parent->monfmt, ast_channel_cdr(qe->chan)->uniqueid, 1, X_REC_IN | X_REC_OUT); + } else if (qe->chan) { + ast_monitor_start(which, qe->parent->monfmt, ast_channel_uniqueid(qe->chan), 1, X_REC_IN | X_REC_OUT); } else { - /* Last ditch effort -- no CDR, make up something */ + /* Last ditch effort -- no channel, make up something */ snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random()); ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT); } @@ -5871,8 +5820,8 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a if (mixmonapp) { ast_debug(1, "Starting MixMonitor as requested.\n"); if (!monitorfilename) { - if (ast_channel_cdr(qe->chan)) { - ast_copy_string(tmpid, ast_channel_cdr(qe->chan)->uniqueid, sizeof(tmpid)); + if (qe->chan) { + ast_copy_string(tmpid, ast_channel_uniqueid(qe->chan), sizeof(tmpid)); } else { snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random()); } @@ -5944,14 +5893,15 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a } ast_debug(1, "Arguments being passed to MixMonitor: %s\n", mixmonargs); - /* We purposely lock the CDR so that pbx_exec does not update the application data */ - if (ast_channel_cdr(qe->chan)) { - ast_set_flag(ast_channel_cdr(qe->chan), AST_CDR_FLAG_LOCKED); - } + /* BUGBUG + * This needs to be done differently. We need to start a MixMonitor on + * the actual queue bridge itself, not drop some channel out and pull it + * back. Once the media channel work is done, start a media channel on + * the bridge. + * + * Alternatively, don't use pbx_exec to put an audio hook on a channel. + */ pbx_exec(qe->chan, mixmonapp, mixmonargs); - if (ast_channel_cdr(qe->chan)) { - ast_clear_flag(ast_channel_cdr(qe->chan), AST_CDR_FLAG_LOCKED); - } } else { ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n"); } @@ -6039,33 +5989,6 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "CONNECT", "%ld|%s|%ld", (long) time(NULL) - qe->start, ast_channel_uniqueid(peer), (long)(orig - to > 0 ? (orig - to) / 1000 : 0)); - if (ast_channel_cdr(qe->chan)) { - struct ast_cdr *cdr; - struct ast_cdr *newcdr; - - /* Only work with the last CDR in the stack*/ - cdr = ast_channel_cdr(qe->chan); - while (cdr->next) { - cdr = cdr->next; - } - - /* If this CDR is not related to us add new one*/ - if ((strcasecmp(cdr->uniqueid, ast_channel_uniqueid(qe->chan))) && - (strcasecmp(cdr->linkedid, ast_channel_uniqueid(qe->chan))) && - (newcdr = ast_cdr_dup(cdr))) { - ast_channel_lock(qe->chan); - ast_cdr_init(newcdr, qe->chan); - ast_cdr_reset(newcdr, 0); - cdr = ast_cdr_append(cdr, newcdr); - cdr = cdr->next; - ast_channel_unlock(qe->chan); - } - - if (update_cdr) { - ast_copy_string(cdr->dstchannel, member->membername, sizeof(cdr->dstchannel)); - } - } - blob = ast_json_pack("{s: s, s: s, s: s, s: i, s: i}", "Queue", queuename, "Interface", member->interface, |