2005-11-08 23:37:53 +00:00
|
|
|
/*
|
|
|
|
* Asterisk -- An open source telephony toolkit.
|
|
|
|
*
|
2006-09-26 17:25:27 +00:00
|
|
|
* Copyright (c) 2004-2006 Tilghman Lesher <app_stack_v003@the-tilghman.com>.
|
2005-11-08 23:37:53 +00:00
|
|
|
*
|
|
|
|
* This code is released by the author with no restrictions on usage.
|
|
|
|
*
|
|
|
|
* See http://www.asterisk.org for more information about
|
|
|
|
* the Asterisk project. Please do not directly contact
|
|
|
|
* any of the maintainers of this project for assistance;
|
|
|
|
* the project provides a web site, mailing lists and IRC
|
|
|
|
* channels for your use.
|
|
|
|
*
|
|
|
|
* This program is free software, distributed under the terms of
|
|
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
|
|
* at the top of the source tree.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*! \file
|
|
|
|
*
|
|
|
|
* \brief Stack applications Gosub, Return, etc.
|
2005-12-30 21:18:06 +00:00
|
|
|
*
|
2006-09-26 17:25:27 +00:00
|
|
|
* \author Tilghman Lesher <app_stack_v003@the-tilghman.com>
|
2017-12-22 14:23:22 +00:00
|
|
|
*
|
2005-11-08 23:37:53 +00:00
|
|
|
* \ingroup applications
|
|
|
|
*/
|
|
|
|
|
2008-10-15 08:55:47 +00:00
|
|
|
/*** MODULEINFO
|
2011-07-05 22:11:40 +00:00
|
|
|
<use type="module">res_agi</use>
|
2011-07-14 20:28:54 +00:00
|
|
|
<support_level>core</support_level>
|
2008-10-15 08:55:47 +00:00
|
|
|
***/
|
|
|
|
|
2006-06-07 18:54:56 +00:00
|
|
|
#include "asterisk.h"
|
2017-12-22 14:23:22 +00:00
|
|
|
|
2005-11-08 23:37:53 +00:00
|
|
|
#include "asterisk/pbx.h"
|
|
|
|
#include "asterisk/module.h"
|
2006-09-26 17:25:27 +00:00
|
|
|
#include "asterisk/app.h"
|
2007-06-20 04:36:23 +00:00
|
|
|
#include "asterisk/manager.h"
|
2007-11-22 03:50:04 +00:00
|
|
|
#include "asterisk/channel.h"
|
2008-05-30 16:10:46 +00:00
|
|
|
#include "asterisk/agi.h"
|
2013-05-02 20:59:20 +00:00
|
|
|
#include "asterisk/stasis_channels.h"
|
2005-11-08 23:37:53 +00:00
|
|
|
|
2008-11-01 21:10:07 +00:00
|
|
|
/*** DOCUMENTATION
|
|
|
|
<application name="Gosub" language="en_US">
|
|
|
|
<synopsis>
|
|
|
|
Jump to label, saving return address.
|
|
|
|
</synopsis>
|
|
|
|
<syntax>
|
|
|
|
<parameter name="context" />
|
|
|
|
<parameter name="exten" />
|
|
|
|
<parameter name="priority" required="true" hasparams="optional">
|
|
|
|
<argument name="arg1" multiple="true" required="true" />
|
|
|
|
<argument name="argN" />
|
|
|
|
</parameter>
|
|
|
|
</syntax>
|
|
|
|
<description>
|
|
|
|
<para>Jumps to the label specified, saving the return address.</para>
|
|
|
|
</description>
|
2008-11-05 13:07:29 +00:00
|
|
|
<see-also>
|
|
|
|
<ref type="application">GosubIf</ref>
|
|
|
|
<ref type="application">Goto</ref>
|
|
|
|
<ref type="application">Return</ref>
|
|
|
|
<ref type="application">StackPop</ref>
|
|
|
|
</see-also>
|
2008-11-01 21:10:07 +00:00
|
|
|
</application>
|
|
|
|
<application name="GosubIf" language="en_US">
|
|
|
|
<synopsis>
|
|
|
|
Conditionally jump to label, saving return address.
|
|
|
|
</synopsis>
|
|
|
|
<syntax argsep="?">
|
|
|
|
<parameter name="condition" required="true" />
|
|
|
|
<parameter name="destination" required="true" argsep=":">
|
|
|
|
<argument name="labeliftrue" hasparams="optional">
|
2012-07-10 13:40:32 +00:00
|
|
|
<para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
|
|
|
|
Takes the form similar to Goto() of [[context,]extension,]priority.</para>
|
2008-11-01 21:10:07 +00:00
|
|
|
<argument name="arg1" required="true" multiple="true" />
|
|
|
|
<argument name="argN" />
|
|
|
|
</argument>
|
|
|
|
<argument name="labeliffalse" hasparams="optional">
|
2012-07-10 13:40:32 +00:00
|
|
|
<para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
|
|
|
|
Takes the form similar to Goto() of [[context,]extension,]priority.</para>
|
2008-11-01 21:10:07 +00:00
|
|
|
<argument name="arg1" required="true" multiple="true" />
|
|
|
|
<argument name="argN" />
|
|
|
|
</argument>
|
|
|
|
</parameter>
|
|
|
|
</syntax>
|
|
|
|
<description>
|
|
|
|
<para>If the condition is true, then jump to labeliftrue. If false, jumps to
|
|
|
|
labeliffalse, if specified. In either case, a jump saves the return point
|
|
|
|
in the dialplan, to be returned to with a Return.</para>
|
|
|
|
</description>
|
2008-11-05 13:07:29 +00:00
|
|
|
<see-also>
|
|
|
|
<ref type="application">Gosub</ref>
|
|
|
|
<ref type="application">Return</ref>
|
|
|
|
<ref type="function">IF</ref>
|
|
|
|
<ref type="application">GotoIf</ref>
|
2012-07-10 13:40:32 +00:00
|
|
|
<ref type="application">Goto</ref>
|
2008-11-05 13:07:29 +00:00
|
|
|
</see-also>
|
2008-11-01 21:10:07 +00:00
|
|
|
</application>
|
|
|
|
<application name="Return" language="en_US">
|
|
|
|
<synopsis>
|
|
|
|
Return from gosub routine.
|
|
|
|
</synopsis>
|
|
|
|
<syntax>
|
|
|
|
<parameter name="value">
|
|
|
|
<para>Return value.</para>
|
|
|
|
</parameter>
|
|
|
|
</syntax>
|
|
|
|
<description>
|
|
|
|
<para>Jumps to the last label on the stack, removing it. The return <replaceable>value</replaceable>, if
|
|
|
|
any, is saved in the channel variable <variable>GOSUB_RETVAL</variable>.</para>
|
|
|
|
</description>
|
2008-11-05 13:07:29 +00:00
|
|
|
<see-also>
|
|
|
|
<ref type="application">Gosub</ref>
|
|
|
|
<ref type="application">StackPop</ref>
|
|
|
|
</see-also>
|
2008-11-01 21:10:07 +00:00
|
|
|
</application>
|
|
|
|
<application name="StackPop" language="en_US">
|
|
|
|
<synopsis>
|
|
|
|
Remove one address from gosub stack.
|
|
|
|
</synopsis>
|
|
|
|
<syntax />
|
|
|
|
<description>
|
|
|
|
<para>Removes last label on the stack, discarding it.</para>
|
|
|
|
</description>
|
2008-11-05 13:07:29 +00:00
|
|
|
<see-also>
|
|
|
|
<ref type="application">Return</ref>
|
|
|
|
<ref type="application">Gosub</ref>
|
|
|
|
</see-also>
|
2008-11-01 21:10:07 +00:00
|
|
|
</application>
|
2008-11-03 17:11:22 +00:00
|
|
|
<function name="LOCAL" language="en_US">
|
|
|
|
<synopsis>
|
|
|
|
Manage variables local to the gosub stack frame.
|
|
|
|
</synopsis>
|
|
|
|
<syntax>
|
|
|
|
<parameter name="varname" required="true" />
|
|
|
|
</syntax>
|
|
|
|
<description>
|
|
|
|
<para>Read and write a variable local to the gosub stack frame, once we Return() it will be lost
|
|
|
|
(or it will go back to whatever value it had before the Gosub()).</para>
|
|
|
|
</description>
|
|
|
|
<see-also>
|
|
|
|
<ref type="application">Gosub</ref>
|
|
|
|
<ref type="application">GosubIf</ref>
|
|
|
|
<ref type="application">Return</ref>
|
|
|
|
</see-also>
|
|
|
|
</function>
|
2008-12-02 18:39:12 +00:00
|
|
|
<function name="LOCAL_PEEK" language="en_US">
|
|
|
|
<synopsis>
|
|
|
|
Retrieve variables hidden by the local gosub stack frame.
|
|
|
|
</synopsis>
|
|
|
|
<syntax>
|
|
|
|
<parameter name="n" required="true" />
|
|
|
|
<parameter name="varname" required="true" />
|
|
|
|
</syntax>
|
|
|
|
<description>
|
2008-12-03 11:01:23 +00:00
|
|
|
<para>Read a variable <replaceable>varname</replaceable> hidden by
|
2008-12-02 18:39:12 +00:00
|
|
|
<replaceable>n</replaceable> levels of gosub stack frames. Note that ${LOCAL_PEEK(0,foo)}
|
2008-12-03 11:01:23 +00:00
|
|
|
is the same as <variable>foo</variable>, since the value of <replaceable>n</replaceable>
|
|
|
|
peeks under 0 levels of stack frames; in other words, 0 is the current level. If
|
|
|
|
<replaceable>n</replaceable> exceeds the available number of stack frames, then an empty
|
|
|
|
string is returned.</para>
|
2008-12-02 18:39:12 +00:00
|
|
|
</description>
|
|
|
|
<see-also>
|
|
|
|
<ref type="application">Gosub</ref>
|
|
|
|
<ref type="application">GosubIf</ref>
|
|
|
|
<ref type="application">Return</ref>
|
|
|
|
</see-also>
|
|
|
|
</function>
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
<function name="STACK_PEEK" language="en_US">
|
|
|
|
<synopsis>
|
|
|
|
View info about the location which called Gosub
|
|
|
|
</synopsis>
|
|
|
|
<syntax>
|
|
|
|
<parameter name="n" required="true" />
|
|
|
|
<parameter name="which" required="true" />
|
|
|
|
<parameter name="suppress" required="false" />
|
|
|
|
</syntax>
|
|
|
|
<description>
|
|
|
|
<para>Read the calling <literal>c</literal>ontext, <literal>e</literal>xtension,
|
|
|
|
<literal>p</literal>riority, or <literal>l</literal>abel, as specified by
|
|
|
|
<replaceable>which</replaceable>, by going up <replaceable>n</replaceable> frames
|
|
|
|
in the Gosub stack. If <replaceable>suppress</replaceable> is true, then if the
|
|
|
|
number of available stack frames is exceeded, then no error message will be
|
|
|
|
printed.</para>
|
|
|
|
</description>
|
|
|
|
</function>
|
2009-06-06 23:28:38 +00:00
|
|
|
<agi name="gosub" language="en_US">
|
|
|
|
<synopsis>
|
|
|
|
Cause the channel to execute the specified dialplan subroutine.
|
|
|
|
</synopsis>
|
|
|
|
<syntax>
|
|
|
|
<parameter name="context" required="true" />
|
|
|
|
<parameter name="extension" required="true" />
|
|
|
|
<parameter name="priority" required="true" />
|
|
|
|
<parameter name="optional-argument" />
|
|
|
|
</syntax>
|
|
|
|
<description>
|
|
|
|
<para>Cause the channel to execute the specified dialplan subroutine,
|
|
|
|
returning to the dialplan with execution of a Return().</para>
|
|
|
|
</description>
|
2013-05-02 20:59:20 +00:00
|
|
|
<see-also>
|
|
|
|
<ref type="application">GoSub</ref>
|
|
|
|
</see-also>
|
2009-06-06 23:28:38 +00:00
|
|
|
</agi>
|
2013-05-02 20:59:20 +00:00
|
|
|
<managerEvent language="en_US" name="VarSet">
|
|
|
|
<managerEventInstance class="EVENT_FLAG_DIALPLAN">
|
|
|
|
<synopsis>Raised when a variable local to the gosub stack frame is set due to a subroutine call.</synopsis>
|
|
|
|
<syntax>
|
2013-08-01 17:07:52 +00:00
|
|
|
<channel_snapshot/>
|
2013-05-02 20:59:20 +00:00
|
|
|
<parameter name="Variable">
|
|
|
|
<para>The LOCAL variable being set.</para>
|
|
|
|
<note><para>The variable name will always be enclosed with
|
|
|
|
<literal>LOCAL()</literal></para></note>
|
|
|
|
</parameter>
|
|
|
|
<parameter name="Value">
|
|
|
|
<para>The new value of the variable.</para>
|
|
|
|
</parameter>
|
|
|
|
</syntax>
|
|
|
|
<see-also>
|
|
|
|
<ref type="application">GoSub</ref>
|
|
|
|
<ref type="agi">gosub</ref>
|
|
|
|
<ref type="function">LOCAL</ref>
|
|
|
|
<ref type="function">LOCAL_PEEK</ref>
|
|
|
|
</see-also>
|
|
|
|
</managerEventInstance>
|
|
|
|
</managerEvent>
|
2008-11-01 21:10:07 +00:00
|
|
|
***/
|
2008-06-05 15:58:11 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
static const char app_gosub[] = "Gosub";
|
|
|
|
static const char app_gosubif[] = "GosubIf";
|
|
|
|
static const char app_return[] = "Return";
|
|
|
|
static const char app_pop[] = "StackPop";
|
2005-11-08 23:37:53 +00:00
|
|
|
|
2007-03-03 16:43:36 +00:00
|
|
|
static void gosub_free(void *data);
|
|
|
|
|
2012-07-18 17:18:20 +00:00
|
|
|
static const struct ast_datastore_info stack_info = {
|
2007-03-03 16:43:36 +00:00
|
|
|
.type = "GOSUB",
|
|
|
|
.destroy = gosub_free,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct gosub_stack_frame {
|
|
|
|
AST_LIST_ENTRY(gosub_stack_frame) entries;
|
|
|
|
/* 100 arguments is all that we support anyway, but this will handle up to 255 */
|
|
|
|
unsigned char arguments;
|
2007-06-20 04:36:23 +00:00
|
|
|
struct varshead varshead;
|
2007-03-03 16:43:36 +00:00
|
|
|
int priority;
|
2012-06-14 23:22:53 +00:00
|
|
|
/*! TRUE if the return location marks the end of a special routine. */
|
|
|
|
unsigned int is_special:1;
|
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
2014-09-05 22:04:33 +00:00
|
|
|
/*! Whether or not we were in a subroutine when this one was created */
|
|
|
|
unsigned int in_subroutine:1;
|
2007-03-03 16:43:36 +00:00
|
|
|
char *context;
|
|
|
|
char extension[0];
|
|
|
|
};
|
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
AST_LIST_HEAD(gosub_stack_list, gosub_stack_frame);
|
|
|
|
|
2007-06-20 13:00:45 +00:00
|
|
|
static int frame_set_var(struct ast_channel *chan, struct gosub_stack_frame *frame, const char *var, const char *value)
|
|
|
|
{
|
|
|
|
struct ast_var_t *variables;
|
|
|
|
int found = 0;
|
2013-05-02 20:59:20 +00:00
|
|
|
int len;
|
|
|
|
RAII_VAR(char *, local_buffer, NULL, ast_free);
|
2007-06-20 13:00:45 +00:00
|
|
|
|
|
|
|
/* Does this variable already exist? */
|
|
|
|
AST_LIST_TRAVERSE(&frame->varshead, variables, entries) {
|
|
|
|
if (!strcmp(var, ast_var_name(variables))) {
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-20 23:30:05 +00:00
|
|
|
if (!found) {
|
2013-08-06 08:36:15 +00:00
|
|
|
if ((variables = ast_var_assign(var, ""))) {
|
|
|
|
AST_LIST_INSERT_HEAD(&frame->varshead, variables, entries);
|
|
|
|
}
|
2009-05-20 23:30:05 +00:00
|
|
|
pbx_builtin_pushvar_helper(chan, var, value);
|
|
|
|
} else {
|
|
|
|
pbx_builtin_setvar_helper(chan, var, value);
|
2007-06-20 13:00:45 +00:00
|
|
|
}
|
2009-05-20 23:30:05 +00:00
|
|
|
|
2013-05-02 20:59:20 +00:00
|
|
|
len = 8 + strlen(var); /* LOCAL() + var */
|
|
|
|
local_buffer = ast_malloc(len);
|
|
|
|
if (!local_buffer) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
sprintf(local_buffer, "LOCAL(%s)", var);
|
|
|
|
ast_channel_publish_varset(chan, local_buffer, value);
|
2007-06-20 13:00:45 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-03-03 16:43:36 +00:00
|
|
|
static void gosub_release_frame(struct ast_channel *chan, struct gosub_stack_frame *frame)
|
2005-11-08 23:37:53 +00:00
|
|
|
{
|
2007-06-20 04:36:23 +00:00
|
|
|
struct ast_var_t *vardata;
|
2006-09-26 17:25:27 +00:00
|
|
|
|
2007-03-03 16:43:36 +00:00
|
|
|
/* If chan is not defined, then we're calling it as part of gosub_free,
|
|
|
|
* and the channel variables will be deallocated anyway. Otherwise, we're
|
|
|
|
* just releasing a single frame, so we need to clean up the arguments for
|
|
|
|
* that frame, so that we re-expose the variables from the previous frame
|
|
|
|
* that were hidden by this one.
|
|
|
|
*/
|
2007-06-20 05:47:05 +00:00
|
|
|
while ((vardata = AST_LIST_REMOVE_HEAD(&frame->varshead, entries))) {
|
|
|
|
if (chan)
|
2017-12-22 14:23:22 +00:00
|
|
|
pbx_builtin_setvar_helper(chan, ast_var_name(vardata), NULL);
|
2007-06-20 04:36:23 +00:00
|
|
|
ast_var_delete(vardata);
|
2007-06-20 05:47:05 +00:00
|
|
|
}
|
2007-06-20 04:36:23 +00:00
|
|
|
|
2007-03-03 16:43:36 +00:00
|
|
|
ast_free(frame);
|
|
|
|
}
|
2006-09-26 17:25:27 +00:00
|
|
|
|
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
2014-09-05 22:04:33 +00:00
|
|
|
static struct gosub_stack_frame *gosub_allocate_frame(const char *context, const char *extension, int priority, int in_subroutine, unsigned char arguments)
|
2007-03-03 16:43:36 +00:00
|
|
|
{
|
|
|
|
struct gosub_stack_frame *new = NULL;
|
2020-06-01 23:25:48 +00:00
|
|
|
int len_extension = strlen(extension) + 1;
|
|
|
|
int len_context = strlen(context) + 1;
|
2007-03-03 16:43:36 +00:00
|
|
|
|
2020-06-01 23:25:48 +00:00
|
|
|
if ((new = ast_calloc(1, sizeof(*new) + len_extension + len_context))) {
|
2007-06-20 04:36:23 +00:00
|
|
|
AST_LIST_HEAD_INIT_NOLOCK(&new->varshead);
|
2020-06-01 23:25:48 +00:00
|
|
|
ast_copy_string(new->extension, extension, len_extension);
|
|
|
|
new->context = new->extension + len_extension;
|
|
|
|
ast_copy_string(new->context, context, len_context);
|
2007-03-03 16:43:36 +00:00
|
|
|
new->priority = priority;
|
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
2014-09-05 22:04:33 +00:00
|
|
|
new->in_subroutine = in_subroutine ? 1 : 0;
|
2007-03-03 16:43:36 +00:00
|
|
|
new->arguments = arguments;
|
|
|
|
}
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void gosub_free(void *data)
|
|
|
|
{
|
2012-06-14 23:22:53 +00:00
|
|
|
struct gosub_stack_list *oldlist = data;
|
2007-03-03 16:43:36 +00:00
|
|
|
struct gosub_stack_frame *oldframe;
|
2012-06-14 23:22:53 +00:00
|
|
|
|
2007-03-03 16:43:36 +00:00
|
|
|
AST_LIST_LOCK(oldlist);
|
|
|
|
while ((oldframe = AST_LIST_REMOVE_HEAD(oldlist, entries))) {
|
|
|
|
gosub_release_frame(NULL, oldframe);
|
|
|
|
}
|
|
|
|
AST_LIST_UNLOCK(oldlist);
|
|
|
|
AST_LIST_HEAD_DESTROY(oldlist);
|
|
|
|
ast_free(oldlist);
|
|
|
|
}
|
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
static int pop_exec(struct ast_channel *chan, const char *data)
|
2007-03-03 16:43:36 +00:00
|
|
|
{
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
struct ast_datastore *stack_store;
|
2007-03-03 16:43:36 +00:00
|
|
|
struct gosub_stack_frame *oldframe;
|
2012-06-14 23:22:53 +00:00
|
|
|
struct gosub_stack_list *oldlist;
|
|
|
|
int res = 0;
|
2007-03-03 16:43:36 +00:00
|
|
|
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_lock(chan);
|
|
|
|
if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
|
2007-03-03 16:43:36 +00:00
|
|
|
ast_log(LOG_WARNING, "%s called with no gosub stack allocated.\n", app_pop);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2007-03-03 16:43:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
oldlist = stack_store->data;
|
|
|
|
AST_LIST_LOCK(oldlist);
|
2012-06-14 23:22:53 +00:00
|
|
|
oldframe = AST_LIST_FIRST(oldlist);
|
2007-06-14 19:39:12 +00:00
|
|
|
if (oldframe) {
|
2012-06-14 23:22:53 +00:00
|
|
|
if (oldframe->is_special) {
|
|
|
|
ast_debug(1, "%s attempted to pop special return location.\n", app_pop);
|
|
|
|
|
|
|
|
/* Abort the special routine dialplan execution. Dialplan programming error. */
|
|
|
|
res = -1;
|
|
|
|
} else {
|
|
|
|
AST_LIST_REMOVE_HEAD(oldlist, entries);
|
|
|
|
gosub_release_frame(chan, oldframe);
|
|
|
|
}
|
2007-06-14 19:39:12 +00:00
|
|
|
} else {
|
|
|
|
ast_debug(1, "%s called with an empty gosub stack\n", app_pop);
|
|
|
|
}
|
2012-06-14 23:22:53 +00:00
|
|
|
AST_LIST_UNLOCK(oldlist);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2012-06-14 23:22:53 +00:00
|
|
|
return res;
|
2005-11-08 23:37:53 +00:00
|
|
|
}
|
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
static int return_exec(struct ast_channel *chan, const char *data)
|
2005-11-08 23:37:53 +00:00
|
|
|
{
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
struct ast_datastore *stack_store;
|
2007-03-03 16:43:36 +00:00
|
|
|
struct gosub_stack_frame *oldframe;
|
2012-06-14 23:22:53 +00:00
|
|
|
struct gosub_stack_list *oldlist;
|
2009-05-21 21:13:09 +00:00
|
|
|
const char *retval = data;
|
2009-11-10 21:22:50 +00:00
|
|
|
int res = 0;
|
2005-11-08 23:37:53 +00:00
|
|
|
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_lock(chan);
|
|
|
|
if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
|
2007-03-03 16:43:36 +00:00
|
|
|
ast_log(LOG_ERROR, "Return without Gosub: stack is unallocated\n");
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2005-11-08 23:37:53 +00:00
|
|
|
return -1;
|
2006-09-26 17:25:27 +00:00
|
|
|
}
|
|
|
|
|
2007-03-03 16:43:36 +00:00
|
|
|
oldlist = stack_store->data;
|
|
|
|
AST_LIST_LOCK(oldlist);
|
|
|
|
oldframe = AST_LIST_REMOVE_HEAD(oldlist, entries);
|
|
|
|
AST_LIST_UNLOCK(oldlist);
|
2006-09-26 17:25:27 +00:00
|
|
|
|
2007-03-03 16:43:36 +00:00
|
|
|
if (!oldframe) {
|
|
|
|
ast_log(LOG_ERROR, "Return without Gosub: stack is empty\n");
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2005-11-08 23:37:53 +00:00
|
|
|
return -1;
|
2012-06-14 23:22:53 +00:00
|
|
|
}
|
|
|
|
if (oldframe->is_special) {
|
|
|
|
/* Exit from special routine. */
|
2009-11-10 21:22:50 +00:00
|
|
|
res = -1;
|
2005-11-08 23:37:53 +00:00
|
|
|
}
|
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
/*
|
|
|
|
* We cannot use ast_explicit_goto() because we MUST restore
|
|
|
|
* what was there before. Channels that do not have a PBX may
|
|
|
|
* not have the context or exten set.
|
|
|
|
*/
|
2023-08-10 16:51:12 +00:00
|
|
|
ast_channel_context_set(chan, oldframe->context);
|
|
|
|
ast_channel_exten_set(chan, oldframe->extension);
|
|
|
|
if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
|
|
|
|
--oldframe->priority;
|
2012-06-14 23:22:53 +00:00
|
|
|
}
|
2023-08-10 16:51:12 +00:00
|
|
|
ast_channel_priority_set(chan, oldframe->priority);
|
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
2014-09-05 22:04:33 +00:00
|
|
|
ast_set2_flag(ast_channel_flags(chan), oldframe->in_subroutine, AST_FLAG_SUBROUTINE_EXEC);
|
2012-06-14 23:22:53 +00:00
|
|
|
|
2007-03-03 16:43:36 +00:00
|
|
|
gosub_release_frame(chan, oldframe);
|
2006-09-26 17:25:27 +00:00
|
|
|
|
|
|
|
/* Set a return value, if any */
|
|
|
|
pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", S_OR(retval, ""));
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2009-11-10 21:22:50 +00:00
|
|
|
return res;
|
2005-11-08 23:37:53 +00:00
|
|
|
}
|
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
/*!
|
|
|
|
* \internal
|
|
|
|
* \brief Add missing context and/or exten to Gosub application argument string.
|
|
|
|
* \since 11.0
|
|
|
|
*
|
|
|
|
* \param chan Channel to obtain context/exten.
|
|
|
|
* \param args Gosub application argument string.
|
|
|
|
*
|
|
|
|
* \details
|
|
|
|
* Fills in the optional context and exten from the given channel.
|
|
|
|
* Convert: [[context,]exten,]priority[(arg1[,...][,argN])]
|
|
|
|
* To: context,exten,priority[(arg1[,...][,argN])]
|
|
|
|
*
|
|
|
|
* \retval expanded Gosub argument string on success. Must be freed.
|
|
|
|
* \retval NULL on error.
|
|
|
|
*
|
|
|
|
* \note The parsing needs to be kept in sync with the
|
|
|
|
* gosub_exec() argument format.
|
|
|
|
*/
|
|
|
|
static const char *expand_gosub_args(struct ast_channel *chan, const char *args)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char *parse;
|
|
|
|
char *label;
|
|
|
|
char *new_args;
|
|
|
|
const char *context;
|
|
|
|
const char *exten;
|
|
|
|
const char *pri;
|
|
|
|
|
|
|
|
/* Separate the context,exten,pri from the optional routine arguments. */
|
|
|
|
parse = ast_strdupa(args);
|
|
|
|
label = strsep(&parse, "(");
|
|
|
|
if (parse) {
|
|
|
|
char *endparen;
|
|
|
|
|
|
|
|
endparen = strrchr(parse, ')');
|
|
|
|
if (endparen) {
|
|
|
|
*endparen = '\0';
|
|
|
|
} else {
|
|
|
|
ast_log(LOG_WARNING, "Ouch. No closing paren: '%s'?\n", args);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Split context,exten,pri */
|
|
|
|
context = strsep(&label, ",");
|
|
|
|
exten = strsep(&label, ",");
|
|
|
|
pri = strsep(&label, ",");
|
|
|
|
if (!exten) {
|
|
|
|
/* Only a priority in this one */
|
|
|
|
pri = context;
|
|
|
|
exten = NULL;
|
|
|
|
context = NULL;
|
|
|
|
} else if (!pri) {
|
|
|
|
/* Only an extension and priority in this one */
|
|
|
|
pri = exten;
|
|
|
|
exten = context;
|
|
|
|
context = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
if (ast_strlen_zero(exten)) {
|
|
|
|
exten = ast_channel_exten(chan);
|
|
|
|
}
|
|
|
|
if (ast_strlen_zero(context)) {
|
|
|
|
context = ast_channel_context(chan);
|
|
|
|
}
|
|
|
|
len = strlen(context) + strlen(exten) + strlen(pri) + 3;
|
|
|
|
if (!ast_strlen_zero(parse)) {
|
|
|
|
len += 2 + strlen(parse);
|
|
|
|
}
|
|
|
|
new_args = ast_malloc(len);
|
|
|
|
if (new_args) {
|
|
|
|
if (ast_strlen_zero(parse)) {
|
|
|
|
snprintf(new_args, len, "%s,%s,%s", context, exten, pri);
|
|
|
|
} else {
|
|
|
|
snprintf(new_args, len, "%s,%s,%s(%s)", context, exten, pri, parse);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
|
|
|
ast_debug(4, "Gosub args:%s new_args:%s\n", args, new_args ? new_args : "");
|
|
|
|
|
|
|
|
return new_args;
|
|
|
|
}
|
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
static int gosub_exec(struct ast_channel *chan, const char *data)
|
2005-11-08 23:37:53 +00:00
|
|
|
{
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
struct ast_datastore *stack_store;
|
2012-06-14 23:22:53 +00:00
|
|
|
struct gosub_stack_list *oldlist;
|
2012-06-01 23:53:59 +00:00
|
|
|
struct gosub_stack_frame *newframe;
|
|
|
|
struct gosub_stack_frame *lastframe;
|
|
|
|
char argname[15];
|
|
|
|
char *parse;
|
|
|
|
char *label;
|
|
|
|
char *caller_id;
|
|
|
|
char *orig_context;
|
|
|
|
char *orig_exten;
|
|
|
|
char *dest_context;
|
|
|
|
char *dest_exten;
|
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
2014-09-05 22:04:33 +00:00
|
|
|
int orig_in_subroutine;
|
2012-06-01 23:53:59 +00:00
|
|
|
int orig_priority;
|
|
|
|
int dest_priority;
|
|
|
|
int i;
|
|
|
|
int max_argc = 0;
|
2006-09-26 17:25:27 +00:00
|
|
|
AST_DECLARE_APP_ARGS(args2,
|
|
|
|
AST_APP_ARG(argval)[100];
|
|
|
|
);
|
2005-11-08 23:37:53 +00:00
|
|
|
|
|
|
|
if (ast_strlen_zero(data)) {
|
2008-05-30 16:10:46 +00:00
|
|
|
ast_log(LOG_ERROR, "%s requires an argument: %s([[context,]exten,]priority[(arg1[,...][,argN])])\n", app_gosub, app_gosub);
|
2005-11-08 23:37:53 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-06-01 23:53:59 +00:00
|
|
|
/*
|
|
|
|
* Separate the arguments from the label
|
|
|
|
*
|
|
|
|
* NOTE: You cannot use ast_app_separate_args for this, because
|
|
|
|
* '(' cannot be used as a delimiter.
|
|
|
|
*/
|
|
|
|
parse = ast_strdupa(data);
|
|
|
|
label = strsep(&parse, "(");
|
|
|
|
if (parse) {
|
|
|
|
char *endparen;
|
|
|
|
|
|
|
|
endparen = strrchr(parse, ')');
|
|
|
|
if (endparen) {
|
|
|
|
*endparen = '\0';
|
|
|
|
} else {
|
|
|
|
ast_log(LOG_WARNING, "Ouch. No closing paren: '%s'?\n", data);
|
|
|
|
}
|
|
|
|
AST_STANDARD_RAW_ARGS(args2, parse);
|
|
|
|
} else {
|
|
|
|
args2.argc = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
orig_context = ast_strdupa(ast_channel_context(chan));
|
|
|
|
orig_exten = ast_strdupa(ast_channel_exten(chan));
|
|
|
|
orig_priority = ast_channel_priority(chan);
|
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
2014-09-05 22:04:33 +00:00
|
|
|
orig_in_subroutine = ast_test_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
|
2012-06-01 23:53:59 +00:00
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
|
|
|
if (ast_parseable_goto(chan, label)) {
|
|
|
|
ast_log(LOG_ERROR, "%s address is invalid: '%s'\n", app_gosub, data);
|
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
dest_context = ast_strdupa(ast_channel_context(chan));
|
|
|
|
dest_exten = ast_strdupa(ast_channel_exten(chan));
|
|
|
|
dest_priority = ast_channel_priority(chan);
|
|
|
|
if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
|
|
|
|
++dest_priority;
|
|
|
|
}
|
|
|
|
caller_id = S_COR(ast_channel_caller(chan)->id.number.valid,
|
|
|
|
ast_channel_caller(chan)->id.number.str, NULL);
|
|
|
|
if (caller_id) {
|
|
|
|
caller_id = ast_strdupa(caller_id);
|
|
|
|
}
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
|
|
|
if (!ast_exists_extension(chan, dest_context, dest_exten, dest_priority, caller_id)) {
|
2021-09-02 23:20:43 +00:00
|
|
|
ast_log(LOG_ERROR, "%s attempted to reach non-existent destination '%s,%s,%d' from '%s,%s,%d'",
|
|
|
|
app_gosub, dest_context, dest_exten, dest_priority, orig_context, orig_exten, orig_priority);
|
2012-06-01 23:53:59 +00:00
|
|
|
goto error_exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now we know that we're going to a new location */
|
|
|
|
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_lock(chan);
|
2012-06-01 23:53:59 +00:00
|
|
|
|
|
|
|
/* Find stack datastore return list. */
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
|
2012-06-01 23:53:59 +00:00
|
|
|
ast_debug(1, "Channel %s has no datastore, so we're allocating one.\n",
|
|
|
|
ast_channel_name(chan));
|
2008-08-05 16:56:11 +00:00
|
|
|
stack_store = ast_datastore_alloc(&stack_info, NULL);
|
2007-03-03 16:43:36 +00:00
|
|
|
if (!stack_store) {
|
2012-06-01 23:53:59 +00:00
|
|
|
ast_log(LOG_ERROR, "Unable to allocate new datastore. %s failed.\n",
|
|
|
|
app_gosub);
|
|
|
|
goto error_exit_locked;
|
2007-03-03 16:43:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
oldlist = ast_calloc(1, sizeof(*oldlist));
|
|
|
|
if (!oldlist) {
|
2012-06-01 23:53:59 +00:00
|
|
|
ast_log(LOG_ERROR, "Unable to allocate datastore list head. %s failed.\n",
|
|
|
|
app_gosub);
|
2008-08-05 16:56:11 +00:00
|
|
|
ast_datastore_free(stack_store);
|
2012-06-01 23:53:59 +00:00
|
|
|
goto error_exit_locked;
|
2007-03-03 16:43:36 +00:00
|
|
|
}
|
2012-06-01 23:53:59 +00:00
|
|
|
AST_LIST_HEAD_INIT(oldlist);
|
2007-03-03 16:43:36 +00:00
|
|
|
|
|
|
|
stack_store->data = oldlist;
|
|
|
|
ast_channel_datastore_add(chan, stack_store);
|
2010-03-16 23:49:35 +00:00
|
|
|
} else {
|
|
|
|
oldlist = stack_store->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((lastframe = AST_LIST_FIRST(oldlist))) {
|
|
|
|
max_argc = lastframe->arguments;
|
2007-03-03 16:43:36 +00:00
|
|
|
}
|
|
|
|
|
2012-06-01 23:53:59 +00:00
|
|
|
/* Mask out previous Gosub arguments in this invocation */
|
2010-03-16 23:49:35 +00:00
|
|
|
if (args2.argc > max_argc) {
|
|
|
|
max_argc = args2.argc;
|
|
|
|
}
|
|
|
|
|
2012-06-01 23:53:59 +00:00
|
|
|
/* Create the return address */
|
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
2014-09-05 22:04:33 +00:00
|
|
|
newframe = gosub_allocate_frame(orig_context, orig_exten, orig_priority + 1, orig_in_subroutine, max_argc);
|
2008-12-03 18:37:46 +00:00
|
|
|
if (!newframe) {
|
2012-06-01 23:53:59 +00:00
|
|
|
goto error_exit_locked;
|
2008-12-03 18:37:46 +00:00
|
|
|
}
|
2007-06-20 13:00:45 +00:00
|
|
|
|
2012-06-01 23:53:59 +00:00
|
|
|
/* Set our arguments */
|
2010-03-16 23:49:35 +00:00
|
|
|
for (i = 0; i < max_argc; i++) {
|
2006-09-26 17:25:27 +00:00
|
|
|
snprintf(argname, sizeof(argname), "ARG%d", i + 1);
|
2010-03-16 23:49:35 +00:00
|
|
|
frame_set_var(chan, newframe, argname, i < args2.argc ? args2.argval[i] : "");
|
|
|
|
ast_debug(1, "Setting '%s' to '%s'\n", argname, i < args2.argc ? args2.argval[i] : "");
|
2006-09-26 17:25:27 +00:00
|
|
|
}
|
2014-05-09 22:49:26 +00:00
|
|
|
snprintf(argname, sizeof(argname), "%u", args2.argc);
|
2008-10-27 16:44:55 +00:00
|
|
|
frame_set_var(chan, newframe, "ARGC", argname);
|
2006-09-26 17:25:27 +00:00
|
|
|
|
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
2014-09-05 22:04:33 +00:00
|
|
|
ast_set_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
|
|
|
|
|
2006-10-02 04:17:57 +00:00
|
|
|
/* And finally, save our return address */
|
2007-03-03 16:43:36 +00:00
|
|
|
AST_LIST_LOCK(oldlist);
|
|
|
|
AST_LIST_INSERT_HEAD(oldlist, newframe, entries);
|
|
|
|
AST_LIST_UNLOCK(oldlist);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2007-03-03 16:43:36 +00:00
|
|
|
|
2005-11-08 23:37:53 +00:00
|
|
|
return 0;
|
2012-06-01 23:53:59 +00:00
|
|
|
|
|
|
|
error_exit:
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
|
|
|
|
error_exit_locked:
|
|
|
|
/* Restore the original dialplan location. */
|
|
|
|
ast_channel_context_set(chan, orig_context);
|
|
|
|
ast_channel_exten_set(chan, orig_exten);
|
|
|
|
ast_channel_priority_set(chan, orig_priority);
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
return -1;
|
2005-11-08 23:37:53 +00:00
|
|
|
}
|
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
static int gosubif_exec(struct ast_channel *chan, const char *data)
|
2005-11-08 23:37:53 +00:00
|
|
|
{
|
2006-10-02 22:02:45 +00:00
|
|
|
char *args;
|
2005-11-08 23:37:53 +00:00
|
|
|
int res=0;
|
2006-10-02 22:02:45 +00:00
|
|
|
AST_DECLARE_APP_ARGS(cond,
|
|
|
|
AST_APP_ARG(ition);
|
|
|
|
AST_APP_ARG(labels);
|
|
|
|
);
|
|
|
|
AST_DECLARE_APP_ARGS(label,
|
|
|
|
AST_APP_ARG(iftrue);
|
|
|
|
AST_APP_ARG(iffalse);
|
|
|
|
);
|
2005-11-08 23:37:53 +00:00
|
|
|
|
|
|
|
if (ast_strlen_zero(data)) {
|
2006-10-02 04:17:57 +00:00
|
|
|
ast_log(LOG_WARNING, "GosubIf requires an argument: GosubIf(cond?label1(args):label2(args)\n");
|
2005-11-08 23:37:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-10-02 22:02:45 +00:00
|
|
|
args = ast_strdupa(data);
|
2009-08-06 21:29:26 +00:00
|
|
|
AST_NONSTANDARD_RAW_ARGS(cond, args, '?');
|
2006-10-02 22:02:45 +00:00
|
|
|
if (cond.argc != 2) {
|
|
|
|
ast_log(LOG_WARNING, "GosubIf requires an argument: GosubIf(cond?label1(args):label2(args)\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-08-06 21:29:26 +00:00
|
|
|
AST_NONSTANDARD_RAW_ARGS(label, cond.labels, ':');
|
2005-11-08 23:37:53 +00:00
|
|
|
|
2006-10-02 22:02:45 +00:00
|
|
|
if (pbx_checkcondition(cond.ition)) {
|
|
|
|
if (!ast_strlen_zero(label.iftrue))
|
|
|
|
res = gosub_exec(chan, label.iftrue);
|
|
|
|
} else if (!ast_strlen_zero(label.iffalse)) {
|
|
|
|
res = gosub_exec(chan, label.iffalse);
|
2005-11-08 23:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2007-06-20 04:36:23 +00:00
|
|
|
static int local_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
|
|
|
|
{
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
struct ast_datastore *stack_store;
|
2012-06-14 23:22:53 +00:00
|
|
|
struct gosub_stack_list *oldlist;
|
2007-06-20 04:36:23 +00:00
|
|
|
struct gosub_stack_frame *frame;
|
|
|
|
struct ast_var_t *variables;
|
|
|
|
|
2014-03-27 19:21:44 +00:00
|
|
|
if (!chan) {
|
|
|
|
ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_lock(chan);
|
|
|
|
if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
|
|
|
|
ast_channel_unlock(chan);
|
2007-06-20 04:36:23 +00:00
|
|
|
return -1;
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
}
|
2007-06-20 04:36:23 +00:00
|
|
|
|
|
|
|
oldlist = stack_store->data;
|
|
|
|
AST_LIST_LOCK(oldlist);
|
2009-08-09 07:11:22 +00:00
|
|
|
if (!(frame = AST_LIST_FIRST(oldlist))) {
|
|
|
|
/* Not within a Gosub routine */
|
|
|
|
AST_LIST_UNLOCK(oldlist);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2009-08-09 07:11:22 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2007-06-20 04:36:23 +00:00
|
|
|
AST_LIST_TRAVERSE(&frame->varshead, variables, entries) {
|
|
|
|
if (!strcmp(data, ast_var_name(variables))) {
|
2008-04-30 19:21:04 +00:00
|
|
|
const char *tmp;
|
|
|
|
tmp = pbx_builtin_getvar_helper(chan, data);
|
2007-06-20 05:47:05 +00:00
|
|
|
ast_copy_string(buf, S_OR(tmp, ""), len);
|
2007-06-20 04:36:23 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AST_LIST_UNLOCK(oldlist);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2007-06-20 04:36:23 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int local_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
|
|
|
|
{
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
struct ast_datastore *stack_store;
|
2012-06-14 23:22:53 +00:00
|
|
|
struct gosub_stack_list *oldlist;
|
2007-06-20 04:36:23 +00:00
|
|
|
struct gosub_stack_frame *frame;
|
|
|
|
|
2014-03-27 19:21:44 +00:00
|
|
|
if (!chan) {
|
|
|
|
ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_lock(chan);
|
|
|
|
if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
|
2007-06-20 04:36:23 +00:00
|
|
|
ast_log(LOG_ERROR, "Tried to set LOCAL(%s), but we aren't within a Gosub routine\n", var);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2007-06-20 04:36:23 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
oldlist = stack_store->data;
|
|
|
|
AST_LIST_LOCK(oldlist);
|
|
|
|
frame = AST_LIST_FIRST(oldlist);
|
2007-06-20 05:47:05 +00:00
|
|
|
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
if (frame) {
|
2007-06-20 13:00:45 +00:00
|
|
|
frame_set_var(chan, frame, var, value);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
}
|
2007-06-20 04:36:23 +00:00
|
|
|
|
|
|
|
AST_LIST_UNLOCK(oldlist);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
2007-06-20 04:36:23 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ast_custom_function local_function = {
|
|
|
|
.name = "LOCAL",
|
|
|
|
.write = local_write,
|
|
|
|
.read = local_read,
|
|
|
|
};
|
|
|
|
|
2008-12-02 18:39:12 +00:00
|
|
|
static int peek_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
|
|
|
|
{
|
|
|
|
int found = 0, n;
|
|
|
|
struct ast_var_t *variables;
|
|
|
|
AST_DECLARE_APP_ARGS(args,
|
|
|
|
AST_APP_ARG(n);
|
|
|
|
AST_APP_ARG(name);
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!chan) {
|
|
|
|
ast_log(LOG_ERROR, "LOCAL_PEEK must be called on an active channel\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-08-06 21:29:26 +00:00
|
|
|
AST_STANDARD_RAW_ARGS(args, data);
|
2014-02-01 00:25:54 +00:00
|
|
|
|
|
|
|
if (ast_strlen_zero(args.n) || ast_strlen_zero(args.name)) {
|
|
|
|
ast_log(LOG_ERROR, "LOCAL_PEEK requires parameters n and varname\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-12-02 18:39:12 +00:00
|
|
|
n = atoi(args.n);
|
|
|
|
*buf = '\0';
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
2012-02-29 16:52:47 +00:00
|
|
|
AST_LIST_TRAVERSE(ast_channel_varshead(chan), variables, entries) {
|
2008-12-02 18:39:12 +00:00
|
|
|
if (!strcmp(args.name, ast_var_name(variables)) && ++found > n) {
|
|
|
|
ast_copy_string(buf, ast_var_value(variables), len);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ast_custom_function peek_function = {
|
|
|
|
.name = "LOCAL_PEEK",
|
|
|
|
.read = peek_read,
|
|
|
|
};
|
|
|
|
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
static int stackpeek_read(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
|
|
|
|
{
|
|
|
|
struct ast_datastore *stack_store;
|
2012-06-14 23:22:53 +00:00
|
|
|
struct gosub_stack_list *oldlist;
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
struct gosub_stack_frame *frame;
|
|
|
|
int n;
|
|
|
|
AST_DECLARE_APP_ARGS(args,
|
|
|
|
AST_APP_ARG(n);
|
|
|
|
AST_APP_ARG(which);
|
|
|
|
AST_APP_ARG(suppress);
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!chan) {
|
|
|
|
ast_log(LOG_ERROR, "STACK_PEEK must be called on an active channel\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = ast_strdupa(data);
|
|
|
|
AST_STANDARD_APP_ARGS(args, data);
|
|
|
|
|
2014-02-01 00:25:54 +00:00
|
|
|
if (ast_strlen_zero(args.n) || ast_strlen_zero(args.which)) {
|
|
|
|
ast_log(LOG_ERROR, "STACK_PEEK requires parameters n and which\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
n = atoi(args.n);
|
|
|
|
if (n <= 0) {
|
|
|
|
ast_log(LOG_ERROR, "STACK_PEEK must be called with a positive peek value\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
if (!(stack_store = ast_channel_datastore_find(chan, &stack_info, NULL))) {
|
|
|
|
if (!ast_true(args.suppress)) {
|
|
|
|
ast_log(LOG_ERROR, "STACK_PEEK called on a channel without a gosub stack\n");
|
|
|
|
}
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
oldlist = stack_store->data;
|
|
|
|
|
|
|
|
AST_LIST_LOCK(oldlist);
|
|
|
|
AST_LIST_TRAVERSE(oldlist, frame, entries) {
|
|
|
|
if (--n == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!frame) {
|
|
|
|
/* Too deep */
|
|
|
|
if (!ast_true(args.suppress)) {
|
|
|
|
ast_log(LOG_ERROR, "Stack peek of '%s' is more stack frames than I have\n", args.n);
|
|
|
|
}
|
2014-04-11 21:43:30 +00:00
|
|
|
AST_LIST_UNLOCK(oldlist);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_channel_unlock(chan);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
args.which = ast_skip_blanks(args.which);
|
|
|
|
|
|
|
|
switch (args.which[0]) {
|
|
|
|
case 'l': /* label */
|
|
|
|
ast_str_set(str, len, "%s,%s,%d", frame->context, frame->extension, frame->priority - 1);
|
|
|
|
break;
|
|
|
|
case 'c': /* context */
|
|
|
|
ast_str_set(str, len, "%s", frame->context);
|
|
|
|
break;
|
|
|
|
case 'e': /* extension */
|
|
|
|
ast_str_set(str, len, "%s", frame->extension);
|
|
|
|
break;
|
|
|
|
case 'p': /* priority */
|
|
|
|
ast_str_set(str, len, "%d", frame->priority - 1);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ast_log(LOG_ERROR, "Unknown argument '%s' to STACK_PEEK\n", args.which);
|
2012-06-14 23:22:53 +00:00
|
|
|
break;
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
AST_LIST_UNLOCK(oldlist);
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ast_custom_function stackpeek_function = {
|
|
|
|
.name = "STACK_PEEK",
|
|
|
|
.read2 = stackpeek_read,
|
|
|
|
};
|
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
/*!
|
|
|
|
* \internal
|
|
|
|
* \brief Pop stack frames until remove a special return location.
|
|
|
|
* \since 11.0
|
|
|
|
*
|
|
|
|
* \param chan Channel to balance stack on.
|
|
|
|
*
|
|
|
|
* \note The channel is already locked when called.
|
|
|
|
*/
|
|
|
|
static void balance_stack(struct ast_channel *chan)
|
|
|
|
{
|
|
|
|
struct ast_datastore *stack_store;
|
|
|
|
struct gosub_stack_list *oldlist;
|
|
|
|
struct gosub_stack_frame *oldframe;
|
|
|
|
int found;
|
|
|
|
|
|
|
|
stack_store = ast_channel_datastore_find(chan, &stack_info, NULL);
|
|
|
|
if (!stack_store) {
|
|
|
|
ast_log(LOG_WARNING, "No %s stack allocated.\n", app_gosub);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
oldlist = stack_store->data;
|
|
|
|
AST_LIST_LOCK(oldlist);
|
|
|
|
do {
|
|
|
|
oldframe = AST_LIST_REMOVE_HEAD(oldlist, entries);
|
|
|
|
if (!oldframe) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
found = oldframe->is_special;
|
|
|
|
gosub_release_frame(chan, oldframe);
|
|
|
|
} while (!found);
|
|
|
|
AST_LIST_UNLOCK(oldlist);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \internal
|
|
|
|
* \brief Run a subroutine on a channel.
|
|
|
|
* \since 11.0
|
|
|
|
*
|
|
|
|
* \note Absolutely _NO_ channel locks should be held before calling this function.
|
|
|
|
*
|
|
|
|
* \param chan Channel to execute subroutine on.
|
|
|
|
* \param sub_args Gosub application argument string.
|
|
|
|
* \param ignore_hangup TRUE if a hangup does not stop execution of the routine.
|
|
|
|
*
|
|
|
|
* \retval 0 success
|
|
|
|
* \retval -1 on error
|
|
|
|
*/
|
|
|
|
static int gosub_run(struct ast_channel *chan, const char *sub_args, int ignore_hangup)
|
|
|
|
{
|
|
|
|
const char *saved_context;
|
|
|
|
const char *saved_exten;
|
|
|
|
int saved_priority;
|
|
|
|
int saved_hangup_flags;
|
|
|
|
int saved_autoloopflag;
|
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
2014-09-05 22:04:33 +00:00
|
|
|
int saved_in_subroutine;
|
2012-06-14 23:22:53 +00:00
|
|
|
int res;
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
|
|
|
|
ast_verb(3, "%s Internal %s(%s) start\n",
|
|
|
|
ast_channel_name(chan), app_gosub, sub_args);
|
|
|
|
|
|
|
|
/* Save non-hangup softhangup flags. */
|
|
|
|
saved_hangup_flags = ast_channel_softhangup_internal_flag(chan)
|
2014-08-13 16:24:37 +00:00
|
|
|
& AST_SOFTHANGUP_ASYNCGOTO;
|
2012-06-14 23:22:53 +00:00
|
|
|
if (saved_hangup_flags) {
|
2014-08-13 16:24:37 +00:00
|
|
|
ast_channel_clear_softhangup(chan, AST_SOFTHANGUP_ASYNCGOTO);
|
2012-06-14 23:22:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Save autoloop flag */
|
|
|
|
saved_autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
|
|
|
|
ast_set_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
|
|
|
|
|
|
|
|
/* Save current dialplan location */
|
|
|
|
saved_context = ast_strdupa(ast_channel_context(chan));
|
|
|
|
saved_exten = ast_strdupa(ast_channel_exten(chan));
|
|
|
|
saved_priority = ast_channel_priority(chan);
|
|
|
|
|
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
2014-09-05 22:04:33 +00:00
|
|
|
/* Save whether or not we are in a subroutine */
|
|
|
|
saved_in_subroutine = ast_test_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
|
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_debug(4, "%s Original location: %s,%s,%d\n", ast_channel_name(chan),
|
|
|
|
saved_context, saved_exten, saved_priority);
|
|
|
|
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
res = gosub_exec(chan, sub_args);
|
|
|
|
ast_debug(4, "%s exited with status %d\n", app_gosub, res);
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
if (!res) {
|
|
|
|
struct ast_datastore *stack_store;
|
|
|
|
|
|
|
|
/* Mark the return location as special. */
|
|
|
|
stack_store = ast_channel_datastore_find(chan, &stack_info, NULL);
|
|
|
|
if (!stack_store) {
|
|
|
|
/* Should never happen! */
|
|
|
|
ast_log(LOG_ERROR, "No %s stack!\n", app_gosub);
|
|
|
|
res = -1;
|
|
|
|
} else {
|
|
|
|
struct gosub_stack_list *oldlist;
|
|
|
|
struct gosub_stack_frame *cur;
|
|
|
|
|
|
|
|
oldlist = stack_store->data;
|
|
|
|
cur = AST_LIST_FIRST(oldlist);
|
|
|
|
cur->is_special = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!res) {
|
|
|
|
int found = 0; /* set if we find at least one match */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Run gosub body autoloop.
|
|
|
|
*
|
|
|
|
* Note that this loop is inverted from the normal execution
|
|
|
|
* loop because we just executed the Gosub application as the
|
|
|
|
* first extension of the autoloop.
|
|
|
|
*/
|
|
|
|
do {
|
|
|
|
/* Check for hangup. */
|
|
|
|
if (ast_check_hangup(chan)) {
|
|
|
|
if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) {
|
|
|
|
ast_log(LOG_ERROR, "%s An async goto just messed up our execution location.\n",
|
|
|
|
ast_channel_name(chan));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!ignore_hangup) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Next dialplan priority. */
|
|
|
|
ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
|
|
|
|
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
res = ast_spawn_extension(chan, ast_channel_context(chan),
|
|
|
|
ast_channel_exten(chan), ast_channel_priority(chan),
|
|
|
|
S_COR(ast_channel_caller(chan)->id.number.valid,
|
|
|
|
ast_channel_caller(chan)->id.number.str, NULL),
|
|
|
|
&found, 1);
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
} while (!res);
|
|
|
|
if (found && res) {
|
|
|
|
/* Something bad happened, or a hangup has been requested. */
|
|
|
|
ast_debug(1, "Spawn extension (%s,%s,%d) exited with %d on '%s'\n",
|
|
|
|
ast_channel_context(chan), ast_channel_exten(chan),
|
|
|
|
ast_channel_priority(chan), res, ast_channel_name(chan));
|
|
|
|
ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
|
|
|
|
ast_channel_context(chan), ast_channel_exten(chan),
|
|
|
|
ast_channel_priority(chan), ast_channel_name(chan));
|
|
|
|
}
|
|
|
|
|
2023-08-10 16:51:12 +00:00
|
|
|
/* Did the routine return? */
|
|
|
|
if (ast_channel_priority(chan) == saved_priority
|
2012-06-14 23:22:53 +00:00
|
|
|
&& !strcmp(ast_channel_context(chan), saved_context)
|
2023-08-10 16:51:12 +00:00
|
|
|
&& !strcmp(ast_channel_exten(chan), saved_exten)) {
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_verb(3, "%s Internal %s(%s) complete GOSUB_RETVAL=%s\n",
|
|
|
|
ast_channel_name(chan), app_gosub, sub_args,
|
|
|
|
S_OR(pbx_builtin_getvar_helper(chan, "GOSUB_RETVAL"), ""));
|
|
|
|
} else {
|
2022-07-22 20:57:05 +00:00
|
|
|
ast_log(LOG_WARNING, "%s Abnormal '%s(%s)' exit. Popping routine return locations.\n",
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_channel_name(chan), app_gosub, sub_args);
|
|
|
|
balance_stack(chan);
|
|
|
|
pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", "");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We executed the requested subroutine to the best of our ability. */
|
|
|
|
res = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_debug(4, "%s Ending location: %s,%s,%d\n", ast_channel_name(chan),
|
|
|
|
ast_channel_context(chan), ast_channel_exten(chan),
|
|
|
|
ast_channel_priority(chan));
|
|
|
|
|
|
|
|
/* Restore dialplan location */
|
|
|
|
if (!(ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO)) {
|
|
|
|
ast_channel_context_set(chan, saved_context);
|
|
|
|
ast_channel_exten_set(chan, saved_exten);
|
|
|
|
ast_channel_priority_set(chan, saved_priority);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Restore autoloop flag */
|
|
|
|
ast_set2_flag(ast_channel_flags(chan), saved_autoloopflag, AST_FLAG_IN_AUTOLOOP);
|
|
|
|
|
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
2014-09-05 22:04:33 +00:00
|
|
|
/* Restore subroutine flag */
|
|
|
|
ast_set2_flag(ast_channel_flags(chan), saved_in_subroutine, AST_FLAG_SUBROUTINE_EXEC);
|
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
/* Restore non-hangup softhangup flags. */
|
|
|
|
if (saved_hangup_flags) {
|
|
|
|
ast_softhangup_nolock(chan, saved_hangup_flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2009-05-21 21:13:09 +00:00
|
|
|
static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, const char * const *argv)
|
2008-05-30 16:10:46 +00:00
|
|
|
{
|
2012-06-14 23:22:53 +00:00
|
|
|
int res;
|
|
|
|
int priority;
|
|
|
|
int old_autoloopflag;
|
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
2014-09-05 22:04:33 +00:00
|
|
|
int old_in_subroutine;
|
2012-06-14 23:22:53 +00:00
|
|
|
int old_priority;
|
|
|
|
const char *old_context;
|
|
|
|
const char *old_extension;
|
2008-05-30 16:10:46 +00:00
|
|
|
char *gosub_args;
|
|
|
|
|
|
|
|
if (argc < 4 || argc > 5) {
|
|
|
|
return RESULT_SHOWUSAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_debug(1, "Gosub called with %d arguments: 0:%s 1:%s 2:%s 3:%s 4:%s\n", argc, argv[0], argv[1], argv[2], argv[3], argc == 5 ? argv[4] : "");
|
|
|
|
|
2009-08-10 19:20:57 +00:00
|
|
|
if (sscanf(argv[3], "%30d", &priority) != 1 || priority < 1) {
|
2008-05-30 16:10:46 +00:00
|
|
|
/* Lookup the priority label */
|
2010-07-14 15:48:36 +00:00
|
|
|
priority = ast_findlabel_extension(chan, argv[1], argv[2], argv[3],
|
2012-02-29 16:52:47 +00:00
|
|
|
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
|
2010-07-14 15:48:36 +00:00
|
|
|
if (priority < 0) {
|
2008-05-30 16:10:46 +00:00
|
|
|
ast_log(LOG_ERROR, "Priority '%s' not found in '%s@%s'\n", argv[3], argv[2], argv[1]);
|
2008-11-19 12:42:19 +00:00
|
|
|
ast_agi_send(agi->fd, chan, "200 result=-1 Gosub label not found\n");
|
2008-05-30 16:10:46 +00:00
|
|
|
return RESULT_FAILURE;
|
|
|
|
}
|
2010-07-14 15:48:36 +00:00
|
|
|
} else if (!ast_exists_extension(chan, argv[1], argv[2], priority,
|
2012-02-29 16:52:47 +00:00
|
|
|
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
|
2008-11-19 12:42:19 +00:00
|
|
|
ast_agi_send(agi->fd, chan, "200 result=-1 Gosub label not found\n");
|
2008-05-30 16:10:46 +00:00
|
|
|
return RESULT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc == 5) {
|
2012-08-21 21:01:11 +00:00
|
|
|
if (ast_asprintf(&gosub_args, "%s,%s,%d(%s)", argv[1], argv[2], priority, argv[4]) < 0) {
|
2008-11-02 18:52:13 +00:00
|
|
|
gosub_args = NULL;
|
|
|
|
}
|
2008-05-30 16:10:46 +00:00
|
|
|
} else {
|
2012-08-21 21:01:11 +00:00
|
|
|
if (ast_asprintf(&gosub_args, "%s,%s,%d", argv[1], argv[2], priority) < 0) {
|
2008-11-02 18:52:13 +00:00
|
|
|
gosub_args = NULL;
|
|
|
|
}
|
2008-05-30 16:10:46 +00:00
|
|
|
}
|
2012-06-14 23:22:53 +00:00
|
|
|
if (!gosub_args) {
|
|
|
|
ast_agi_send(agi->fd, chan, "503 result=-2 Memory allocation failure\n");
|
|
|
|
return RESULT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
2008-05-30 16:10:46 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_verb(3, "%s AGI %s(%s) start\n", ast_channel_name(chan), app_gosub, gosub_args);
|
2008-05-30 16:10:46 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
/* 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);
|
|
|
|
|
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
2014-09-05 22:04:33 +00:00
|
|
|
/* Save subroutine flag */
|
|
|
|
old_in_subroutine = ast_test_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
|
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
/* 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));
|
|
|
|
old_priority = ast_channel_priority(chan);
|
|
|
|
|
|
|
|
ast_debug(4, "%s Original location: %s,%s,%d\n", ast_channel_name(chan),
|
|
|
|
old_context, old_extension, old_priority);
|
|
|
|
ast_channel_unlock(chan);
|
2008-05-30 16:10:46 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
res = gosub_exec(chan, gosub_args);
|
|
|
|
if (!res) {
|
|
|
|
struct ast_datastore *stack_store;
|
|
|
|
|
|
|
|
/* Mark the return location as special. */
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
stack_store = ast_channel_datastore_find(chan, &stack_info, NULL);
|
|
|
|
if (!stack_store) {
|
|
|
|
/* Should never happen! */
|
|
|
|
ast_log(LOG_ERROR, "No %s stack!\n", app_gosub);
|
|
|
|
res = -1;
|
|
|
|
} else {
|
|
|
|
struct gosub_stack_list *oldlist;
|
2012-05-04 22:17:38 +00:00
|
|
|
struct gosub_stack_frame *cur;
|
2012-06-14 23:22:53 +00:00
|
|
|
|
2012-05-04 22:17:38 +00:00
|
|
|
oldlist = stack_store->data;
|
|
|
|
cur = AST_LIST_FIRST(oldlist);
|
2012-06-14 23:22:53 +00:00
|
|
|
cur->is_special = 1;
|
|
|
|
}
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
}
|
|
|
|
if (!res) {
|
|
|
|
struct ast_pbx *pbx;
|
|
|
|
struct ast_pbx_args args;
|
|
|
|
int abnormal_exit;
|
|
|
|
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
|
|
args.no_hangup_chan = 1;
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
|
|
|
|
/* Next dialplan priority. */
|
|
|
|
ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
|
|
|
|
|
|
|
|
/* Suppress warning about PBX already existing */
|
|
|
|
pbx = ast_channel_pbx(chan);
|
|
|
|
ast_channel_pbx_set(chan, NULL);
|
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
|
|
|
ast_agi_send(agi->fd, chan, "100 result=0 Trying...\n");
|
|
|
|
ast_pbx_run_args(chan, &args);
|
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
ast_free(ast_channel_pbx(chan));
|
|
|
|
ast_channel_pbx_set(chan, pbx);
|
|
|
|
|
|
|
|
/* Did the routine return? */
|
|
|
|
if (ast_channel_priority(chan) == old_priority
|
|
|
|
&& !strcmp(ast_channel_context(chan), old_context)
|
|
|
|
&& !strcmp(ast_channel_exten(chan), old_extension)) {
|
|
|
|
ast_verb(3, "%s AGI %s(%s) complete GOSUB_RETVAL=%s\n",
|
|
|
|
ast_channel_name(chan), app_gosub, gosub_args,
|
|
|
|
S_OR(pbx_builtin_getvar_helper(chan, "GOSUB_RETVAL"), ""));
|
|
|
|
abnormal_exit = 0;
|
2008-05-30 16:10:46 +00:00
|
|
|
} else {
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_log(LOG_NOTICE, "%s Abnormal AGI %s(%s) exit. Popping routine return locations.\n",
|
|
|
|
ast_channel_name(chan), app_gosub, gosub_args);
|
|
|
|
balance_stack(chan);
|
|
|
|
pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", "");
|
|
|
|
abnormal_exit = 1;
|
2008-05-30 16:10:46 +00:00
|
|
|
}
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
|
|
|
ast_agi_send(agi->fd, chan, "200 result=0 Gosub complete%s\n",
|
|
|
|
abnormal_exit ? " (abnormal exit)" : "");
|
2008-05-30 16:10:46 +00:00
|
|
|
} else {
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_agi_send(agi->fd, chan, "200 result=%d Gosub failed\n", res);
|
2008-05-30 16:10:46 +00:00
|
|
|
}
|
|
|
|
|
2013-10-02 17:12:49 +00:00
|
|
|
ast_free(gosub_args);
|
2012-06-14 23:22:53 +00:00
|
|
|
|
|
|
|
ast_channel_lock(chan);
|
|
|
|
ast_debug(4, "%s Ending location: %s,%s,%d\n", ast_channel_name(chan),
|
|
|
|
ast_channel_context(chan), ast_channel_exten(chan),
|
|
|
|
ast_channel_priority(chan));
|
|
|
|
|
2008-05-30 16:10:46 +00:00
|
|
|
/* Restore previous location */
|
2012-02-13 17:27:06 +00:00
|
|
|
ast_channel_context_set(chan, old_context);
|
|
|
|
ast_channel_exten_set(chan, old_extension);
|
2012-02-20 23:43:27 +00:00
|
|
|
ast_channel_priority_set(chan, old_priority);
|
2008-05-30 16:10:46 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
/* Restore autoloop flag */
|
|
|
|
ast_set2_flag(ast_channel_flags(chan), old_autoloopflag, AST_FLAG_IN_AUTOLOOP);
|
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
2014-09-05 22:04:33 +00:00
|
|
|
|
|
|
|
/* Restore subroutine flag */
|
|
|
|
ast_set2_flag(ast_channel_flags(chan), old_in_subroutine, AST_FLAG_SUBROUTINE_EXEC);
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_channel_unlock(chan);
|
|
|
|
|
2008-05-30 16:10:46 +00:00
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2009-06-15 19:10:10 +00:00
|
|
|
static struct agi_command gosub_agi_command =
|
2009-06-06 23:28:38 +00:00
|
|
|
{ { "gosub", NULL }, handle_gosub, NULL, NULL, 0 };
|
2008-05-30 16:10:46 +00:00
|
|
|
|
2006-08-21 02:11:39 +00:00
|
|
|
static int unload_module(void)
|
2005-11-08 23:37:53 +00:00
|
|
|
{
|
2012-06-14 23:22:53 +00:00
|
|
|
ast_install_stack_functions(NULL);
|
2012-04-20 23:29:56 +00:00
|
|
|
|
2017-12-29 08:57:17 +00:00
|
|
|
ast_agi_unregister(&gosub_agi_command);
|
2008-05-30 16:10:46 +00:00
|
|
|
|
2005-11-08 23:37:53 +00:00
|
|
|
ast_unregister_application(app_return);
|
|
|
|
ast_unregister_application(app_pop);
|
|
|
|
ast_unregister_application(app_gosubif);
|
|
|
|
ast_unregister_application(app_gosub);
|
2007-06-20 04:36:23 +00:00
|
|
|
ast_custom_function_unregister(&local_function);
|
2008-12-02 18:39:12 +00:00
|
|
|
ast_custom_function_unregister(&peek_function);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_custom_function_unregister(&stackpeek_function);
|
2005-11-08 23:37:53 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-08-21 02:11:39 +00:00
|
|
|
static int load_module(void)
|
2005-11-08 23:37:53 +00:00
|
|
|
{
|
2012-06-14 23:22:53 +00:00
|
|
|
/* Setup the stack application callback functions. */
|
|
|
|
static struct ast_app_stack_funcs funcs = {
|
|
|
|
.run_sub = gosub_run,
|
|
|
|
.expand_sub_args = expand_gosub_args,
|
|
|
|
};
|
2012-04-20 23:29:56 +00:00
|
|
|
|
2009-06-15 16:07:23 +00:00
|
|
|
ast_agi_register(ast_module_info->self, &gosub_agi_command);
|
2008-05-30 16:10:46 +00:00
|
|
|
|
2008-11-01 21:10:07 +00:00
|
|
|
ast_register_application_xml(app_pop, pop_exec);
|
|
|
|
ast_register_application_xml(app_return, return_exec);
|
|
|
|
ast_register_application_xml(app_gosubif, gosubif_exec);
|
|
|
|
ast_register_application_xml(app_gosub, gosub_exec);
|
2007-06-20 04:36:23 +00:00
|
|
|
ast_custom_function_register(&local_function);
|
2008-12-02 18:39:12 +00:00
|
|
|
ast_custom_function_register(&peek_function);
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
ast_custom_function_register(&stackpeek_function);
|
2005-11-08 23:37:53 +00:00
|
|
|
|
2012-06-14 23:22:53 +00:00
|
|
|
funcs.module = ast_module_info->self,
|
|
|
|
ast_install_stack_functions(&funcs);
|
|
|
|
|
2005-11-08 23:37:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Enable macros in 1.8 to find the next highest "h" extension in a context, like in 1.4.
This change restores functionality that was present in 1.4, when AEL macros
were implemented with the Macro dialplan application. Macros are fraught with
functionality issues, because they consume a large portion of the underlying
application stack. This limits the ability of AEL users to call many layers
of subroutines, an issue which Gosub does not have (originally tested to
100,000 levels deep). Therefore, starting in 1.6.0, AEL macros were
implemented with Gosub.
However, there were some implicit behaviors of Macro, which were not replicated
at the same time as with the transition to Gosub, one of which is documented in
the related issue. In particular, the "h" extension is designed to execute not
in the Macro context, but in the topmost calling context. Due to legacy issues
with a misapplied bugfix many years ago, when a macro exited in 1.4, it looks
in all calling contexts, bubbling up from the deepest level until it finds an
"h" extension.
Since AEL hides the complexity of the underlying dialplan logic from the AEL
programmer, it's reasonable to assume that this behavior should not change in
the transition from Asterisk 1.4 LTS to Asterisk 1.8 LTS, lest we break
working AEL configurations in the transition to Asterisk 1.8 LTS. This fix
is the result, which implements a search for the "h" extension in all calling
Gosub contexts.
Fixes ASTERISK-19336
Patch: 20120308__ael_bugfix_for_trunk__2.diff (License #5003) by Tilghman Lesher
(with slight modifications for 1.8)
Tested by: Johan Wilfer
Review: https://reviewboard.asterisk.org/r/1776/
........
Merged revisions 358810 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 358811 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-03-13 08:06:20 +00:00
|
|
|
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT | AST_MODFLAG_LOAD_ORDER, "Dialplan subroutines (Gosub, Return, etc)",
|
2015-05-06 00:49:04 +00:00
|
|
|
.support_level = AST_MODULE_SUPPORT_CORE,
|
|
|
|
.load = load_module,
|
|
|
|
.unload = unload_module,
|
|
|
|
.load_pri = AST_MODPRI_APP_DEPEND,
|
2017-11-19 22:30:49 +00:00
|
|
|
.optional_modules = "res_agi",
|
2015-05-06 00:49:04 +00:00
|
|
|
);
|