Mon Jun 27 16:50:55 2011

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

Generated on Mon Jun 27 16:50:55 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7