Wed Aug 18 22:33:52 2010

Asterisk developer's documentation


func_global.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2006, Tilghman Lesher
00005  *
00006  * Tilghman Lesher <func_global__200605@the-tilghman.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Global variable dialplan functions
00022  *
00023  * \author Tilghman Lesher <func_global__200605@the-tilghman.com>
00024  *
00025  * \ingroup functions
00026  */
00027 
00028 #include "asterisk.h"
00029 
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 135680 $")
00031 
00032 #include <sys/stat.h>
00033 
00034 #include "asterisk/module.h"
00035 #include "asterisk/pbx.h"
00036 #include "asterisk/channel.h"
00037 #include "asterisk/app.h"
00038 #include "asterisk/manager.h"
00039 
00040 static void shared_variable_free(void *data);
00041 
00042 static struct ast_datastore_info shared_variable_info = {
00043    .type = "SHARED_VARIABLES",
00044    .destroy = shared_variable_free,
00045 };
00046 
00047 static void shared_variable_free(void *data)
00048 {
00049    struct varshead *varshead = data;
00050    struct ast_var_t *var;
00051 
00052    while ((var = AST_LIST_REMOVE_HEAD(varshead, entries))) {
00053       ast_var_delete(var);
00054    }
00055    ast_free(varshead);
00056 }
00057 
00058 static int global_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00059 {
00060    const char *var = pbx_builtin_getvar_helper(NULL, data);
00061 
00062    *buf = '\0';
00063 
00064    if (var)
00065       ast_copy_string(buf, var, len);
00066 
00067    return 0;
00068 }
00069 
00070 static int global_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00071 {
00072    pbx_builtin_setvar_helper(NULL, data, value);
00073 
00074    return 0;
00075 }
00076 
00077 static struct ast_custom_function global_function = {
00078    .name = "GLOBAL",
00079    .synopsis = "Gets or sets the global variable specified",
00080    .syntax = "GLOBAL(<varname>)",
00081    .read = global_read,
00082    .write = global_write,
00083 };
00084 
00085 static int shared_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00086 {
00087    struct ast_datastore *varstore;
00088    struct varshead *varshead;
00089    struct ast_var_t *var;
00090    AST_DECLARE_APP_ARGS(args,
00091       AST_APP_ARG(var);
00092       AST_APP_ARG(chan);
00093    );
00094 
00095    if (ast_strlen_zero(data)) {
00096       ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
00097       return -1;
00098    }
00099 
00100    AST_STANDARD_APP_ARGS(args, data);
00101 
00102    if (!ast_strlen_zero(args.chan)) {
00103       char *prefix = alloca(strlen(args.chan) + 2);
00104       sprintf(prefix, "%s-", args.chan);
00105       if (!(chan = ast_get_channel_by_name_locked(args.chan)) && !(chan = ast_get_channel_by_name_prefix_locked(prefix, strlen(prefix)))) {
00106          ast_log(LOG_ERROR, "Channel '%s' not found!  Variable '%s' will be blank.\n", args.chan, args.var);
00107          return -1;
00108       }
00109    } else
00110       ast_channel_lock(chan);
00111 
00112    if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
00113       ast_channel_unlock(chan);
00114       return -1;
00115    }
00116 
00117    varshead = varstore->data;
00118    *buf = '\0';
00119 
00120    /* Protected by the channel lock */
00121    AST_LIST_TRAVERSE(varshead, var, entries) {
00122       if (!strcmp(args.var, ast_var_name(var))) {
00123          ast_copy_string(buf, ast_var_value(var), len);
00124          break;
00125       }
00126    }
00127 
00128    ast_channel_unlock(chan);
00129 
00130    return 0;
00131 }
00132 
00133 static int shared_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00134 {
00135    struct ast_datastore *varstore;
00136    struct varshead *varshead;
00137    struct ast_var_t *var;
00138    AST_DECLARE_APP_ARGS(args,
00139       AST_APP_ARG(var);
00140       AST_APP_ARG(chan);
00141    );
00142 
00143    if (ast_strlen_zero(data)) {
00144       ast_log(LOG_WARNING, "SHARED() requires an argument: SHARED(<var>[,<chan>])\n");
00145       return -1;
00146    }
00147 
00148    AST_STANDARD_APP_ARGS(args, data);
00149 
00150    if (!ast_strlen_zero(args.chan)) {
00151       char *prefix = alloca(strlen(args.chan) + 2);
00152       sprintf(prefix, "%s-", args.chan);
00153       if (!(chan = ast_get_channel_by_name_locked(args.chan)) && !(chan = ast_get_channel_by_name_prefix_locked(prefix, strlen(prefix)))) {
00154          ast_log(LOG_ERROR, "Channel '%s' not found!  Variable '%s' not set to '%s'.\n", args.chan, args.var, value);
00155          return -1;
00156       }
00157    } else
00158       ast_channel_lock(chan);
00159 
00160    if (!(varstore = ast_channel_datastore_find(chan, &shared_variable_info, NULL))) {
00161       if (!(varstore = ast_datastore_alloc(&shared_variable_info, NULL))) {
00162          ast_log(LOG_ERROR, "Unable to allocate new datastore.  Shared variable not set.\n");
00163          ast_channel_unlock(chan);
00164          return -1;
00165       }
00166 
00167       if (!(varshead = ast_calloc(1, sizeof(*varshead)))) {
00168          ast_log(LOG_ERROR, "Unable to allocate variable structure.  Shared variable not set.\n");
00169          ast_datastore_free(varstore);
00170          ast_channel_unlock(chan);
00171          return -1;
00172       }
00173 
00174       varstore->data = varshead;
00175       ast_channel_datastore_add(chan, varstore);
00176    }
00177    varshead = varstore->data;
00178 
00179    /* Protected by the channel lock */
00180    AST_LIST_TRAVERSE(varshead, var, entries) {
00181       /* If there's a previous value, remove it */
00182       if (!strcmp(args.var, ast_var_name(var))) {
00183          AST_LIST_REMOVE(varshead, var, entries);
00184          ast_var_delete(var);
00185          break;
00186       }
00187    }
00188 
00189    var = ast_var_assign(args.var, S_OR(value, ""));
00190    AST_LIST_INSERT_HEAD(varshead, var, entries);
00191    manager_event(EVENT_FLAG_DIALPLAN, "VarSet", 
00192       "Channel: %s\r\n"
00193       "Variable: SHARED(%s)\r\n"
00194       "Value: %s\r\n"
00195       "Uniqueid: %s\r\n", 
00196       chan ? chan->name : "none", args.var, value, 
00197       chan ? chan->uniqueid : "none");
00198 
00199    ast_channel_unlock(chan);
00200 
00201    return 0;
00202 }
00203 
00204 static struct ast_custom_function shared_function = {
00205    .name = "SHARED",
00206    .synopsis = "Gets or sets the shared variable specified",
00207    .syntax = "SHARED(<varname>[,<channel>])",
00208    .desc =
00209 "Implements a shared variable area, in which you may share variables between\n"
00210 "channels.  If channel is unspecified, defaults to the current channel.  Note\n"
00211 "that the channel name may be the complete name (i.e. SIP/12-abcd1234) or the\n"
00212 "prefix only (i.e. SIP/12).\n"
00213 "\n"
00214 "The variables used in this space are separate from the general namespace of\n"
00215 "the channel and thus ${SHARED(foo)} and ${foo} represent two completely\n"
00216 "different variables, despite sharing the same name.\n"
00217 "\n"
00218 "Finally, realize that there is an inherent race between channels operating\n"
00219 "at the same time, fiddling with each others' internal variables, which is why\n"
00220 "this special variable namespace exists; it is to remind you that variables in\n"
00221 "the SHARED namespace may change at any time, without warning.  You should\n"
00222 "therefore take special care to ensure that when using the SHARED namespace,\n"
00223 "you retrieve the variable and store it in a regular channel variable before\n"
00224 "using it in a set of calculations (or you might be surprised by the result).\n",
00225    .read = shared_read,
00226    .write = shared_write,
00227 };
00228 
00229 static int unload_module(void)
00230 {
00231    int res = 0;
00232 
00233    res |= ast_custom_function_unregister(&global_function);
00234    res |= ast_custom_function_unregister(&shared_function);
00235 
00236    return res;
00237 }
00238 
00239 static int load_module(void)
00240 {
00241    int res = 0;
00242 
00243    res |= ast_custom_function_register(&global_function);
00244    res |= ast_custom_function_register(&shared_function);
00245 
00246    return res;
00247 }
00248 
00249 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Variable dialplan functions");

Generated on Wed Aug 18 22:33:52 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7