2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Realtime PBX Module
23 * \arg See also: \ref AstARA
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36 #include "asterisk/file.h"
37 #include "asterisk/logger.h"
38 #include "asterisk/channel.h"
39 #include "asterisk/config.h"
40 #include "asterisk/options.h"
41 #include "asterisk/pbx.h"
42 #include "asterisk/module.h"
43 #include "asterisk/frame.h"
44 #include "asterisk/term.h"
45 #include "asterisk/manager.h"
46 #include "asterisk/file.h"
47 #include "asterisk/cli.h"
48 #include "asterisk/lock.h"
49 #include "asterisk/md5.h"
50 #include "asterisk/linkedlists.h"
51 #include "asterisk/chanvars.h"
52 #include "asterisk/sched.h"
53 #include "asterisk/io.h"
54 #include "asterisk/utils.h"
55 #include "asterisk/crypto.h"
56 #include "asterisk/astdb.h"
59 #define MODE_MATCHMORE 1
60 #define MODE_CANMATCH 2
62 #define EXT_DATA_SIZE 256
64 static char *tdesc = "Realtime Switch";
66 /* Realtime switch looks up extensions in the supplied realtime table.
68 [context@][realtimetable][/options]
70 If the realtimetable is omitted it is assumed to be "extensions". If no context is
71 specified the context is assumed to be whatever is the container.
73 The realtime table should have entries for context,exten,priority,app,args
75 The realtime table currently does not support callerid fields.
80 #define REALTIME_COMMON(mode) \
86 struct ast_variable *var=NULL; \
87 buf = ast_strdupa(data); \
89 opts = strchr(buf, '/'); \
95 table = strchr(buf, '@'); \
101 if (ast_strlen_zero(cxt)) \
103 if (ast_strlen_zero(table)) \
104 table = "extensions"; \
105 var = realtime_switch_common(table, cxt, exten, priority, mode); \
109 static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode)
111 struct ast_variable *var;
112 struct ast_config *cfg;
115 char rexten[AST_MAX_EXTENSION + 20]="";
117 snprintf(pri, sizeof(pri), "%d", priority);
120 ematch = "exten LIKE";
121 snprintf(rexten, sizeof(rexten), "%s_%%", exten);
124 ematch = "exten LIKE";
125 snprintf(rexten, sizeof(rexten), "%s%%", exten);
130 strncpy(rexten, exten, sizeof(rexten) - 1);
132 var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, NULL);
134 cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, NULL);
136 char *cat = ast_category_browse(cfg, NULL);
141 match = ast_extension_close(cat, exten, 1);
144 match = ast_extension_close(cat, exten, 0);
148 match = ast_extension_match(cat, exten);
151 var = ast_category_detach_variables(ast_category_get(cfg, cat));
154 cat = ast_category_browse(cfg, cat);
156 ast_config_destroy(cfg);
162 static int realtime_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
164 REALTIME_COMMON(MODE_MATCH);
165 if (var) ast_variables_destroy(var);
168 return res > 0 ? res : 0;
171 static int realtime_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
173 REALTIME_COMMON(MODE_CANMATCH);
174 if (var) ast_variables_destroy(var);
177 return res > 0 ? res : 0;
180 static int realtime_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
183 char appdata[512]="";
187 char tmp3[EXT_DATA_SIZE];
189 struct ast_variable *v;
190 REALTIME_COMMON(MODE_MATCH);
194 if (!strcasecmp(v->name, "app"))
195 strncpy(app, v->value, sizeof(app) -1 );
196 else if (!strcasecmp(v->name, "appdata"))
197 tmp = ast_strdupa(v->value);
200 ast_variables_destroy(var);
201 if (!ast_strlen_zero(app)) {
202 a = pbx_findapp(app);
204 if(!ast_strlen_zero(tmp))
205 pbx_substitute_variables_helper(chan, tmp, appdata, sizeof(appdata) - 1);
206 if (option_verbose > 2)
207 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\")\n",
208 term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)),
209 term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
210 term_color(tmp3, (!ast_strlen_zero(appdata) ? (char *)appdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
211 manager_event(EVENT_FLAG_CALL, "Newexten",
216 "Application: %s\r\n"
219 chan->name, chan->context, chan->exten, chan->priority, app, appdata ? appdata : "(NULL)", chan->uniqueid);
221 res = pbx_exec(chan, a, appdata, newstack);
223 ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context);
229 static int realtime_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
231 REALTIME_COMMON(MODE_MATCHMORE);
232 if (var) ast_variables_destroy(var);
235 return res > 0 ? res : 0;
238 static struct ast_switch realtime_switch =
241 description: "Realtime Dialplan Switch",
242 exists: realtime_exists,
243 canmatch: realtime_canmatch,
245 matchmore: realtime_matchmore,
248 char *description(void)
260 return ASTERISK_GPL_KEY;
263 int unload_module(void)
265 ast_unregister_switch(&realtime_switch);
269 int load_module(void)
271 ast_register_switch(&realtime_switch);