summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2013-06-17 03:00:38 +0000
committerMatthew Jordan <mjordan@digium.com>2013-06-17 03:00:38 +0000
commit6258bbe7bd1885ac5dec095ed0c4490c83a99f44 (patch)
treeff2794f730ca55903a09b9fe7f73f45169a71386 /apps
parent67e35c7b4748c3cef954820a2b182e2a5edf8d98 (diff)
Update Asterisk's CDRs for the new bridging framework
This patch is the initial push to update Asterisk's CDR engine for the new bridging framework. This patch guts the existing CDR engine and builds the new on top of messages coming across Stasis. As changes in channel state and bridge state are detected, CDRs are built and dispatched accordingly. This fundamentally changes CDRs in a few ways. (1) CDRs are now *very* reflective of the actual state of channels and bridges. This means CDRs track well with what an actual channel is doing - which is useful in transfer scenarios (which were previously difficult to pin down). It does, however, mean that CDRs cannot be 'fooled'. Previous behavior in Asterisk allowed for CDR applications, channels, and other properties to be spoofed in parts of the code - this no longer works. (2) CDRs have defined behavior in multi-party scenarios. This behavior will not be what everyone wants, but it is a defined behavior and as such, it is predictable. (3) The CDR manipulation functions and applications have been overhauled. Major changes have been made to ResetCDR and ForkCDR in particular. Many of the options for these two applications no longer made any sense with the new framework and the (slightly) more immutable nature of CDRs. There are a plethora of other changes. For a full description of CDR behavior, see the CDR specification on the Asterisk wiki. (closes issue ASTERISK-21196) Review: https://reviewboard.asterisk.org/r/2486/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@391947 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'apps')
-rw-r--r--apps/app_authenticate.c8
-rw-r--r--apps/app_cdr.c105
-rw-r--r--apps/app_dial.c76
-rw-r--r--apps/app_disa.c8
-rw-r--r--apps/app_dumpchan.c13
-rw-r--r--apps/app_followme.c46
-rw-r--r--apps/app_forkcdr.c222
-rw-r--r--apps/app_osplookup.c23
-rw-r--r--apps/app_queue.c127
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,