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

Generated on Sat Aug 6 00:39:31 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7