![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
pbx_realtime.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2005, Digium, Inc. 00005 * 00006 * Mark Spencer <markster@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! \file 00020 * 00021 * \brief Realtime PBX Module 00022 * 00023 * \arg See also: \ref AstARA 00024 */ 00025 00026 #include "asterisk.h" 00027 00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 46210 $") 00029 00030 #include <stdlib.h> 00031 #include <stdio.h> 00032 #include <unistd.h> 00033 #include <string.h> 00034 #include <errno.h> 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 00065 /* Realtime switch looks up extensions in the supplied realtime table. 00066 00067 [context@][realtimetable][/options] 00068 00069 If the realtimetable is omitted it is assumed to be "extensions". If no context is 00070 specified the context is assumed to be whatever is the container. 00071 00072 The realtime table should have entries for context,exten,priority,app,args 00073 00074 The realtime table currently does not support callerid fields. 00075 00076 */ 00077 00078 00079 static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode) 00080 { 00081 struct ast_variable *var; 00082 struct ast_config *cfg; 00083 char pri[20]; 00084 char *ematch; 00085 char rexten[AST_MAX_EXTENSION + 20]=""; 00086 int match; 00087 snprintf(pri, sizeof(pri), "%d", priority); 00088 switch(mode) { 00089 case MODE_MATCHMORE: 00090 ematch = "exten LIKE"; 00091 snprintf(rexten, sizeof(rexten), "%s_%%", exten); 00092 break; 00093 case MODE_CANMATCH: 00094 ematch = "exten LIKE"; 00095 snprintf(rexten, sizeof(rexten), "%s%%", exten); 00096 break; 00097 case MODE_MATCH: 00098 default: 00099 ematch = "exten"; 00100 ast_copy_string(rexten, exten, sizeof(rexten)); 00101 } 00102 var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, NULL); 00103 if (!var) { 00104 cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, NULL); 00105 if (cfg) { 00106 char *cat = ast_category_browse(cfg, NULL); 00107 00108 while(cat) { 00109 switch(mode) { 00110 case MODE_MATCHMORE: 00111 match = ast_extension_close(cat, exten, 1); 00112 break; 00113 case MODE_CANMATCH: 00114 match = ast_extension_close(cat, exten, 0); 00115 break; 00116 case MODE_MATCH: 00117 default: 00118 match = ast_extension_match(cat, exten); 00119 } 00120 if (match) { 00121 var = ast_category_detach_variables(ast_category_get(cfg, cat)); 00122 break; 00123 } 00124 cat = ast_category_browse(cfg, cat); 00125 } 00126 ast_config_destroy(cfg); 00127 } 00128 } 00129 return var; 00130 } 00131 00132 static struct ast_variable *realtime_common(const char *context, const char *exten, int priority, const char *data, int mode) 00133 { 00134 const char *ctx = NULL; 00135 char *table; 00136 struct ast_variable *var=NULL; 00137 char *buf = ast_strdupa(data); 00138 if (buf) { 00139 char *opts = strchr(buf, '/'); 00140 if (opts) 00141 *opts++ = '\0'; 00142 table = strchr(buf, '@'); 00143 if (table) { 00144 *table++ = '\0'; 00145 ctx = buf; 00146 } 00147 ctx = S_OR(ctx, context); 00148 table = S_OR(table, "extensions"); 00149 var = realtime_switch_common(table, ctx, exten, priority, mode); 00150 } 00151 return var; 00152 } 00153 00154 static int realtime_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) 00155 { 00156 struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH); 00157 if (var) { 00158 ast_variables_destroy(var); 00159 return 1; 00160 } 00161 return 0; 00162 } 00163 00164 static int realtime_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) 00165 { 00166 struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_CANMATCH); 00167 if (var) { 00168 ast_variables_destroy(var); 00169 return 1; 00170 } 00171 return 0; 00172 } 00173 00174 static int realtime_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) 00175 { 00176 int res = -1; 00177 struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH); 00178 00179 if (var) { 00180 char *tmp=""; 00181 char app[256]; 00182 struct ast_variable *v; 00183 00184 for (v = var; v ; v = v->next) { 00185 if (!strcasecmp(v->name, "app")) 00186 ast_copy_string(app, v->value, sizeof(app)); 00187 else if (!strcasecmp(v->name, "appdata")) 00188 tmp = ast_strdupa(v->value); 00189 } 00190 ast_variables_destroy(var); 00191 if (!ast_strlen_zero(app)) { 00192 struct ast_app *a = pbx_findapp(app); 00193 if (a) { 00194 char appdata[512]=""; 00195 char tmp1[80]; 00196 char tmp2[80]; 00197 char tmp3[EXT_DATA_SIZE]; 00198 00199 if(!ast_strlen_zero(tmp)) 00200 pbx_substitute_variables_helper(chan, tmp, appdata, sizeof(appdata) - 1); 00201 if (option_verbose > 2) 00202 ast_verbose( VERBOSE_PREFIX_3 "Executing %s(\"%s\", \"%s\")\n", 00203 term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)), 00204 term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)), 00205 term_color(tmp3, S_OR(appdata, ""), COLOR_BRMAGENTA, 0, sizeof(tmp3))); 00206 manager_event(EVENT_FLAG_CALL, "Newexten", 00207 "Channel: %s\r\n" 00208 "Context: %s\r\n" 00209 "Extension: %s\r\n" 00210 "Priority: %d\r\n" 00211 "Application: %s\r\n" 00212 "AppData: %s\r\n" 00213 "Uniqueid: %s\r\n", 00214 chan->name, chan->context, chan->exten, chan->priority, app, appdata ? appdata : "(NULL)", chan->uniqueid); 00215 00216 res = pbx_exec(chan, a, appdata); 00217 } else 00218 ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context); 00219 } 00220 } 00221 return res; 00222 } 00223 00224 static int realtime_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) 00225 { 00226 struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCHMORE); 00227 if (var) { 00228 ast_variables_destroy(var); 00229 return 1; 00230 } 00231 return 0; 00232 } 00233 00234 static struct ast_switch realtime_switch = 00235 { 00236 name: "Realtime", 00237 description: "Realtime Dialplan Switch", 00238 exists: realtime_exists, 00239 canmatch: realtime_canmatch, 00240 exec: realtime_exec, 00241 matchmore: realtime_matchmore, 00242 }; 00243 00244 static int unload_module(void) 00245 { 00246 ast_unregister_switch(&realtime_switch); 00247 return 0; 00248 } 00249 00250 static int load_module(void) 00251 { 00252 ast_register_switch(&realtime_switch); 00253 return 0; 00254 } 00255 00256 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Realtime Switch");