[asterisk-commits] mjordan: trunk r422720 - in /trunk: ./ apps/ include/asterisk/ main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Sep 5 17:04:36 CDT 2014
Author: mjordan
Date: Fri Sep 5 17:04:33 2014
New Revision: 422720
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=422720
Log:
main/cdrs: Preserve context/extension when executing a Macro or GoSub
The context/extension in a CDR is generally considered the destination of a
call. When looking at a 2-party call CDR, users will typically be presented
with the following:
context exten channel dest_channel app data
default 1000 SIP/8675309 SIP/1000 Dial SIP/1000,,20
However, if the Dial actually takes place in a Macro, the current behaviour
in 12 will result in the following CDR:
context exten channel dest_channel app data
macro-dial s SIP/8675309 SIP/1000 Dial SIP/1000,,20
The same is true of a GoSub:
context exten channel dest_channel app data
subs dial_stuff SIP/8675309 SIP/1000 Dial SIP/1000,,20
This generally makes the context/exten fields less than useful.
It isn't hard to preserve these values in the CDR state machine; however, we
need to have something that informs us when a channel is executing a
subroutine. Prior to this patch, there isn't anything that does this.
This patch solves this problem by adding a new channel flag,
AST_FLAG_SUBROUTINE_EXEC. This flag is set on a channel when it executes a
Macro or a GoSub. The CDR engine looks for this value when updating a Party A
snapshot; if the flag is present, we don't override the context/exten on the
main CDR object. In a funny quirk, executing a hangup handler must *not* abide
by this logic, as the endbeforehexten logic assumes that the user wants to see
data that occurs in hangup logic, which includes those subroutines. Since
those execute outside of a typical Dial operation (and will typically have
their own dedicated CDR anyway), this is unlikely to cause any heartburn.
Review: https://reviewboard.asterisk.org/r/3962/
ASTERISK-24254 #close
Reported by: tm1000, Tony Lewis
Tested by: Tony Lewis
........
Merged revisions 422718 from http://svn.asterisk.org/svn/asterisk/branches/12
........
Merged revisions 422719 from http://svn.asterisk.org/svn/asterisk/branches/13
Modified:
trunk/ (props changed)
trunk/apps/app_macro.c
trunk/apps/app_stack.c
trunk/include/asterisk/channel.h
trunk/main/cdr.c
Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-13-merged' - no diff available.
Modified: trunk/apps/app_macro.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_macro.c?view=diff&rev=422720&r1=422719&r2=422720
==============================================================================
--- trunk/apps/app_macro.c (original)
+++ trunk/apps/app_macro.c Fri Sep 5 17:04:33 2014
@@ -248,6 +248,7 @@
char *save_macro_context;
char *save_macro_priority;
char *save_macro_offset;
+ int save_in_subroutine;
struct ast_datastore *macro_store = ast_channel_datastore_find(chan, ¯o_ds_info, NULL);
if (ast_strlen_zero(data)) {
@@ -329,6 +330,7 @@
}
/* Save old info */
+ ast_channel_lock(chan);
oldpriority = ast_channel_priority(chan);
ast_copy_string(oldexten, ast_channel_exten(chan), sizeof(oldexten));
ast_copy_string(oldcontext, ast_channel_context(chan), sizeof(oldcontext));
@@ -355,12 +357,14 @@
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
+ save_in_subroutine = ast_test_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
+ ast_set_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
+
/* Setup environment for new run */
ast_channel_exten_set(chan, "s");
ast_channel_context_set(chan, fullmacro);
ast_channel_priority_set(chan, 1);
- ast_channel_lock(chan);
while((cur = strsep(&rest, ",")) && (argc < MAX_ARGS)) {
const char *argp;
/* Save copy of old arguments if we're overwriting some, otherwise
@@ -513,6 +517,7 @@
snprintf(depthc, sizeof(depthc), "%d", depth);
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
ast_set2_flag(ast_channel_flags(chan), autoloopflag, AST_FLAG_IN_AUTOLOOP);
+ ast_set2_flag(ast_channel_flags(chan), save_in_subroutine, AST_FLAG_SUBROUTINE_EXEC);
for (x = 1; x < argc; x++) {
/* Restore old arguments and delete ours */
Modified: trunk/apps/app_stack.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_stack.c?view=diff&rev=422720&r1=422719&r2=422720
==============================================================================
--- trunk/apps/app_stack.c (original)
+++ trunk/apps/app_stack.c Fri Sep 5 17:04:33 2014
@@ -251,6 +251,8 @@
int priority;
/*! TRUE if the return location marks the end of a special routine. */
unsigned int is_special:1;
+ /*! Whether or not we were in a subroutine when this one was created */
+ unsigned int in_subroutine:1;
char *context;
char extension[0];
};
@@ -310,7 +312,7 @@
ast_free(frame);
}
-static struct gosub_stack_frame *gosub_allocate_frame(const char *context, const char *extension, int priority, unsigned char arguments)
+static struct gosub_stack_frame *gosub_allocate_frame(const char *context, const char *extension, int priority, int in_subroutine, unsigned char arguments)
{
struct gosub_stack_frame *new = NULL;
int len_extension = strlen(extension), len_context = strlen(context);
@@ -321,6 +323,7 @@
new->context = new->extension + len_extension + 1;
strcpy(new->context, context);
new->priority = priority;
+ new->in_subroutine = in_subroutine ? 1 : 0;
new->arguments = arguments;
}
return new;
@@ -416,6 +419,7 @@
--oldframe->priority;
}
ast_channel_priority_set(chan, oldframe->priority);
+ ast_set2_flag(ast_channel_flags(chan), oldframe->in_subroutine, AST_FLAG_SUBROUTINE_EXEC);
gosub_release_frame(chan, oldframe);
@@ -524,6 +528,7 @@
char *orig_exten;
char *dest_context;
char *dest_exten;
+ int orig_in_subroutine;
int orig_priority;
int dest_priority;
int i;
@@ -563,6 +568,7 @@
orig_context = ast_strdupa(ast_channel_context(chan));
orig_exten = ast_strdupa(ast_channel_exten(chan));
orig_priority = ast_channel_priority(chan);
+ orig_in_subroutine = ast_test_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
ast_channel_unlock(chan);
if (ast_parseable_goto(chan, label)) {
@@ -630,7 +636,7 @@
}
/* Create the return address */
- newframe = gosub_allocate_frame(orig_context, orig_exten, orig_priority + 1, max_argc);
+ newframe = gosub_allocate_frame(orig_context, orig_exten, orig_priority + 1, orig_in_subroutine, max_argc);
if (!newframe) {
goto error_exit_locked;
}
@@ -643,6 +649,8 @@
}
snprintf(argname, sizeof(argname), "%u", args2.argc);
frame_set_var(chan, newframe, "ARGC", argname);
+
+ ast_set_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
/* And finally, save our return address */
AST_LIST_LOCK(oldlist);
@@ -967,6 +975,7 @@
int saved_priority;
int saved_hangup_flags;
int saved_autoloopflag;
+ int saved_in_subroutine;
int res;
ast_channel_lock(chan);
@@ -989,6 +998,9 @@
saved_context = ast_strdupa(ast_channel_context(chan));
saved_exten = ast_strdupa(ast_channel_exten(chan));
saved_priority = ast_channel_priority(chan);
+
+ /* Save whether or not we are in a subroutine */
+ saved_in_subroutine = ast_test_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
ast_debug(4, "%s Original location: %s,%s,%d\n", ast_channel_name(chan),
saved_context, saved_exten, saved_priority);
@@ -1091,6 +1103,9 @@
/* Restore autoloop flag */
ast_set2_flag(ast_channel_flags(chan), saved_autoloopflag, AST_FLAG_IN_AUTOLOOP);
+ /* Restore subroutine flag */
+ ast_set2_flag(ast_channel_flags(chan), saved_in_subroutine, AST_FLAG_SUBROUTINE_EXEC);
+
/* Restore non-hangup softhangup flags. */
if (saved_hangup_flags) {
ast_softhangup_nolock(chan, saved_hangup_flags);
@@ -1106,6 +1121,7 @@
int res;
int priority;
int old_autoloopflag;
+ int old_in_subroutine;
int old_priority;
const char *old_context;
const char *old_extension;
@@ -1153,6 +1169,9 @@
/* Save autoloop flag */
old_autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
ast_set_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
+
+ /* Save subroutine flag */
+ old_in_subroutine = ast_test_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
/* Save previous location, since we're going to change it */
old_context = ast_strdupa(ast_channel_context(chan));
@@ -1246,6 +1265,9 @@
/* Restore autoloop flag */
ast_set2_flag(ast_channel_flags(chan), old_autoloopflag, AST_FLAG_IN_AUTOLOOP);
+
+ /* Restore subroutine flag */
+ ast_set2_flag(ast_channel_flags(chan), old_in_subroutine, AST_FLAG_SUBROUTINE_EXEC);
ast_channel_unlock(chan);
return RESULT_SUCCESS;
Modified: trunk/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=422720&r1=422719&r2=422720
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Fri Sep 5 17:04:33 2014
@@ -962,6 +962,10 @@
* The data on chan->timingdata is an astobj2 object.
*/
AST_FLAG_TIMINGDATA_IS_AO2_OBJ = (1 << 26),
+ /*!
+ * The channel is executing a subroutine or macro
+ */
+ AST_FLAG_SUBROUTINE_EXEC = (1 << 27),
};
/*! \brief ast_bridge_config flags */
Modified: trunk/main/cdr.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/cdr.c?view=diff&rev=422720&r1=422719&r2=422720
==============================================================================
--- trunk/main/cdr.c (original)
+++ trunk/main/cdr.c Fri Sep 5 17:04:33 2014
@@ -692,6 +692,8 @@
AST_STRING_FIELD(bridge); /*!< The bridge the party A happens to be in. */
AST_STRING_FIELD(appl); /*!< The last accepted application party A was in */
AST_STRING_FIELD(data); /*!< The data for the last accepted application party A was in */
+ AST_STRING_FIELD(context); /*!< The accepted context for Party A */
+ AST_STRING_FIELD(exten); /*!< The accepted extension for Party A */
);
struct cdr_object *next; /*!< The next CDR object in the chain */
struct cdr_object *last; /*!< The last CDR object in the chain */
@@ -1115,8 +1117,8 @@
ast_copy_string(cdr_copy->uniqueid, party_a->uniqueid, sizeof(cdr_copy->uniqueid));
ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
- ast_copy_string(cdr_copy->dst, party_a->exten, sizeof(cdr_copy->dst));
- ast_copy_string(cdr_copy->dcontext, party_a->context, sizeof(cdr_copy->dcontext));
+ ast_copy_string(cdr_copy->dst, it_cdr->exten, sizeof(cdr_copy->dst));
+ ast_copy_string(cdr_copy->dcontext, it_cdr->context, sizeof(cdr_copy->dcontext));
/* Party B */
if (party_b) {
@@ -1353,6 +1355,17 @@
cdr_object_check_party_a_hangup(cdr);
return 0;
}
+
+ /*
+ * Only record the context and extension if we aren't in a subroutine, or if
+ * we are executing hangup logic.
+ */
+ if (!ast_test_flag(&snapshot->flags, AST_FLAG_SUBROUTINE_EXEC)
+ || ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
+ ast_string_field_set(cdr, context, snapshot->context);
+ ast_string_field_set(cdr, exten, snapshot->exten);
+ }
+
cdr_object_swap_snapshot(&cdr->party_a, snapshot);
/* When Party A is originated to an application and the application exits, the stack
More information about the asterisk-commits
mailing list