Wed Oct 28 11:51:06 2009

Asterisk developer's documentation


pbx_realtime.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.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 Realtime PBX Module
00022  *
00023  * \arg See also: \ref AstARA
00024  */
00025 
00026 #include "asterisk.h"
00027 
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 129307 $")
00029 
00030 #include "asterisk/file.h"
00031 #include "asterisk/logger.h"
00032 #include "asterisk/channel.h"
00033 #include "asterisk/config.h"
00034 #include "asterisk/pbx.h"
00035 #include "asterisk/module.h"
00036 #include "asterisk/frame.h"
00037 #include "asterisk/term.h"
00038 #include "asterisk/manager.h"
00039 #include "asterisk/cli.h"
00040 #include "asterisk/lock.h"
00041 #include "asterisk/md5.h"
00042 #include "asterisk/linkedlists.h"
00043 #include "asterisk/chanvars.h"
00044 #include "asterisk/sched.h"
00045 #include "asterisk/io.h"
00046 #include "asterisk/utils.h"
00047 #include "asterisk/crypto.h"
00048 #include "asterisk/astdb.h"
00049 
00050 #define MODE_MATCH      0
00051 #define MODE_MATCHMORE  1
00052 #define MODE_CANMATCH   2
00053 
00054 #define EXT_DATA_SIZE 256
00055 
00056 /* Realtime switch looks up extensions in the supplied realtime table.
00057 
00058    [context@][realtimetable][/options]
00059 
00060    If the realtimetable is omitted it is assumed to be "extensions".  If no context is 
00061    specified the context is assumed to be whatever is the container.
00062 
00063    The realtime table should have entries for context,exten,priority,app,args
00064    
00065    The realtime table currently does not support callerid fields.
00066 
00067 */
00068 
00069 
00070 static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode)
00071 {
00072    struct ast_variable *var;
00073    struct ast_config *cfg;
00074    char pri[20];
00075    char *ematch;
00076    char rexten[AST_MAX_EXTENSION + 20]="";
00077    int match;
00078    snprintf(pri, sizeof(pri), "%d", priority);
00079    switch(mode) {
00080    case MODE_MATCHMORE:
00081       ematch = "exten LIKE";
00082       snprintf(rexten, sizeof(rexten), "%s_%%", exten);
00083       break;
00084    case MODE_CANMATCH:
00085       ematch = "exten LIKE";
00086       snprintf(rexten, sizeof(rexten), "%s%%", exten);
00087       break;
00088    case MODE_MATCH:
00089    default:
00090       ematch = "exten";
00091       ast_copy_string(rexten, exten, sizeof(rexten));
00092    }
00093    var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, SENTINEL);
00094    if (!var) {
00095       cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, SENTINEL);   
00096       if (cfg) {
00097          char *cat = ast_category_browse(cfg, NULL);
00098 
00099          while(cat) {
00100             switch(mode) {
00101             case MODE_MATCHMORE:
00102                match = ast_extension_close(cat, exten, 1);
00103                break;
00104             case MODE_CANMATCH:
00105                match = ast_extension_close(cat, exten, 0);
00106                break;
00107             case MODE_MATCH:
00108             default:
00109                match = ast_extension_match(cat, exten);
00110             }
00111             if (match) {
00112                var = ast_category_detach_variables(ast_category_get(cfg, cat));
00113                break;
00114             }
00115             cat = ast_category_browse(cfg, cat);
00116          }
00117          ast_config_destroy(cfg);
00118       }
00119    }
00120    return var;
00121 }
00122 
00123 static struct ast_variable *realtime_common(const char *context, const char *exten, int priority, const char *data, int mode)
00124 {
00125    const char *ctx = NULL;
00126    char *table;
00127    struct ast_variable *var=NULL;
00128    char *buf = ast_strdupa(data);
00129    if (buf) {
00130       char *opts = strchr(buf, '/');
00131       if (opts)
00132          *opts++ = '\0';
00133       table = strchr(buf, '@');
00134       if (table) {
00135          *table++ = '\0';
00136          ctx = buf;
00137       }
00138       ctx = S_OR(ctx, context);
00139       table = S_OR(table, "extensions");
00140       var = realtime_switch_common(table, ctx, exten, priority, mode);
00141    }
00142    return var;
00143 }
00144 
00145 static int realtime_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00146 {
00147    struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH);
00148    if (var) {
00149       ast_variables_destroy(var);
00150       return 1;
00151    }
00152    return 0;
00153 }
00154 
00155 static int realtime_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00156 {
00157    struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_CANMATCH);
00158    if (var) {
00159       ast_variables_destroy(var);
00160       return 1;
00161    }
00162    return 0;
00163 }
00164 
00165 static int realtime_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00166 {
00167    int res = -1;
00168    struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH);
00169 
00170    if (var) {
00171       char *tmp="";
00172       char *app = NULL;
00173       struct ast_variable *v;
00174 
00175       for (v = var; v ; v = v->next) {
00176          if (!strcasecmp(v->name, "app"))
00177             app = ast_strdupa(v->value);
00178          else if (!strcasecmp(v->name, "appdata")) {
00179             if (ast_compat_pbx_realtime) {
00180                char *ptr;
00181                int in = 0;
00182                tmp = alloca(strlen(v->value) * 2 + 1);
00183                for (ptr = tmp; *v->value; v->value++) {
00184                   if (*v->value == ',') {
00185                      *ptr++ = '\\';
00186                      *ptr++ = ',';
00187                   } else if (*v->value == '|' && !in) {
00188                      *ptr++ = ',';
00189                   } else {
00190                      *ptr++ = *v->value;
00191                   }
00192 
00193                   /* Don't escape '|', meaning 'or', inside expressions ($[ ]) */
00194                   if (v->value[0] == '[' && v->value[-1] == '$') {
00195                      in++;
00196                   } else if (v->value[0] == ']' && in) {
00197                      in--;
00198                   }
00199                }
00200                *ptr = '\0';
00201             } else {
00202                tmp = ast_strdupa(v->value);
00203             }
00204          }
00205       }
00206       ast_variables_destroy(var);
00207       if (!ast_strlen_zero(app)) {
00208          struct ast_app *a = pbx_findapp(app);
00209          if (a) {
00210             char appdata[512];
00211             char tmp1[80];
00212             char tmp2[80];
00213             char tmp3[EXT_DATA_SIZE];
00214 
00215             appdata[0] = 0; /* just in case the substitute var func isn't called */
00216             if(!ast_strlen_zero(tmp))
00217                pbx_substitute_variables_helper(chan, tmp, appdata, sizeof(appdata) - 1);
00218             ast_verb(3, "Executing %s(\"%s\", \"%s\")\n",
00219                    term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)),
00220                    term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
00221                    term_color(tmp3, S_OR(appdata, ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
00222             manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
00223                        "Channel: %s\r\n"
00224                        "Context: %s\r\n"
00225                        "Extension: %s\r\n"
00226                        "Priority: %d\r\n"
00227                        "Application: %s\r\n"
00228                        "AppData: %s\r\n"
00229                        "Uniqueid: %s\r\n",
00230                        chan->name, chan->context, chan->exten, chan->priority, app, !ast_strlen_zero(appdata) ? appdata : "(NULL)", chan->uniqueid);
00231             
00232             res = pbx_exec(chan, a, appdata);
00233          } else
00234             ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context);
00235       } else {
00236          ast_log(LOG_WARNING, "No application specified for realtime extension '%s' in context '%s'\n", exten, context);
00237       }
00238    }
00239    return res;
00240 }
00241 
00242 static int realtime_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00243 {
00244    struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCHMORE);
00245    if (var) {
00246       ast_variables_destroy(var);
00247       return 1;
00248    }
00249    return 0;
00250 }
00251 
00252 static struct ast_switch realtime_switch =
00253 {
00254         name:                   "Realtime",
00255         description:       "Realtime Dialplan Switch",
00256         exists:                 realtime_exists,
00257         canmatch:               realtime_canmatch,
00258         exec:                   realtime_exec,
00259         matchmore:              realtime_matchmore,
00260 };
00261 
00262 static int unload_module(void)
00263 {
00264    ast_unregister_switch(&realtime_switch);
00265    return 0;
00266 }
00267 
00268 static int load_module(void)
00269 {
00270    if (ast_register_switch(&realtime_switch))
00271       return AST_MODULE_LOAD_FAILURE;
00272    return AST_MODULE_LOAD_SUCCESS;
00273 }
00274 
00275 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Realtime Switch");

Generated on Wed Oct 28 11:51:06 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6