Asterisk - The Open Source Telephony Project  18.5.0
pbx_loopback.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <[email protected]>
7  *
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.
13  *
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.
17  */
18 
19 /*! \file
20  *
21  * \brief Loopback PBX Module
22  *
23  */
24 
25 /*** MODULEINFO
26  <support_level>core</support_level>
27  ***/
28 
29 #include "asterisk.h"
30 
31 #include "asterisk/file.h"
32 #include "asterisk/logger.h"
33 #include "asterisk/channel.h"
34 #include "asterisk/config.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/module.h"
37 #include "asterisk/frame.h"
38 #include "asterisk/cli.h"
39 #include "asterisk/lock.h"
40 #include "asterisk/md5.h"
41 #include "asterisk/linkedlists.h"
42 #include "asterisk/chanvars.h"
43 #include "asterisk/sched.h"
44 #include "asterisk/io.h"
45 #include "asterisk/utils.h"
46 #include "asterisk/astdb.h"
47 
48 
49 /* Loopback switch creates a 'tunnel' to another context. When extension
50  lookups pass through the 'tunnel', Asterisk expressions can be used
51  to modify the target extension, context, and priority in any way desired.
52  If there is a match at the far end, execution jumps through the 'tunnel'
53  to the matched context, extension, and priority.
54 
55  Global variables as well as ${CONTEXT}, ${EXTEN}, and ${PRIORITY} are
56  available for substitution. After substitution Loopback expects to get
57  a string of the form:
58 
59  [exten]@context[:priority][/extramatch]
60 
61  Where exten, context, and priority are another extension, context, and priority
62  to lookup and "extramatch" is a dialplan extension pattern which the *original*
63  number must match. If exten or priority are empty, the original values are
64  used.
65 
66  Note that the search context MUST be a different context from the current
67  context or the search will not succeed. This is intended to reduce the
68  likelihood of loops (they're still possible if you try hard, so be careful!)
69 
70 */
71 
72 
73 #define LOOPBACK_COMMON \
74  char buf[1024]; \
75  int res; \
76  char *newexten=(char *)exten, *newcontext=(char *)context; \
77  int newpriority=priority; \
78  char *newpattern=NULL; \
79  loopback_subst(buf, sizeof(buf), exten, context, priority, data); \
80  loopback_parse(&newexten, &newcontext, &newpriority, &newpattern, buf); \
81  ast_debug(1, "Parsed into %s @ %s priority %d pattern %s\n", newexten, newcontext, newpriority, newpattern); \
82  if (!strcasecmp(newcontext, context)) return -1
83 
84 static char *loopback_subst(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
85 {
86  struct ast_var_t *newvariable;
87  struct varshead headp;
88  char tmp[80];
89 
90  snprintf(tmp, sizeof(tmp), "%d", priority);
92  if ((newvariable = ast_var_assign("EXTEN", exten))) {
93  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
94  }
95  if ((newvariable = ast_var_assign("CONTEXT", context))) {
96  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
97  }
98  if ((newvariable = ast_var_assign("PRIORITY", tmp))) {
99  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
100  }
101  /* Substitute variables */
102  pbx_substitute_variables_varshead(&headp, data, buf, buflen);
103  /* free the list */
104  while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
105  ast_var_delete(newvariable);
106  return buf;
107 }
108 
109 static void loopback_parse(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
110 {
111  char *con;
112  char *pri;
113  *newpattern = strchr(buf, '/');
114  if (*newpattern)
115  *(*newpattern)++ = '\0';
116  con = strchr(buf, '@');
117  if (con) {
118  *con++ = '\0';
119  pri = strchr(con, ':');
120  } else
121  pri = strchr(buf, ':');
122  if (!ast_strlen_zero(buf))
123  *newexten = buf;
124  if (!ast_strlen_zero(con))
125  *newcontext = con;
126  if (!ast_strlen_zero(pri))
127  sscanf(pri, "%30d", priority);
128 }
129 
130 static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
131 {
133  if (newpattern && !ast_extension_match(newpattern, exten))
134  res = 0;
135  else
136  res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid);
137  return res;
138 }
139 
140 static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
141 {
143  if (newpattern && !ast_extension_match(newpattern, exten))
144  res = 0;
145  else
146  res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid);
147  return res;
148 }
149 
150 static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
151 {
152  int found;
154  res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid, &found, 0);
155  return res;
156 }
157 
158 static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
159 {
161  if (newpattern && !ast_extension_match(newpattern, exten))
162  res = 0;
163  else
164  res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
165  return res;
166 }
167 
169 {
170  .name = "Loopback",
171  .description = "Loopback Dialplan Switch",
172  .exists = loopback_exists,
173  .canmatch = loopback_canmatch,
174  .exec = loopback_exec,
175  .matchmore = loopback_matchmore,
176 };
177 
178 static int unload_module(void)
179 {
180  ast_unregister_switch(&loopback_switch);
181  return 0;
182 }
183 
184 static int load_module(void)
185 {
186  if (ast_register_switch(&loopback_switch))
189 }
190 
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Definition: pbx.c:4199
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_loopback.c:130
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Channel Variables.
static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_loopback.c:140
static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_loopback.c:158
static int tmp()
Definition: bt_open.c:389
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
Definition: pbx_switch.c:76
static char * loopback_subst(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
Definition: pbx_loopback.c:84
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
I/O Management (derived from Cheops-NG)
static int priority
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4194
Utility functions.
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char * name
Definition: pbx.h:162
static void loopback_parse(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
Definition: pbx_loopback.c:109
Configuration File Parser.
General Asterisk PBX channel definitions.
Scheduler Routines (derived from cheops)
Asterisk internal frame definitions.
A set of macros to manage forward-linked lists.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
Core PBX routines and definitions.
static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
Definition: pbx_loopback.c:150
static int unload_module(void)
Definition: pbx_loopback.c:178
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
static int load_module(void)
Definition: pbx_loopback.c:184
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: extconf.c:4297
#define ast_var_assign(name, value)
Definition: chanvars.h:40
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
Definition: pbx_switch.c:58
Module could not be loaded properly.
Definition: module.h:102
#define LOOPBACK_COMMON
Definition: pbx_loopback.c:73
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
Launch a new extension (i.e. new stack)
Definition: pbx.c:4204
Support for logging to various files, console and syslog Configuration in file logger.conf.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
Standard Command Line Interface.
static struct ast_switch loopback_switch
Definition: pbx_loopback.c:168
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
MD5 digest functions.
Persistant data storage (akin to *doze registry)
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)