Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:55 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 <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