Wed Aug 7 17:15:43 2019

Asterisk developer's documentation


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 /*** MODULEINFO
00026    <support_level>core</support_level>
00027  ***/
00028 
00029 #include "asterisk.h"
00030 
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 396279 $")
00032 
00033 #include "asterisk/file.h"
00034 #include "asterisk/logger.h"
00035 #include "asterisk/channel.h"
00036 #include "asterisk/config.h"
00037 #include "asterisk/pbx.h"
00038 #include "asterisk/module.h"
00039 #include "asterisk/frame.h"
00040 #include "asterisk/cli.h"
00041 #include "asterisk/lock.h"
00042 #include "asterisk/md5.h"
00043 #include "asterisk/linkedlists.h"
00044 #include "asterisk/chanvars.h"
00045 #include "asterisk/sched.h"
00046 #include "asterisk/io.h"
00047 #include "asterisk/utils.h"
00048 #include "asterisk/astdb.h"
00049 
00050 
00051 /* Loopback switch creates a 'tunnel' to another context.  When extension
00052    lookups pass through the 'tunnel', Asterisk expressions can be used
00053    to modify the target extension, context, and priority in any way desired.
00054    If there is a match at the far end, execution jumps through the 'tunnel'
00055    to the matched context, extension, and priority.
00056  
00057    Global variables as well as ${CONTEXT}, ${EXTEN}, and ${PRIORITY} are 
00058    available for substitution.  After substitution Loopback expects to get
00059    a string of the form:
00060 
00061    [exten]@context[:priority][/extramatch]
00062    
00063    Where exten, context, and priority are another extension, context, and priority
00064    to lookup and "extramatch" is a dialplan extension pattern which the *original*
00065    number must match.  If exten or priority are empty, the original values are 
00066    used.
00067 
00068    Note that the search context MUST be a different context from the current
00069    context or the search will not succeed.  This is intended to reduce the
00070    likelihood of loops (they're still possible if you try hard, so be careful!)
00071 
00072 */
00073 
00074 
00075 #define LOOPBACK_COMMON \
00076    char buf[1024]; \
00077    int res; \
00078    char *newexten=(char *)exten, *newcontext=(char *)context; \
00079    int newpriority=priority; \
00080    char *newpattern=NULL; \
00081    loopback_subst(buf, sizeof(buf), exten, context, priority, data); \
00082    loopback_parse(&newexten, &newcontext, &newpriority, &newpattern, buf); \
00083    ast_log(LOG_DEBUG, "Parsed into %s @ %s priority %d\n", newexten, newcontext, newpriority); \
00084    if (!strcasecmp(newcontext, context)) return -1
00085 
00086 static char *loopback_subst(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
00087 {
00088    struct ast_var_t *newvariable;
00089    struct varshead headp;
00090    char tmp[80];
00091 
00092    snprintf(tmp, sizeof(tmp), "%d", priority);
00093    AST_LIST_HEAD_INIT_NOLOCK(&headp);
00094    if ((newvariable = ast_var_assign("EXTEN", exten))) {
00095       AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00096    }
00097    if ((newvariable = ast_var_assign("CONTEXT", context))) {
00098       AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00099    }
00100    if ((newvariable = ast_var_assign("PRIORITY", tmp))) {
00101       AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00102    }
00103    /* Substitute variables */
00104    pbx_substitute_variables_varshead(&headp, data, buf, buflen);
00105    /* free the list */
00106    while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
00107                 ast_var_delete(newvariable);
00108    return buf;
00109 }
00110 
00111 static void loopback_parse(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
00112 {
00113    char *con;
00114    char *pri;
00115    *newpattern = strchr(buf, '/');
00116    if (*newpattern)
00117       *(*newpattern)++ = '\0';
00118    con = strchr(buf, '@');
00119    if (con) {
00120       *con++ = '\0';
00121       pri = strchr(con, ':');
00122    } else
00123       pri = strchr(buf, ':');
00124    if (!ast_strlen_zero(buf))
00125       *newexten = buf;
00126    if (!ast_strlen_zero(con))
00127       *newcontext = con;
00128    if (!ast_strlen_zero(pri))
00129       sscanf(pri, "%30d", priority);
00130 }
00131 
00132 static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00133 {
00134    LOOPBACK_COMMON;
00135    res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid);
00136    if (newpattern && !ast_extension_match(newpattern, exten))
00137       res = 0;
00138    return res;
00139 }
00140 
00141 static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00142 {
00143    LOOPBACK_COMMON;
00144    res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid);
00145    if (newpattern && !ast_extension_match(newpattern, exten))
00146       res = 0;
00147    return res;
00148 }
00149 
00150 static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00151 {
00152    int found;
00153    LOOPBACK_COMMON;
00154    res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid, &found, 0);
00155    return res;
00156 }
00157 
00158 static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00159 {
00160    LOOPBACK_COMMON;
00161    res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
00162    if (newpattern && !ast_extension_match(newpattern, exten))
00163       res = 0;
00164    return res;
00165 }
00166 
00167 static struct ast_switch loopback_switch =
00168 {
00169    .name       = "Loopback",
00170    .description      = "Loopback Dialplan Switch",
00171    .exists        = loopback_exists,
00172    .canmatch      = loopback_canmatch,
00173    .exec       = loopback_exec,
00174    .matchmore     = loopback_matchmore,
00175 };
00176 
00177 static int unload_module(void)
00178 {
00179    ast_unregister_switch(&loopback_switch);
00180    return 0;
00181 }
00182 
00183 static int load_module(void)
00184 {
00185    if (ast_register_switch(&loopback_switch))
00186       return AST_MODULE_LOAD_FAILURE;
00187    return AST_MODULE_LOAD_SUCCESS;
00188 }
00189 
00190 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Loopback Switch");

Generated on 7 Aug 2019 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1