Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
func_global.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2006, Tilghman Lesher
5 *
6 * Tilghman Lesher <func_global__200605@the-tilghman.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Global variable dialplan functions
22 *
23 * \author Tilghman Lesher <func_global__200605@the-tilghman.com>
24 *
25 * \ingroup functions
26 */
27
28/*** MODULEINFO
29 <support_level>core</support_level>
30 ***/
31
32#include "asterisk.h"
33
34#include <sys/stat.h>
35
36#include "asterisk/module.h"
37#include "asterisk/pbx.h"
38#include "asterisk/channel.h"
39#include "asterisk/app.h"
41
42/*** DOCUMENTATION
43 <function name="GLOBAL" language="en_US">
44 <since>
45 <version>1.4.0</version>
46 </since>
47 <synopsis>
48 Gets or sets the global variable specified.
49 </synopsis>
50 <syntax>
51 <parameter name="varname" required="true">
52 <para>Global variable name</para>
53 </parameter>
54 </syntax>
55 <description>
56 <para>Set or get the value of a global variable specified in <replaceable>varname</replaceable></para>
57 </description>
58 </function>
59 <function name="GLOBAL_DELETE" language="en_US">
60 <since>
61 <version>18.21.0</version>
62 <version>20.6.0</version>
63 <version>21.1.0</version>
64 </since>
65 <synopsis>
66 Deletes a specified global variable.
67 </synopsis>
68 <syntax>
69 <parameter name="varname" required="true">
70 <para>Global variable name</para>
71 </parameter>
72 </syntax>
73 <description>
74 <para>Delete the global variable specified in <replaceable>varname</replaceable>.
75 Will succeed if the global variable exists or not.</para>
76 </description>
77 <see-also>
78 <ref type="function">GLOBAL</ref>
79 <ref type="function">DELETE</ref>
80 </see-also>
81 </function>
82 <function name="GLOBAL_EXISTS" language="en_US">
83 <since>
84 <version>18.21.0</version>
85 <version>20.6.0</version>
86 <version>21.1.0</version>
87 </since>
88 <synopsis>
89 Check if a global variable exists or not.
90 </synopsis>
91 <syntax>
92 <parameter name="varname" required="true">
93 <para>Global variable name</para>
94 </parameter>
95 </syntax>
96 <description>
97 <para>Returns <literal>1</literal> if global variable exists or <literal>0</literal> otherwise.</para>
98 </description>
99 <see-also>
100 <ref type="function">VARIABLE_EXISTS</ref>
101 </see-also>
102 </function>
103 <function name="SHARED" language="en_US">
104 <since>
105 <version>1.6.0</version>
106 </since>
107 <synopsis>
108 Gets or sets the shared variable specified.
109 </synopsis>
110 <syntax>
111 <parameter name="varname" required="true">
112 <para>Variable name</para>
113 </parameter>
114 <parameter name="channel">
115 <para>If not specified will default to current channel. It is the complete
116 channel name: <literal>SIP/12-abcd1234</literal> or the prefix only <literal>SIP/12</literal>.</para>
117 </parameter>
118 </syntax>
119 <description>
120 <para>Implements a shared variable area, in which you may share variables between
121 channels.</para>
122 <para>The variables used in this space are separate from the general namespace of
123 the channel and thus <variable>SHARED(foo)</variable> and <variable>foo</variable>
124 represent two completely different variables, despite sharing the same name.</para>
125 <para>Finally, realize that there is an inherent race between channels operating
126 at the same time, fiddling with each others' internal variables, which is why
127 this special variable namespace exists; it is to remind you that variables in
128 the SHARED namespace may change at any time, without warning. You should
129 therefore take special care to ensure that when using the SHARED namespace,
130 you retrieve the variable and store it in a regular channel variable before
131 using it in a set of calculations (or you might be surprised by the result).</para>
132 </description>
133 </function>
134 <managerEvent language="en_US" name="VarSet">
135 <managerEventInstance class="EVENT_FLAG_DIALPLAN">
136 <since>
137 <version>12.0.0</version>
138 </since>
139 <synopsis>Raised when a variable is shared between channels.</synopsis>
140 <syntax>
141 <channel_snapshot/>
142 <parameter name="Variable">
143 <para>The SHARED variable being set.</para>
144 <note><para>The variable name will always be enclosed with
145 <literal>SHARED()</literal></para></note>
146 </parameter>
147 <parameter name="Value">
148 <para>The new value of the variable.</para>
149 </parameter>
150 </syntax>
151 <see-also>
152 <ref type="function">SHARED</ref>
153 </see-also>
154 </managerEventInstance>
155 </managerEvent>
156 ***/
157
158static void shared_variable_free(void *data);
159
161 .type = "SHARED_VARIABLES",
162 .destroy = shared_variable_free,
163};
164
165static void shared_variable_free(void *data)
166{
167 struct varshead *varshead = data;
168 struct ast_var_t *var;
169
172 }
174}
175
176static int global_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
177{
178 const char *var = pbx_builtin_getvar_helper(NULL, data);
179
180 *buf = '\0';
181
182 if (var)
184
185 return 0;
186}
187
188static int global_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
189{
191
192 return 0;
193}
194
196 .name = "GLOBAL",
197 .read = global_read,
198 .write = global_write,
199};
200
201static int global_delete_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
202{
204
205 return 0;
206}
207
209 .name = "GLOBAL_DELETE",
210 .write = global_delete_write,
211};
212
213static int global_exists_read(struct ast_channel *chan, const char *cmd, char *data,
214 char *buf, size_t len)
215{
216 const char *var = pbx_builtin_getvar_helper(NULL, data);
217
218 strcpy(buf, var ? "1" : "0");
219
220 return 0;
221}
222
224 .name = "GLOBAL_EXISTS",
225 .read = global_exists_read,
226};
227
228static int shared_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
229{
230 struct ast_datastore *varstore;
231 struct varshead *varshead;
232 struct ast_var_t *var;
235 AST_APP_ARG(chan);
236 );
237 struct ast_channel *c_ref = NULL;
238
239 if (ast_strlen_zero(data)) {
240 ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
241 return -1;
242 }
243
245
246 if (!ast_strlen_zero(args.chan)) {
247 char *prefix = ast_alloca(strlen(args.chan) + 2);
248 sprintf(prefix, "%s-", args.chan);
249 if (!(c_ref = ast_channel_get_by_name(args.chan)) && !(c_ref = ast_channel_get_by_name_prefix(prefix, strlen(prefix)))) {
250 ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' will be blank.\n", args.chan, args.var);
251 return -1;
252 }
253 chan = c_ref;
254 } else if (!chan) {
255 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
256 return -1;
257 }
258
259 ast_channel_lock(chan);
260
261 if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
262 ast_channel_unlock(chan);
263 if (c_ref) {
264 c_ref = ast_channel_unref(c_ref);
265 }
266 return -1;
267 }
268
269 varshead = varstore->data;
270 *buf = '\0';
271
272 /* Protected by the channel lock */
273 AST_LIST_TRAVERSE(varshead, var, entries) {
274 if (!strcmp(args.var, ast_var_name(var))) {
276 break;
277 }
278 }
279
280 ast_channel_unlock(chan);
281
282 if (c_ref) {
283 c_ref = ast_channel_unref(c_ref);
284 }
285
286 return 0;
287}
288
289static int shared_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
290{
291 struct ast_datastore *varstore;
292 struct varshead *varshead;
293 struct ast_var_t *var;
296 AST_APP_ARG(chan);
297 );
298 struct ast_channel *c_ref = NULL;
299 int len;
300 RAII_VAR(char *, shared_buffer, NULL, ast_free);
301
302 if (ast_strlen_zero(data)) {
303 ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
304 return -1;
305 }
306
308
309 if (!ast_strlen_zero(args.chan)) {
310 char *prefix = ast_alloca(strlen(args.chan) + 2);
311 sprintf(prefix, "%s-", args.chan);
312 if (!(c_ref = ast_channel_get_by_name(args.chan)) && !(c_ref = ast_channel_get_by_name_prefix(prefix, strlen(prefix)))) {
313 ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' not set to '%s'.\n", args.chan, args.var, value);
314 return -1;
315 }
316 chan = c_ref;
317 } else if (!chan) {
318 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
319 return -1;
320 }
321
322 len = 9 + strlen(args.var); /* SHARED() + var */
323 shared_buffer = ast_malloc(len);
324 if (!shared_buffer) {
325 if (c_ref) {
326 ast_channel_unref(c_ref);
327 }
328 return -1;
329 }
330
331 ast_channel_lock(chan);
332
333 if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
334 if (!(varstore = ast_datastore_alloc(&shared_variable_info, NULL))) {
335 ast_log(LOG_ERROR, "Unable to allocate new datastore. Shared variable not set.\n");
336 ast_channel_unlock(chan);
337 if (c_ref) {
338 c_ref = ast_channel_unref(c_ref);
339 }
340 return -1;
341 }
342
343 if (!(varshead = ast_calloc(1, sizeof(*varshead)))) {
344 ast_log(LOG_ERROR, "Unable to allocate variable structure. Shared variable not set.\n");
345 ast_datastore_free(varstore);
346 ast_channel_unlock(chan);
347 if (c_ref) {
348 c_ref = ast_channel_unref(c_ref);
349 }
350 return -1;
351 }
352
353 varstore->data = varshead;
354 ast_channel_datastore_add(chan, varstore);
355 }
356 varshead = varstore->data;
357
358 /* Protected by the channel lock */
360 /* If there's a previous value, remove it */
361 if (!strcmp(args.var, ast_var_name(var))) {
364 break;
365 }
366 }
368
369 if ((var = ast_var_assign(args.var, S_OR(value, "")))) {
371
372 sprintf(shared_buffer, "SHARED(%s)", args.var);
373 ast_channel_publish_varset(chan, shared_buffer, value);
374 }
375
376 ast_channel_unlock(chan);
377
378 if (c_ref) {
379 c_ref = ast_channel_unref(c_ref);
380 }
381
382 return 0;
383}
384
386 .name = "SHARED",
387 .read = shared_read,
388 .write = shared_write,
389};
390
391static int unload_module(void)
392{
393 int res = 0;
394
399
400 return res;
401}
402
403static int load_module(void)
404{
405 int res = 0;
406
411
412 return res;
413}
414
415AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Variable dialplan functions");
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2414
#define ast_channel_lock(chan)
Definition: channel.h:2970
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1461
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3006
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1481
#define ast_channel_unlock(chan)
Definition: channel.h:2971
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2428
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
#define ast_var_assign(name, value)
Definition: chanvars.h:40
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2471
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int global_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_global.c:188
static int shared_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_global.c:228
static struct ast_custom_function shared_function
Definition: func_global.c:385
static struct ast_custom_function global_exists_function
Definition: func_global.c:223
static struct ast_custom_function global_function
Definition: func_global.c:195
static int global_exists_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_global.c:213
static int global_delete_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_global.c:201
static void shared_variable_free(void *data)
Definition: func_global.c:165
static struct ast_custom_function global_delete_function
Definition: func_global.c:208
static int load_module(void)
Definition: func_global.c:403
static int unload_module(void)
Definition: func_global.c:391
static const struct ast_datastore_info shared_variable_info
Definition: func_global.c:160
static int shared_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_global.c:289
static int global_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_global.c:176
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_publish_varset for a channel.
static char prefix[MAX_PREFIX]
Definition: http.c:144
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define LOG_ERROR
#define LOG_WARNING
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Core PBX routines and definitions.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
#define NULL
Definition: resample.c:96
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Main Channel structure associated with a channel.
const char * data
struct varshead varshead
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
struct ast_var_t::@213 entries
int value
Definition: syslog.c:37
const char * args
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941