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
65 /* Realtime switch looks up extensions in the supplied realtime table.
67 [context@][realtimetable][/options]
69 If the realtimetable is omitted it is assumed to be "extensions". If no context is
70 specified the context is assumed to be whatever is the container.
72 The realtime table should have entries for context,exten,priority,app,args
74 The realtime table currently does not support callerid fields.
79 #define REALTIME_COMMON(mode) \
85 struct ast_variable *var=NULL; \
86 buf = ast_strdupa(data); \
88 opts = strchr(buf, '/'); \
94 table = strchr(buf, '@'); \
100 if (ast_strlen_zero(cxt)) \
102 if (ast_strlen_zero(table)) \
103 table = "extensions"; \
104 var = realtime_switch_common(table, cxt, exten, priority, mode); \
108 static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode)
110 struct ast_variable *var;
111 struct ast_config *cfg;
114 char rexten[AST_MAX_EXTENSION + 20]="";
116 snprintf(pri, sizeof(pri), "%d", priority);
119 ematch = "exten LIKE";
120 snprintf(rexten, sizeof(rexten), "%s_%%", exten);
123 ematch = "exten LIKE";
124 snprintf(rexten, sizeof(rexten), "%s%%", exten);
129 strncpy(rexten, exten, sizeof(rexten) - 1);
131 var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, NULL);
133 cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, NULL);
135 char *cat = ast_category_browse(cfg, NULL);
140 match = ast_extension_close(cat, exten, 1);
143 match = ast_extension_close(cat, exten, 0);
147 match = ast_extension_match(cat, exten);
150 var = ast_category_detach_variables(ast_category_get(cfg, cat));
153 cat = ast_category_browse(cfg, cat);
155 ast_config_destroy(cfg);
161 static int realtime_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
163 REALTIME_COMMON(MODE_MATCH);
164 if (var) ast_variables_destroy(var);
167 return res > 0 ? res : 0;
170 static int realtime_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
172 REALTIME_COMMON(MODE_CANMATCH);
173 if (var) ast_variables_destroy(var);
176 return res > 0 ? res : 0;
179 static int realtime_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
182 char appdata[512]="";
186 char tmp3[EXT_DATA_SIZE];
188 struct ast_variable *v;
189 REALTIME_COMMON(MODE_MATCH);
193 if (!strcasecmp(v->name, "app"))
194 strncpy(app, v->value, sizeof(app) -1 );
195 else if (!strcasecmp(v->name, "appdata"))
196 tmp = ast_strdupa(v->value);
199 ast_variables_destroy(var);
200 if (!ast_strlen_zero(app)) {
201 a = pbx_findapp(app);
203 if(!ast_strlen_zero(tmp))
204 pbx_substitute_variables_helper(chan, tmp, appdata, sizeof(appdata) - 1);
205 if (option_verbose > 2)
206 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\")\n",
207 term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)),
208 term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
209 term_color(tmp3, (!ast_strlen_zero(appdata) ? (char *)appdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
210 manager_event(EVENT_FLAG_CALL, "Newexten",
215 "Application: %s\r\n"
218 chan->name, chan->context, chan->exten, chan->priority, app, appdata ? appdata : "(NULL)", chan->uniqueid);
220 res = pbx_exec(chan, a, appdata);
222 ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context);
228 static int realtime_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
230 REALTIME_COMMON(MODE_MATCHMORE);
232 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 static const char *description(void)
250 return "Realtime Switch";
253 static const char *key(void)
255 return ASTERISK_GPL_KEY;
258 static int unload_module(void *mod)
260 ast_unregister_switch(&realtime_switch);
264 static int load_module(void *mod)
266 ast_register_switch(&realtime_switch);
270 STD_MOD(MOD_1 | NO_USECOUNT | NO_UNLOAD, NULL, NULL, NULL);