Mon Mar 20 08:25:44 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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

Generated on Mon Mar 20 08:25:44 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1