Sat Mar 10 01:54:22 2012

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: 328209 $")
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    newvariable = ast_var_assign("EXTEN", exten);
00095    AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00096    newvariable = ast_var_assign("CONTEXT", context);
00097    AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00098    newvariable = ast_var_assign("PRIORITY", tmp);
00099    AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00100    /* Substitute variables */
00101    pbx_substitute_variables_varshead(&headp, data, buf, buflen);
00102    /* free the list */
00103    while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
00104                 ast_var_delete(newvariable);
00105    return buf;
00106 }
00107 
00108 static void loopback_parse(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
00109 {
00110    char *con;
00111    char *pri;
00112    *newpattern = strchr(buf, '/');
00113    if (*newpattern)
00114       *(*newpattern)++ = '\0';
00115    con = strchr(buf, '@');
00116    if (con) {
00117       *con++ = '\0';
00118       pri = strchr(con, ':');
00119    } else
00120       pri = strchr(buf, ':');
00121    if (!ast_strlen_zero(buf))
00122       *newexten = buf;
00123    if (!ast_strlen_zero(con))
00124       *newcontext = con;
00125    if (!ast_strlen_zero(pri))
00126       sscanf(pri, "%30d", priority);
00127 }
00128 
00129 static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00130 {
00131    LOOPBACK_COMMON;
00132    res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid);
00133    if (newpattern && !ast_extension_match(newpattern, exten))
00134       res = 0;
00135    return res;
00136 }
00137 
00138 static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00139 {
00140    LOOPBACK_COMMON;
00141    res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid);
00142    if (newpattern && !ast_extension_match(newpattern, exten))
00143       res = 0;
00144    return res;
00145 }
00146 
00147 static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00148 {
00149    int found;
00150    LOOPBACK_COMMON;
00151    res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid, &found, 0);
00152    return res;
00153 }
00154 
00155 static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00156 {
00157    LOOPBACK_COMMON;
00158    res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
00159    if (newpattern && !ast_extension_match(newpattern, exten))
00160       res = 0;
00161    return res;
00162 }
00163 
00164 static struct ast_switch loopback_switch =
00165 {
00166         name:                   "Loopback",
00167         description:       "Loopback Dialplan Switch",
00168         exists:                 loopback_exists,
00169         canmatch:               loopback_canmatch,
00170         exec:                   loopback_exec,
00171         matchmore:              loopback_matchmore,
00172 };
00173 
00174 static int unload_module(void)
00175 {
00176    ast_unregister_switch(&loopback_switch);
00177    return 0;
00178 }
00179 
00180 static int load_module(void)
00181 {
00182    if (ast_register_switch(&loopback_switch))
00183       return AST_MODULE_LOAD_FAILURE;
00184    return AST_MODULE_LOAD_SUCCESS;
00185 }
00186 
00187 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Loopback Switch");

Generated on Sat Mar 10 01:54:22 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7