00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00067
00068
00069
00070
00071
00072
00073
00074
00075
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