![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
pbx_loopback.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 Loopback PBX Module 00022 * 00023 */ 00024 00025 #include "asterisk.h" 00026 00027 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 40722 $") 00028 00029 #include <stdlib.h> 00030 #include <stdio.h> 00031 #include <unistd.h> 00032 #include <string.h> 00033 #include <errno.h> 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 00056 /* Loopback switch substitutes ${EXTEN}, ${CONTEXT}, and ${PRIORITY} into 00057 the data passed to it to try to get a string of the form: 00058 00059 [exten]@context[:priority][/extramatch] 00060 00061 Where exten, context, and priority are another extension, context, and priority 00062 to lookup and "extramatch" is an extra match restriction the *original* number 00063 must fit if specified. The "extramatch" begins with _ like an exten pattern 00064 if it is specified. Note that the search context MUST be a different context 00065 from the current context or the search will not succeed in an effort to reduce 00066 the likelihood of loops (they're still possible if you try hard, so be careful!) 00067 00068 */ 00069 00070 00071 #define LOOPBACK_COMMON \ 00072 char buf[1024]; \ 00073 int res; \ 00074 char *newexten=(char *)exten, *newcontext=(char *)context; \ 00075 int newpriority=priority; \ 00076 char *newpattern=NULL; \ 00077 loopback_helper(buf, sizeof(buf), exten, context, priority, data); \ 00078 loopback_subst(&newexten, &newcontext, &newpriority, &newpattern, buf); \ 00079 ast_log(LOG_DEBUG, "Parsed into %s @ %s priority %d\n", newexten, newcontext, newpriority); \ 00080 if (!strcasecmp(newcontext, context)) return -1 00081 00082 00083 static char *loopback_helper(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data) 00084 { 00085 struct ast_var_t *newvariable; 00086 struct varshead headp; 00087 char tmp[80]; 00088 00089 snprintf(tmp, sizeof(tmp), "%d", priority); 00090 memset(buf, 0, buflen); 00091 AST_LIST_HEAD_INIT_NOLOCK(&headp); 00092 AST_LIST_INSERT_HEAD(&headp, ast_var_assign("EXTEN", exten), entries); 00093 AST_LIST_INSERT_HEAD(&headp, ast_var_assign("CONTEXT", context), entries); 00094 AST_LIST_INSERT_HEAD(&headp, ast_var_assign("PRIORITY", tmp), entries); 00095 /* Substitute variables */ 00096 pbx_substitute_variables_varshead(&headp, data, buf, buflen); 00097 /* free the list */ 00098 while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries))) 00099 ast_var_delete(newvariable); 00100 return buf; 00101 } 00102 00103 static void loopback_subst(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf) 00104 { 00105 char *con; 00106 char *pri; 00107 *newpattern = strchr(buf, '/'); 00108 if (*newpattern) 00109 *(*newpattern)++ = '\0'; 00110 con = strchr(buf, '@'); 00111 if (con) { 00112 *con++ = '\0'; 00113 pri = strchr(con, ':'); 00114 } else 00115 pri = strchr(buf, ':'); 00116 if (!ast_strlen_zero(buf)) 00117 *newexten = buf; 00118 if (!ast_strlen_zero(con)) 00119 *newcontext = con; 00120 if (!ast_strlen_zero(pri)) 00121 sscanf(pri, "%d", priority); 00122 } 00123 00124 static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) 00125 { 00126 LOOPBACK_COMMON; 00127 res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid); 00128 if (newpattern && !ast_extension_match(newpattern, exten)) 00129 res = 0; 00130 return res; 00131 } 00132 00133 static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) 00134 { 00135 LOOPBACK_COMMON; 00136 res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid); 00137 if (newpattern && !ast_extension_match(newpattern, exten)) 00138 res = 0; 00139 return res; 00140 } 00141 00142 static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) 00143 { 00144 LOOPBACK_COMMON; 00145 res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid); 00146 /* XXX hmmm... res is overridden ? */ 00147 if (newpattern && !ast_extension_match(newpattern, exten)) 00148 res = -1; 00149 return res; 00150 } 00151 00152 static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data) 00153 { 00154 LOOPBACK_COMMON; 00155 res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid); 00156 if (newpattern && !ast_extension_match(newpattern, exten)) 00157 res = 0; 00158 return res; 00159 } 00160 00161 static struct ast_switch loopback_switch = 00162 { 00163 name: "Loopback", 00164 description: "Loopback Dialplan Switch", 00165 exists: loopback_exists, 00166 canmatch: loopback_canmatch, 00167 exec: loopback_exec, 00168 matchmore: loopback_matchmore, 00169 }; 00170 00171 static int unload_module(void) 00172 { 00173 ast_unregister_switch(&loopback_switch); 00174 return 0; 00175 } 00176 00177 static int load_module(void) 00178 { 00179 ast_register_switch(&loopback_switch); 00180 return 0; 00181 } 00182 00183 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Loopback Switch");