Turn a NOTICE into a DEBUG message.
[asterisk-bristuff.git] / pbx / pbx_loopback.c
blobdcbef909be9cbc199dfd9f0fd038c48bbcc75d62
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 substitutes ${EXTEN}, ${CONTEXT}, and ${PRIORITY} into
57 the data passed to it to try to get a string of the form:
59 [exten]@context[:priority][/extramatch]
61 Where exten, context, and priority are another extension, context, and priority
62 to lookup and "extramatch" is an extra match restriction the *original* number
63 must fit if specified. The "extramatch" begins with _ like an exten pattern
64 if it is specified. Note that the search context MUST be a different context
65 from the current context or the search will not succeed in an effort to reduce
66 the likelihood of loops (they're still possible if you try hard, so be careful!)
71 #define LOOPBACK_COMMON \
72 char buf[1024]; \
73 int res; \
74 char *newexten=(char *)exten, *newcontext=(char *)context; \
75 int newpriority=priority; \
76 char *newpattern=NULL; \
77 loopback_helper(buf, sizeof(buf), exten, context, priority, data); \
78 loopback_subst(&newexten, &newcontext, &newpriority, &newpattern, buf); \
79 ast_log(LOG_DEBUG, "Parsed into %s @ %s priority %d\n", newexten, newcontext, newpriority); \
80 if (!strcasecmp(newcontext, context)) return -1
83 static char *loopback_helper(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
85 struct ast_var_t *newvariable;
86 struct varshead headp;
87 char tmp[80];
89 snprintf(tmp, sizeof(tmp), "%d", priority);
90 memset(buf, 0, buflen);
91 AST_LIST_HEAD_INIT_NOLOCK(&headp);
92 AST_LIST_INSERT_HEAD(&headp, ast_var_assign("EXTEN", exten), entries);
93 AST_LIST_INSERT_HEAD(&headp, ast_var_assign("CONTEXT", context), entries);
94 AST_LIST_INSERT_HEAD(&headp, ast_var_assign("PRIORITY", tmp), entries);
95 /* Substitute variables */
96 pbx_substitute_variables_varshead(&headp, data, buf, buflen);
97 /* free the list */
98 while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
99 ast_var_delete(newvariable);
100 return buf;
103 static void loopback_subst(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
105 char *con;
106 char *pri;
107 *newpattern = strchr(buf, '/');
108 if (*newpattern)
109 *(*newpattern)++ = '\0';
110 con = strchr(buf, '@');
111 if (con) {
112 *con++ = '\0';
113 pri = strchr(con, ':');
114 } else
115 pri = strchr(buf, ':');
116 if (!ast_strlen_zero(buf))
117 *newexten = buf;
118 if (!ast_strlen_zero(con))
119 *newcontext = con;
120 if (!ast_strlen_zero(pri))
121 sscanf(pri, "%d", priority);
124 static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
126 LOOPBACK_COMMON;
127 res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid);
128 if (newpattern && !ast_extension_match(newpattern, exten))
129 res = 0;
130 return res;
133 static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
135 LOOPBACK_COMMON;
136 res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid);
137 if (newpattern && !ast_extension_match(newpattern, exten))
138 res = 0;
139 return res;
142 static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
144 LOOPBACK_COMMON;
145 res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid);
146 /* XXX hmmm... res is overridden ? */
147 if (newpattern && !ast_extension_match(newpattern, exten))
148 res = -1;
149 return res;
152 static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
154 LOOPBACK_COMMON;
155 res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
156 if (newpattern && !ast_extension_match(newpattern, exten))
157 res = 0;
158 return res;
161 static struct ast_switch loopback_switch =
163 name: "Loopback",
164 description: "Loopback Dialplan Switch",
165 exists: loopback_exists,
166 canmatch: loopback_canmatch,
167 exec: loopback_exec,
168 matchmore: loopback_matchmore,
171 static int unload_module(void)
173 ast_unregister_switch(&loopback_switch);
174 return 0;
177 static int load_module(void)
179 ast_register_switch(&loopback_switch);
180 return 0;
183 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Loopback Switch");