Sat Aug 6 00:39:31 2011

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

Generated on Sat Aug 6 00:39:31 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7