4 * Copyright (C) 2004, Digium Inc.
6 * Written by Mark Spencer <markster@digium.com>
8 * This program is Free Software distributed under the terms of
9 * of the GNU General Public License.
12 #include <asterisk/file.h>
13 #include <asterisk/logger.h>
14 #include <asterisk/channel.h>
15 #include <asterisk/config.h>
16 #include <asterisk/config_pvt.h>
17 #include <asterisk/options.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/module.h>
20 #include <asterisk/frame.h>
21 #include <asterisk/term.h>
22 #include <asterisk/manager.h>
23 #include <asterisk/file.h>
24 #include <asterisk/cli.h>
25 #include <asterisk/lock.h>
26 #include <asterisk/md5.h>
27 #include <asterisk/linkedlists.h>
28 #include <asterisk/chanvars.h>
29 #include <asterisk/sched.h>
30 #include <asterisk/io.h>
31 #include <asterisk/utils.h>
32 #include <asterisk/crypto.h>
33 #include <asterisk/astdb.h>
41 #define MODE_MATCHMORE 1
42 #define MODE_CANMATCH 2
44 #define EXT_DATA_SIZE 256
46 static char *tdesc = "Realtime Switch";
48 /* Realtime switch looks up extensions in the supplied realtime table.
50 [context@][realtimetable][/options]
52 If the realtimetable is omitted it is assumed to be "extensions". If no context is
53 specified the context is assumed to be whatever is the container.
55 The realtime table should have entries for context,exten,priority,app,args
57 The realtime table currently does not support callerid fields.
62 #define REALTIME_COMMON(mode) \
68 struct ast_variable *var=NULL; \
69 buf = ast_strdupa(data); \
71 opts = strchr(buf, '/'); \
77 table = strchr(buf, '@'); \
83 if (!cxt || ast_strlen_zero(cxt)) \
85 if (!table || ast_strlen_zero(table)) \
86 table = "extensions"; \
87 var = realtime_switch_common(table, cxt, exten, priority, mode); \
91 static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode)
93 struct ast_variable *var;
94 struct ast_config *cfg;
95 struct ast_category *cat;
98 char rexten[AST_MAX_EXTENSION + 20]="";
100 snprintf(pri, sizeof(pri), "%d", priority);
103 ematch = "exten LIKE";
104 snprintf(rexten, sizeof(rexten), "%s_%%", exten);
107 ematch = "exten LIKE";
108 snprintf(rexten, sizeof(rexten), "%s%%", exten);
113 strncpy(rexten, exten, sizeof(rexten) - 1);
115 var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, NULL);
117 cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, NULL);
123 match = ast_extension_close(cat->name, exten, 1);
126 match = ast_extension_close(cat->name, exten, 0);
130 match = ast_extension_match(cat->name, exten);
145 static int realtime_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
147 REALTIME_COMMON(MODE_MATCH);
148 if (var) ast_destroy_realtime(var);
151 return res > 0 ? res : 0;
154 static int realtime_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
156 REALTIME_COMMON(MODE_CANMATCH);
157 if (var) ast_destroy_realtime(var);
160 return res > 0 ? res : 0;
163 static int realtime_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
166 char appdata[512]="";
170 char tmp3[EXT_DATA_SIZE];
172 struct ast_variable *v;
173 REALTIME_COMMON(MODE_MATCH);
177 if (!strcasecmp(v->name, "app"))
178 strncpy(app, v->value, sizeof(app) -1 );
179 else if (!strcasecmp(v->name, "appdata"))
180 tmp = ast_strdupa(v->value);
183 ast_destroy_realtime(var);
184 if (!ast_strlen_zero(app)) {
185 a = pbx_findapp(app);
187 if(!ast_strlen_zero(tmp))
188 pbx_substitute_variables_helper(chan, tmp, appdata, sizeof(appdata) - 1);
189 if (option_verbose > 2)
190 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\")\n",
191 term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)),
192 term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
193 term_color(tmp3, (!ast_strlen_zero(appdata) ? (char *)appdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
194 manager_event(EVENT_FLAG_CALL, "Newexten",
199 "Application: %s\r\n"
202 chan->name, chan->context, chan->exten, chan->priority, app, appdata ? appdata : "(NULL)", chan->uniqueid);
204 res = pbx_exec(chan, a, appdata, newstack);
206 ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context);
212 static int realtime_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
214 REALTIME_COMMON(MODE_MATCHMORE);
215 if (var) ast_destroy_realtime(var);
218 return res > 0 ? res : 0;
221 static struct ast_switch realtime_switch =
224 description: "Realtime Dialplan Switch",
225 exists: realtime_exists,
226 canmatch: realtime_canmatch,
228 matchmore: realtime_matchmore,
231 char *description(void)
243 return ASTERISK_GPL_KEY;
246 int unload_module(void)
248 ast_unregister_switch(&realtime_switch);
252 int load_module(void)
254 ast_register_switch(&realtime_switch);