diff options
author | Matthew Jordan <mjordan@digium.com> | 2014-09-05 22:04:33 +0000 |
---|---|---|
committer | Matthew Jordan <mjordan@digium.com> | 2014-09-05 22:04:33 +0000 |
commit | d42b116925d4835f158f097150b4802b6feec83b (patch) | |
tree | 071dd60b2a39393ad4e3d6b5daf3173b76f36e00 /apps/app_stack.c | |
parent | 4499eb05d83b8ed54bff6f3e4deb1f7af3098531 (diff) |
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
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@422720 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'apps/app_stack.c')
-rw-r--r-- | apps/app_stack.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/apps/app_stack.c b/apps/app_stack.c index c9d37cd34..253f41310 100644 --- a/apps/app_stack.c +++ b/apps/app_stack.c @@ -251,6 +251,8 @@ struct gosub_stack_frame { 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 @@ static void gosub_release_frame(struct ast_channel *chan, struct gosub_stack_fra 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 @@ static struct gosub_stack_frame *gosub_allocate_frame(const char *context, const 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 @@ static int return_exec(struct ast_channel *chan, const char *data) --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 @@ static int gosub_exec(struct ast_channel *chan, const char *data) 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 @@ static int gosub_exec(struct ast_channel *chan, const char *data) 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 @@ static int gosub_exec(struct ast_channel *chan, const char *data) } /* 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; } @@ -644,6 +650,8 @@ static int gosub_exec(struct ast_channel *chan, const char *data) 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); AST_LIST_INSERT_HEAD(oldlist, newframe, entries); @@ -967,6 +975,7 @@ static int gosub_run(struct ast_channel *chan, const char *sub_args, int ignore_ int saved_priority; int saved_hangup_flags; int saved_autoloopflag; + int saved_in_subroutine; int res; ast_channel_lock(chan); @@ -990,6 +999,9 @@ static int gosub_run(struct ast_channel *chan, const char *sub_args, int ignore_ 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 @@ static int gosub_run(struct ast_channel *chan, const char *sub_args, int ignore_ /* 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 @@ static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, const char int res; int priority; int old_autoloopflag; + int old_in_subroutine; int old_priority; const char *old_context; const char *old_extension; @@ -1154,6 +1170,9 @@ static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, const char 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)); old_extension = ast_strdupa(ast_channel_exten(chan)); @@ -1246,6 +1265,9 @@ static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, const char /* 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; |