Asterisk - The Open Source Telephony Project GIT-master-2de1a68
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 <synopsis>
45 Gets or sets the global variable specified.
46 </synopsis>
47 <syntax>
48 <parameter name="varname" required="true">
49 <para>Global variable name</para>
50 </parameter>
51 </syntax>
52 <description>
53 <para>Set or get the value of a global variable specified in <replaceable>varname</replaceable></para>
54 </description>
55 </function>
56 <function name="GLOBAL_DELETE" language="en_US">
57 <synopsis>
58 Deletes a specified global variable.
59 </synopsis>
60 <syntax>
61 <parameter name="varname" required="true">
62 <para>Global variable name</para>
63 </parameter>
64 </syntax>
65 <description>
66 <para>Delete the global variable specified in <replaceable>varname</replaceable>.
67 Will succeed if the global variable exists or not.</para>
68 </description>
69 <see-also>
70 <ref type="function">GLOBAL</ref>
71 <ref type="function">DELETE</ref>
72 </see-also>
73 </function>
74 <function name="GLOBAL_EXISTS" language="en_US">
75 <synopsis>
76 Check if a global variable exists or not.
77 </synopsis>
78 <syntax>
79 <parameter name="varname" required="true">
80 <para>Global variable name</para>
81 </parameter>
82 </syntax>
83 <description>
84 <para>Returns <literal>1</literal> if global variable exists or <literal>0</literal> otherwise.</para>
85 </description>
86 <see-also>
87 <ref type="function">VARIABLE_EXISTS</ref>
88 </see-also>
89 </function>
90 <function name="SHARED" language="en_US">
91 <synopsis>
92 Gets or sets the shared variable specified.
93 </synopsis>
94 <syntax>
95 <parameter name="varname" required="true">
96 <para>Variable name</para>
97 </parameter>
98 <parameter name="channel">
99 <para>If not specified will default to current channel. It is the complete
100 channel name: <literal>SIP/12-abcd1234</literal> or the prefix only <literal>SIP/12</literal>.</para>
101 </parameter>
102 </syntax>
103 <description>
104 <para>Implements a shared variable area, in which you may share variables between
105 channels.</para>
106 <para>The variables used in this space are separate from the general namespace of
107 the channel and thus <variable>SHARED(foo)</variable> and <variable>foo</variable>
108 represent two completely different variables, despite sharing the same name.</para>
109 <para>Finally, realize that there is an inherent race between channels operating
110 at the same time, fiddling with each others' internal variables, which is why
111 this special variable namespace exists; it is to remind you that variables in
112 the SHARED namespace may change at any time, without warning. You should
113 therefore take special care to ensure that when using the SHARED namespace,
114 you retrieve the variable and store it in a regular channel variable before
115 using it in a set of calculations (or you might be surprised by the result).</para>
116 </description>
117 </function>
118 <managerEvent language="en_US" name="VarSet">
119 <managerEventInstance class="EVENT_FLAG_DIALPLAN">
120 <synopsis>Raised when a variable is shared between channels.</synopsis>
121 <syntax>
122 <channel_snapshot/>
123 <parameter name="Variable">
124 <para>The SHARED variable being set.</para>
125 <note><para>The variable name will always be enclosed with
126 <literal>SHARED()</literal></para></note>
127 </parameter>
128 <parameter name="Value">
129 <para>The new value of the variable.</para>
130 </parameter>
131 </syntax>
132 <see-also>
133 <ref type="function">SHARED</ref>
134 </see-also>
135 </managerEventInstance>
136 </managerEvent>
137 ***/
138
139static void shared_variable_free(void *data);
140
142 .type = "SHARED_VARIABLES",
143 .destroy = shared_variable_free,
144};
145
146static void shared_variable_free(void *data)
147{
148 struct varshead *varshead = data;
149 struct ast_var_t *var;
150
153 }
155}
156
157static int global_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
158{
159 const char *var = pbx_builtin_getvar_helper(NULL, data);
160
161 *buf = '\0';
162
163 if (var)
165
166 return 0;
167}
168
169static int global_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
170{
172
173 return 0;
174}
175
177 .name = "GLOBAL",
178 .read = global_read,
179 .write = global_write,
180};
181
182static int global_delete_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
183{
185
186 return 0;
187}
188
190 .name = "GLOBAL_DELETE",
191 .write = global_delete_write,
192};
193
194static int global_exists_read(struct ast_channel *chan, const char *cmd, char *data,
195 char *buf, size_t len)
196{
197 const char *var = pbx_builtin_getvar_helper(NULL, data);
198
199 strcpy(buf, var ? "1" : "0");
200
201 return 0;
202}
203
205 .name = "GLOBAL_EXISTS",
206 .read = global_exists_read,
207};
208
209static int shared_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
210{
211 struct ast_datastore *varstore;
212 struct varshead *varshead;
213 struct ast_var_t *var;
216 AST_APP_ARG(chan);
217 );
218 struct ast_channel *c_ref = NULL;
219
220 if (ast_strlen_zero(data)) {
221 ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
222 return -1;
223 }
224
226
227 if (!ast_strlen_zero(args.chan)) {
228 char *prefix = ast_alloca(strlen(args.chan) + 2);
229 sprintf(prefix, "%s-", args.chan);
230 if (!(c_ref = ast_channel_get_by_name(args.chan)) && !(c_ref = ast_channel_get_by_name_prefix(prefix, strlen(prefix)))) {
231 ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' will be blank.\n", args.chan, args.var);
232 return -1;
233 }
234 chan = c_ref;
235 } else if (!chan) {
236 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
237 return -1;
238 }
239
240 ast_channel_lock(chan);
241
242 if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
243 ast_channel_unlock(chan);
244 if (c_ref) {
245 c_ref = ast_channel_unref(c_ref);
246 }
247 return -1;
248 }
249
250 varshead = varstore->data;
251 *buf = '\0';
252
253 /* Protected by the channel lock */
254 AST_LIST_TRAVERSE(varshead, var, entries) {
255 if (!strcmp(args.var, ast_var_name(var))) {
257 break;
258 }
259 }
260
261 ast_channel_unlock(chan);
262
263 if (c_ref) {
264 c_ref = ast_channel_unref(c_ref);
265 }
266
267 return 0;
268}
269
270static int shared_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
271{
272 struct ast_datastore *varstore;
273 struct varshead *varshead;
274 struct ast_var_t *var;
277 AST_APP_ARG(chan);
278 );
279 struct ast_channel *c_ref = NULL;
280 int len;
281 RAII_VAR(char *, shared_buffer, NULL, ast_free);
282
283 if (ast_strlen_zero(data)) {
284 ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
285 return -1;
286 }
287
289
290 if (!ast_strlen_zero(args.chan)) {
291 char *prefix = ast_alloca(strlen(args.chan) + 2);
292 sprintf(prefix, "%s-", args.chan);
293 if (!(c_ref = ast_channel_get_by_name(args.chan)) && !(c_ref = ast_channel_get_by_name_prefix(prefix, strlen(prefix)))) {
294 ast_log(LOG_ERROR, "Channel '%s' not found! Variable '%s' not set to '%s'.\n", args.chan, args.var, value);
295 return -1;
296 }
297 chan = c_ref;
298 } else if (!chan) {
299 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
300 return -1;
301 }
302
303 len = 9 + strlen(args.var); /* SHARED() + var */
304 shared_buffer = ast_malloc(len);
305 if (!shared_buffer) {
306 if (c_ref) {
307 ast_channel_unref(c_ref);
308 }
309 return -1;
310 }
311
312 ast_channel_lock(chan);
313
314 if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
315 if (!(varstore = ast_datastore_alloc(&shared_variable_info, NULL))) {
316 ast_log(LOG_ERROR, "Unable to allocate new datastore. Shared variable not set.\n");
317 ast_channel_unlock(chan);
318 if (c_ref) {
319 c_ref = ast_channel_unref(c_ref);
320 }
321 return -1;
322 }
323
324 if (!(varshead = ast_calloc(1, sizeof(*varshead)))) {
325 ast_log(LOG_ERROR, "Unable to allocate variable structure. Shared variable not set.\n");
326 ast_datastore_free(varstore);
327 ast_channel_unlock(chan);
328 if (c_ref) {
329 c_ref = ast_channel_unref(c_ref);
330 }
331 return -1;
332 }
333
334 varstore->data = varshead;
335 ast_channel_datastore_add(chan, varstore);
336 }
337 varshead = varstore->data;
338
339 /* Protected by the channel lock */
341 /* If there's a previous value, remove it */
342 if (!strcmp(args.var, ast_var_name(var))) {
345 break;
346 }
347 }
349
350 if ((var = ast_var_assign(args.var, S_OR(value, "")))) {
352
353 sprintf(shared_buffer, "SHARED(%s)", args.var);
354 ast_channel_publish_varset(chan, shared_buffer, value);
355 }
356
357 ast_channel_unlock(chan);
358
359 if (c_ref) {
360 c_ref = ast_channel_unref(c_ref);
361 }
362
363 return 0;
364}
365
367 .name = "SHARED",
368 .read = shared_read,
369 .write = shared_write,
370};
371
372static int unload_module(void)
373{
374 int res = 0;
375
380
381 return res;
382}
383
384static int load_module(void)
385{
386 int res = 0;
387
392
393 return res;
394}
395
396AST_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:2385
#define ast_channel_lock(chan)
Definition: channel.h:2922
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:1434
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
#define ast_channel_unlock(chan)
Definition: channel.h:2923
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:2399
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:169
static int shared_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_global.c:209
static struct ast_custom_function shared_function
Definition: func_global.c:366
static struct ast_custom_function global_exists_function
Definition: func_global.c:204
static struct ast_custom_function global_function
Definition: func_global.c:176
static int global_exists_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_global.c:194
static int global_delete_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_global.c:182
static void shared_variable_free(void *data)
Definition: func_global.c:146
static struct ast_custom_function global_delete_function
Definition: func_global.c:189
static int load_module(void)
Definition: func_global.c:384
static int unload_module(void)
Definition: func_global.c:372
static const struct ast_datastore_info shared_variable_info
Definition: func_global.c:141
static int shared_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_global.c:270
static int global_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_global.c:157
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:567
#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:1558
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::@211 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