4 * Copyright (C) 2004 - 2005, 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/options.h"
17 #include "asterisk/pbx.h"
18 #include "asterisk/module.h"
19 #include "asterisk/frame.h"
20 #include "asterisk/term.h"
21 #include "asterisk/manager.h"
22 #include "asterisk/file.h"
23 #include "asterisk/cli.h"
24 #include "asterisk/lock.h"
25 #include "asterisk/md5.h"
26 #include "asterisk/linkedlists.h"
27 #include "asterisk/chanvars.h"
28 #include "asterisk/sched.h"
29 #include "asterisk/io.h"
30 #include "asterisk/utils.h"
31 #include "asterisk/crypto.h"
32 #include "asterisk/astdb.h"
40 #define MODE_MATCHMORE 1
41 #define MODE_CANMATCH 2
43 #define EXT_DATA_SIZE 256
45 static char *tdesc = "Realtime Switch";
47 /* Realtime switch looks up extensions in the supplied realtime table.
49 [context@][realtimetable][/options]
51 If the realtimetable is omitted it is assumed to be "extensions". If no context is
52 specified the context is assumed to be whatever is the container.
54 The realtime table should have entries for context,exten,priority,app,args
56 The realtime table currently does not support callerid fields.
61 #define REALTIME_COMMON(mode) \
67 struct ast_variable *var=NULL; \
68 buf = ast_strdupa(data); \
70 opts = strchr(buf, '/'); \
76 table = strchr(buf, '@'); \
82 if (!cxt || ast_strlen_zero(cxt)) \
84 if (!table || ast_strlen_zero(table)) \
85 table = "extensions"; \
86 var = realtime_switch_common(table, cxt, exten, priority, mode); \
90 static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode)
92 struct ast_variable *var;
93 struct ast_config *cfg;
96 char rexten[AST_MAX_EXTENSION + 20]="";
98 snprintf(pri, sizeof(pri), "%d", priority);
101 ematch = "exten LIKE";
102 snprintf(rexten, sizeof(rexten), "%s_%%", exten);
105 ematch = "exten LIKE";
106 snprintf(rexten, sizeof(rexten), "%s%%", exten);
111 strncpy(rexten, exten, sizeof(rexten) - 1);
113 var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, NULL);
115 cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, NULL);
117 char *cat = ast_category_browse(cfg, NULL);
122 match = ast_extension_close(cat, exten, 1);
125 match = ast_extension_close(cat, exten, 0);
129 match = ast_extension_match(cat, exten);
132 var = ast_category_detach_variables(ast_category_get(cfg, cat));
135 cat = ast_category_browse(cfg, cat);
137 ast_config_destroy(cfg);
143 static int realtime_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
145 REALTIME_COMMON(MODE_MATCH);
146 if (var) ast_variables_destroy(var);
149 return res > 0 ? res : 0;
152 static int realtime_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
154 REALTIME_COMMON(MODE_CANMATCH);
155 if (var) ast_variables_destroy(var);
158 return res > 0 ? res : 0;
161 static int realtime_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
164 char appdata[512]="";
168 char tmp3[EXT_DATA_SIZE];
170 struct ast_variable *v;
171 REALTIME_COMMON(MODE_MATCH);
175 if (!strcasecmp(v->name, "app"))
176 strncpy(app, v->value, sizeof(app) -1 );
177 else if (!strcasecmp(v->name, "appdata"))
178 tmp = ast_strdupa(v->value);
181 ast_variables_destroy(var);
182 if (!ast_strlen_zero(app)) {
183 a = pbx_findapp(app);
185 if(!ast_strlen_zero(tmp))
186 pbx_substitute_variables_helper(chan, tmp, appdata, sizeof(appdata) - 1);
187 if (option_verbose > 2)
188 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\")\n",
189 term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)),
190 term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
191 term_color(tmp3, (!ast_strlen_zero(appdata) ? (char *)appdata : ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
192 manager_event(EVENT_FLAG_CALL, "Newexten",
197 "Application: %s\r\n"
200 chan->name, chan->context, chan->exten, chan->priority, app, appdata ? appdata : "(NULL)", chan->uniqueid);
202 res = pbx_exec(chan, a, appdata, newstack);
204 ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context);
210 static int realtime_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
212 REALTIME_COMMON(MODE_MATCHMORE);
213 if (var) ast_variables_destroy(var);
216 return res > 0 ? res : 0;
219 static struct ast_switch realtime_switch =
222 description: "Realtime Dialplan Switch",
223 exists: realtime_exists,
224 canmatch: realtime_canmatch,
226 matchmore: realtime_matchmore,
229 char *description(void)
241 return ASTERISK_GPL_KEY;
244 int unload_module(void)
246 ast_unregister_switch(&realtime_switch);
250 int load_module(void)
252 ast_register_switch(&realtime_switch);