remove the dlfcn compatibility stuff, because no platforms that Asterisk currently...
[asterisk-bristuff.git] / pbx / pbx_loopback.c
blob042cbfb5fc75ab605131e25ce7c5749ba95be4e6
1 /*
2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
19 /*! \file
21 * \brief Loopback PBX Module
25 #include "asterisk.h"
27 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <errno.h>
35 #include "asterisk/file.h"
36 #include "asterisk/logger.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/config.h"
39 #include "asterisk/options.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/module.h"
42 #include "asterisk/frame.h"
43 #include "asterisk/file.h"
44 #include "asterisk/cli.h"
45 #include "asterisk/lock.h"
46 #include "asterisk/md5.h"
47 #include "asterisk/linkedlists.h"
48 #include "asterisk/chanvars.h"
49 #include "asterisk/sched.h"
50 #include "asterisk/io.h"
51 #include "asterisk/utils.h"
52 #include "asterisk/crypto.h"
53 #include "asterisk/astdb.h"
56 /* Loopback switch creates a 'tunnel' to another context. When extension
57 lookups pass through the 'tunnel', Asterisk expressions can be used
58 to modify the target extension, context, and priority in any way desired.
59 If there is a match at the far end, execution jumps through the 'tunnel'
60 to the matched context, extension, and priority.
62 Global variables as well as ${CONTEXT}, ${EXTEN}, and ${PRIORITY} are
63 available for substitution. After substitution Loopback expects to get
64 a string of the form:
66 [exten]@context[:priority][/extramatch]
68 Where exten, context, and priority are another extension, context, and priority
69 to lookup and "extramatch" is a dialplan extension pattern which the *original*
70 number must match. If exten or priority are empty, the original values are
71 used.
73 Note that the search context MUST be a different context from the current
74 context or the search will not succeed. This is intended to reduce the
75 likelihood of loops (they're still possible if you try hard, so be careful!)
80 #define LOOPBACK_COMMON \
81 char buf[1024]; \
82 int res; \
83 char *newexten=(char *)exten, *newcontext=(char *)context; \
84 int newpriority=priority; \
85 char *newpattern=NULL; \
86 loopback_subst(buf, sizeof(buf), exten, context, priority, data); \
87 loopback_parse(&newexten, &newcontext, &newpriority, &newpattern, buf); \
88 ast_log(LOG_DEBUG, "Parsed into %s @ %s priority %d\n", newexten, newcontext, newpriority); \
89 if (!strcasecmp(newcontext, context)) return -1
91 static char *loopback_subst(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
93 struct ast_var_t *newvariable;
94 struct varshead headp;
95 char tmp[80];
97 snprintf(tmp, sizeof(tmp), "%d", priority);
98 memset(buf, 0, buflen);
99 AST_LIST_HEAD_INIT_NOLOCK(&headp);
100 newvariable = ast_var_assign("EXTEN", exten);
101 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
102 newvariable = ast_var_assign("CONTEXT", context);
103 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
104 newvariable = ast_var_assign("PRIORITY", tmp);
105 AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
106 /* Substitute variables */
107 pbx_substitute_variables_varshead(&headp, data, buf, buflen);
108 /* free the list */
109 while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
110 ast_var_delete(newvariable);
111 return buf;
114 static void loopback_parse(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
116 char *con;
117 char *pri;
118 *newpattern = strchr(buf, '/');
119 if (*newpattern)
120 *(*newpattern)++ = '\0';
121 con = strchr(buf, '@');
122 if (con) {
123 *con++ = '\0';
124 pri = strchr(con, ':');
125 } else
126 pri = strchr(buf, ':');
127 if (!ast_strlen_zero(buf))
128 *newexten = buf;
129 if (!ast_strlen_zero(con))
130 *newcontext = con;
131 if (!ast_strlen_zero(pri))
132 sscanf(pri, "%d", priority);
135 static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
137 LOOPBACK_COMMON;
138 res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid);
139 if (newpattern && !ast_extension_match(newpattern, exten))
140 res = 0;
141 return res;
144 static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
146 LOOPBACK_COMMON;
147 res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid);
148 if (newpattern && !ast_extension_match(newpattern, exten))
149 res = 0;
150 return res;
153 static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
155 LOOPBACK_COMMON;
156 res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid);
157 return res;
160 static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
162 LOOPBACK_COMMON;
163 res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
164 if (newpattern && !ast_extension_match(newpattern, exten))
165 res = 0;
166 return res;
169 static struct ast_switch loopback_switch =
171 name: "Loopback",
172 description: "Loopback Dialplan Switch",
173 exists: loopback_exists,
174 canmatch: loopback_canmatch,
175 exec: loopback_exec,
176 matchmore: loopback_matchmore,
179 static int unload_module(void)
181 ast_unregister_switch(&loopback_switch);
182 return 0;
185 static int load_module(void)
187 ast_register_switch(&loopback_switch);
188 return 0;
191 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Loopback Switch");