Mon May 14 04:43:00 2007

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$")
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 substitutes ${EXTEN}, ${CONTEXT}, and ${PRIORITY} into
00057    the data passed to it to try to get a string of the form:
00058 
00059    [exten]@context[:priority][/extramatch]
00060    
00061    Where exten, context, and priority are another extension, context, and priority
00062    to lookup and "extramatch" is an extra match restriction the *original* number 
00063    must fit if  specified.  The "extramatch" begins with _ like an exten pattern
00064    if it is specified.  Note that the search context MUST be a different context
00065    from the current context or the search will not succeed in an effort to reduce
00066    the 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_helper(buf, sizeof(buf), exten, context, priority, data); \
00078    loopback_subst(&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 
00083 static char *loopback_helper(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
00084 {
00085    struct ast_var_t *newvariable;
00086    struct varshead headp;
00087    char tmp[80];
00088 
00089    snprintf(tmp, sizeof(tmp), "%d", priority);
00090    memset(buf, 0, buflen);
00091    AST_LIST_HEAD_INIT_NOLOCK(&headp);
00092    AST_LIST_INSERT_HEAD(&headp, ast_var_assign("EXTEN", exten), entries);
00093    AST_LIST_INSERT_HEAD(&headp, ast_var_assign("CONTEXT", context), entries);
00094    AST_LIST_INSERT_HEAD(&headp, ast_var_assign("PRIORITY", tmp), entries);
00095    /* Substitute variables */
00096    pbx_substitute_variables_varshead(&headp, data, buf, buflen);
00097    /* free the list */
00098    while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries)))
00099                 ast_var_delete(newvariable);
00100    return buf;
00101 }
00102 
00103 static void loopback_subst(char **newexten, char **newcontext, int *priority, char **newpattern, char *buf)
00104 {
00105    char *con;
00106    char *pri;
00107    *newpattern = strchr(buf, '/');
00108    if (*newpattern)
00109       *(*newpattern)++ = '\0';
00110    con = strchr(buf, '@');
00111    if (con) {
00112       *con++ = '\0';
00113       pri = strchr(con, ':');
00114    } else
00115       pri = strchr(buf, ':');
00116    if (!ast_strlen_zero(buf))
00117       *newexten = buf;
00118    if (!ast_strlen_zero(con))
00119       *newcontext = con;
00120    if (!ast_strlen_zero(pri))
00121       sscanf(pri, "%d", priority);
00122 }
00123 
00124 static int loopback_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00125 {
00126    LOOPBACK_COMMON;
00127    res = ast_exists_extension(chan, newcontext, newexten, newpriority, callerid);
00128    if (newpattern && !ast_extension_match(newpattern, exten))
00129       res = 0;
00130    return res;
00131 }
00132 
00133 static int loopback_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00134 {
00135    LOOPBACK_COMMON;
00136    res = ast_canmatch_extension(chan, newcontext, newexten, newpriority, callerid);
00137    if (newpattern && !ast_extension_match(newpattern, exten))
00138       res = 0;
00139    return res;
00140 }
00141 
00142 static int loopback_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00143 {
00144    LOOPBACK_COMMON;
00145    res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid);
00146    /* XXX hmmm... res is overridden ? */
00147    if (newpattern && !ast_extension_match(newpattern, exten))
00148       res = -1;
00149    return res;
00150 }
00151 
00152 static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00153 {
00154    LOOPBACK_COMMON;
00155    res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
00156    if (newpattern && !ast_extension_match(newpattern, exten))
00157       res = 0;
00158    return res;
00159 }
00160 
00161 static struct ast_switch loopback_switch =
00162 {
00163         name:                   "Loopback",
00164         description:       "Loopback Dialplan Switch",
00165         exists:                 loopback_exists,
00166         canmatch:               loopback_canmatch,
00167         exec:                   loopback_exec,
00168         matchmore:              loopback_matchmore,
00169 };
00170 
00171 static int unload_module(void)
00172 {
00173    ast_unregister_switch(&loopback_switch);
00174    return 0;
00175 }
00176 
00177 static int load_module(void)
00178 {
00179    ast_register_switch(&loopback_switch);
00180    return 0;
00181 }
00182 
00183 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Loopback Switch");

Generated on Mon May 14 04:43:00 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1