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 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <unistd.h>
00028 #include <string.h>
00029 #include <errno.h>
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00034
00035 #include "asterisk/file.h"
00036 #include "asterisk/logger.h"
00037 #include "asterisk/channel.h"
00038 #include "asterisk/config.h"
00039 #include "asterisk/options.h"
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/module.h"
00042 #include "asterisk/frame.h"
00043 #include "asterisk/file.h"
00044 #include "asterisk/cli.h"
00045 #include "asterisk/lock.h"
00046 #include "asterisk/md5.h"
00047 #include "asterisk/linkedlists.h"
00048 #include "asterisk/chanvars.h"
00049 #include "asterisk/sched.h"
00050 #include "asterisk/io.h"
00051 #include "asterisk/utils.h"
00052 #include "asterisk/crypto.h"
00053 #include "asterisk/astdb.h"
00054
00055 static char *tdesc = "Loopback Switch";
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #define LOOPBACK_COMMON \
00073 char buf[1024]; \
00074 int res; \
00075 char *newexten=(char *)exten, *newcontext=(char *)context; \
00076 int newpriority=priority; \
00077 char *newpattern=NULL; \
00078 loopback_helper(buf, sizeof(buf), exten, context, priority, data); \
00079 loopback_subst(&newexten, &newcontext, &newpriority, &newpattern, buf); \
00080 ast_log(LOG_DEBUG, "Parsed into %s @ %s priority %d\n", newexten, newcontext, newpriority); \
00081 if (!strcasecmp(newcontext, context)) return -1
00082
00083
00084 static char *loopback_helper(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
00085 {
00086 struct ast_var_t *newvariable;
00087 struct varshead headp;
00088 char tmp[80];
00089
00090 snprintf(tmp, sizeof(tmp), "%d", priority);
00091 memset(buf, 0, buflen);
00092 AST_LIST_HEAD_INIT_NOLOCK(&headp);
00093 newvariable = ast_var_assign("EXTEN", exten);
00094 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00095 newvariable = ast_var_assign("CONTEXT", context);
00096 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00097 newvariable = ast_var_assign("PRIORITY", tmp);
00098 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00099 pbx_substitute_variables_varshead(&headp, data, buf, buflen);
00100
00101 while (!AST_LIST_EMPTY(&headp)) {
00102 newvariable = AST_LIST_REMOVE_HEAD(&headp, entries);
00103 ast_var_delete(newvariable);
00104 }
00105 return buf;
00106 }
00107
00108 static void loopback_subst(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
00109 {
00110 char *con;
00111 char *pri;
00112 *newpattern = strchr(buf, '/');
00113 if (*newpattern) {
00114 *(*newpattern) = '\0';
00115 (*newpattern)++;
00116 }
00117 con = strchr(buf, '@');
00118 if (con) {
00119 *con = '\0';
00120 con++;
00121 pri = strchr(con, ':');
00122 } else
00123 pri = strchr(buf, ':');
00124 if (!ast_strlen_zero(buf))
00125 *newexten = buf;
00126 if (!ast_strlen_zero(con))
00127 *newcontext = con;
00128 if (!ast_strlen_zero(pri))
00129 sscanf(pri, "%d", priority);
00130 }
00131
00132 static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00133 {
00134 LOOPBACK_COMMON;
00135 res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid);
00136 if (newpattern && !ast_extension_match(newpattern, exten))
00137 res = 0;
00138 return res;
00139 }
00140
00141 static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00142 {
00143 LOOPBACK_COMMON;
00144 res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid);
00145 if (newpattern && !ast_extension_match(newpattern, exten))
00146 res = 0;
00147 return res;
00148 }
00149
00150 static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
00151 {
00152 LOOPBACK_COMMON;
00153 if (newstack)
00154 res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid);
00155 else
00156 res = ast_exec_extension(chan, newcontext, newexten, newpriority, callerid);
00157 if (newpattern && !ast_extension_match(newpattern, exten))
00158 res = -1;
00159 return res;
00160 }
00161
00162 static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00163 {
00164 LOOPBACK_COMMON;
00165 res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
00166 if (newpattern && !ast_extension_match(newpattern, exten))
00167 res = 0;
00168 return res;
00169 }
00170
00171 static struct ast_switch loopback_switch =
00172 {
00173 name: "Loopback",
00174 description: "Loopback Dialplan Switch",
00175 exists: loopback_exists,
00176 canmatch: loopback_canmatch,
00177 exec: loopback_exec,
00178 matchmore: loopback_matchmore,
00179 };
00180
00181 char *description(void)
00182 {
00183 return tdesc;
00184 }
00185
00186 int usecount(void)
00187 {
00188 return 1;
00189 }
00190
00191 char *key()
00192 {
00193 return ASTERISK_GPL_KEY;
00194 }
00195
00196 int unload_module(void)
00197 {
00198 ast_unregister_switch(&loopback_switch);
00199 return 0;
00200 }
00201
00202 int load_module(void)
00203 {
00204 ast_register_switch(&loopback_switch);
00205 return 0;
00206 }
00207