Wed Jan 8 2020 09:49:49

Asterisk developer's documentation


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 <markster@digium.com>
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 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 396279 $")
32 
33 #include "asterisk/file.h"
34 #include "asterisk/logger.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/config.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/module.h"
39 #include "asterisk/frame.h"
40 #include "asterisk/cli.h"
41 #include "asterisk/lock.h"
42 #include "asterisk/md5.h"
43 #include "asterisk/linkedlists.h"
44 #include "asterisk/chanvars.h"
45 #include "asterisk/sched.h"
46 #include "asterisk/io.h"
47 #include "asterisk/utils.h"
48 #include "asterisk/astdb.h"
49 
50 
51 /* Loopback switch creates a 'tunnel' to another context. When extension
52  lookups pass through the 'tunnel', Asterisk expressions can be used
53  to modify the target extension, context, and priority in any way desired.
54  If there is a match at the far end, execution jumps through the 'tunnel'
55  to the matched context, extension, and priority.
56 
57  Global variables as well as ${CONTEXT}, ${EXTEN}, and ${PRIORITY} are
58  available for substitution. After substitution Loopback expects to get
59  a string of the form:
60 
61  [exten]@context[:priority][/extramatch]
62 
63  Where exten, context, and priority are another extension, context, and priority
64  to lookup and "extramatch" is a dialplan extension pattern which the *original*
65  number must match. If exten or priority are empty, the original values are
66  used.
67 
68  Note that the search context MUST be a different context from the current
69  context or the search will not succeed. This is intended to reduce the
70  likelihood of loops (they're still possible if you try hard, so be careful!)
71 
72 */
73 
74 
75 #define LOOPBACK_COMMON \
76  char buf[1024]; \
77  int res; \
78  char *newexten=(char *)exten, *newcontext=(char *)context; \
79  int newpriority=priority; \
80  char *newpattern=NULL; \
81  loopback_subst(buf, sizeof(buf), exten, context, priority, data); \
82  loopback_parse(&newexten, &newcontext, &newpriority, &newpattern, buf); \
83  ast_log(LOG_DEBUG, "Parsed into %s @ %s priority %d\n", newexten, newcontext, newpriority); \
84  if (!strcasecmp(newcontext, context)) return -1
85 
86 static char *loopback_subst(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
87 {
88  struct ast_var_t *newvariable;
89  struct varshead headp;
90  char tmp[80];
91 
92  snprintf(tmp, sizeof(tmp), "%d", priority);
94  if ((newvariable = ast_var_assign("EXTEN", exten))) {
95  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
96  }
97  if ((newvariable = ast_var_assign("CONTEXT", context))) {
98  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
99  }
100  if ((newvariable = ast_var_assign("PRIORITY", tmp))) {
101  AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
102  }
103  /* Substitute variables */
104  pbx_substitute_variables_varshead(&headp, data, buf, buflen);
105  /* free the list */
106  while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
107  ast_var_delete(newvariable);
108  return buf;
109 }
110 
111 static void loopback_parse(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
112 {
113  char *con;
114  char *pri;
115  *newpattern = strchr(buf, '/');
116  if (*newpattern)
117  *(*newpattern)++ = '\0';
118  con = strchr(buf, '@');
119  if (con) {
120  *con++ = '\0';
121  pri = strchr(con, ':');
122  } else
123  pri = strchr(buf, ':');
124  if (!ast_strlen_zero(buf))
125  *newexten = buf;
126  if (!ast_strlen_zero(con))
127  *newcontext = con;
128  if (!ast_strlen_zero(pri))
129  sscanf(pri, "%30d", priority);
130 }
131 
132 static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
133 {
135  res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid);
136  if (newpattern && !ast_extension_match(newpattern, exten))
137  res = 0;
138  return res;
139 }
140 
141 static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
142 {
144  res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid);
145  if (newpattern && !ast_extension_match(newpattern, exten))
146  res = 0;
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  res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
162  if (newpattern && !ast_extension_match(newpattern, exten))
163  res = 0;
164  return res;
165 }
166 
168 {
169  .name = "Loopback",
170  .description = "Loopback Dialplan Switch",
171  .exists = loopback_exists,
172  .canmatch = loopback_canmatch,
173  .exec = loopback_exec,
174  .matchmore = loopback_matchmore,
175 };
176 
177 static int unload_module(void)
178 {
179  ast_unregister_switch(&loopback_switch);
180  return 0;
181 }
182 
183 static int load_module(void)
184 {
185  if (ast_register_switch(&loopback_switch))
188 }
189 
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:5420
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
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:132
struct ast_var_t * ast_var_assign(const char *name, const char *value)
Definition: chanvars.c:41
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:141
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
Configuration File Parser.
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
Definition: pbx.c:6457
static char * loopback_subst(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
Definition: pbx_loopback.c:86
I/O Management (derived from Cheops-NG)
void ast_var_delete(struct ast_var_t *var)
Definition: chanvars.c:63
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:5415
Utility functions.
static void loopback_parse(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
Definition: pbx_loopback.c:111
const char * name
Definition: pbx.h:130
General Asterisk PBX channel definitions.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Asterisk internal frame definitions.
Scheduler Routines (derived from cheops)
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:818
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:5400
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:177
static int load_module(void)
Definition: pbx_loopback.c:183
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
Definition: pbx.c:6439
#define LOOPBACK_COMMON
Definition: pbx_loopback.c:75
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2943
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:5425
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:666
Standard Command Line Interface.
static struct ast_switch loopback_switch
Definition: pbx_loopback.c:167
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
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)
Definition: pbx.c:4682
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180