From 2cfddf8cb632fd00d1f790315cdaa39a1518ffaf Mon Sep 17 00:00:00 2001 From: Tilghman Lesher <tilghman@meg.abyt.es> Date: Tue, 1 Sep 2009 23:41:06 +0000 Subject: [PATCH] Add MASTER_CHANNEL() dialplan function, as well as a useful usage. (closes issue #13140) Reported by: cpina Patches: 20090807__issue13140.diff.txt uploaded by tilghman (license 14) Tested by: lmadsen Change-type: feature git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@215301 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- CHANGES | 10 +++++++++ channels/chan_sip.c | 7 ++++++- funcs/func_channel.c | 49 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index ced6e455d5..b4fc577c61 100644 --- a/CHANGES +++ b/CHANGES @@ -41,6 +41,9 @@ SIP Changes force_rport forces RFC 3581 behavior and disables symmetric RTP support. Setting it to comedia enables RFC 3581 behavior if the remote side requests it and enables symmetric RTP support. + * Slave SIP channels now set HASH(SIP_CAUSE,<slave-channel-name>) on each + response. This permits the master channel to know how each channel dialled + in a multi-channel setup resolved in an individual way. IAX2 Changes ----------- @@ -93,6 +96,13 @@ Dialplan Functions disabled) voice - voice mode (returns from FAX mode, reverting the changes that were made when FAX mode was requested) + * Added new dialplan function MASTER_CHANNEL(), which permits retrieving + and setting variables on the channel which created the current channel. + Administrators should take care to avoid naming conflicts, when multiple + channels are dialled at once, especially when used with the Local channel + construct (which all could set variables on the master channel). Usage + of the HASH() dialplan function, with the key set to the name of the slave + channel, is one approach that will avoid conflicts. Dialplan Variables ------------------ diff --git a/channels/chan_sip.c b/channels/chan_sip.c index e8d90a088b..fc963d3baa 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -18630,8 +18630,13 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc sipmethod = find_sip_method(msg); owner = p->owner; - if (owner) + if (owner) { + char causevar[256], causeval[256]; owner->hangupcause = hangup_sip2cause(resp); + snprintf(causevar, sizeof(causevar), "MASTER_CHANNEL(HASH(SIP_CAUSE,%s))", owner->name); + snprintf(causeval, sizeof(causeval), "SIP %s", REQ_OFFSET_TO_STR(req, rlPart2)); + pbx_builtin_setvar_helper(owner, causevar, causeval); + } /* Acknowledge whatever it is destined for */ if ((resp >= 100) && (resp <= 199)) { diff --git a/funcs/func_channel.c b/funcs/func_channel.c index 9cc4001b6a..e82c39a51c 100644 --- a/funcs/func_channel.c +++ b/funcs/func_channel.c @@ -55,6 +55,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") will be space-delimited.</para> </description> </function> + <function name="MASTER_CHANNEL" language="en_US"> + <synopsis> + Gets or sets variables on the master channel + </synopsis> + <description> + <para>Allows access to the channel which created the current channel, if any. If the channel is already + a master channel, then accesses local channel variables.</para> + </description> + </function> <function name="CHANNEL" language="en_US"> <synopsis> Gets/sets various pieces of information about the channel. @@ -496,23 +505,55 @@ static struct ast_custom_function channels_function = { .read = func_channels_read, }; +static int func_mchan_read(struct ast_channel *chan, const char *function, + char *data, struct ast_str **buf, ssize_t len) +{ + struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid); + char *template = alloca(4 + strlen(data)); + sprintf(template, "${%s}", data); /* SAFE */ + ast_str_substitute_variables(buf, len, mchan ? mchan : chan, template); + if (mchan) { + ast_channel_unref(mchan); + } + return 0; +} + +static int func_mchan_write(struct ast_channel *chan, const char *function, + char *data, const char *value) +{ + struct ast_channel *mchan = ast_channel_get_by_name(chan->linkedid); + pbx_builtin_setvar_helper(mchan ? mchan : chan, data, value); + if (mchan) { + ast_channel_unref(mchan); + } + return 0; +} + +static struct ast_custom_function mchan_function = { + .name = "MASTER_CHANNEL", + .read2 = func_mchan_read, + .write = func_mchan_write, +}; + static int unload_module(void) { int res = 0; - + res |= ast_custom_function_unregister(&channel_function); res |= ast_custom_function_unregister(&channels_function); - + res |= ast_custom_function_unregister(&mchan_function); + return res; } static int load_module(void) { int res = 0; - + res |= ast_custom_function_register(&channel_function); res |= ast_custom_function_register(&channels_function); - + res |= ast_custom_function_register(&mchan_function); + return res; } -- GitLab