Thu May 24 14:21:12 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 <stdlib.h>
00026 #include <stdio.h>
00027 #include <unistd.h>
00028 #include <string.h>
00029 #include <errno.h>
00030 
00031 #include "asterisk.h"
00032 
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
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 static char *tdesc = "Loopback Switch";
00056 
00057 /* Loopback switch substitutes ${EXTEN}, ${CONTEXT}, and ${PRIORITY} into
00058    the data passed to it to try to get a string of the form:
00059 
00060    [exten]@context[:priority][/extramatch]
00061    
00062    Where exten, context, and priority are another extension, context, and priority
00063    to lookup and "extramatch" is an extra match restriction the *original* number 
00064    must fit if  specified.  The "extramatch" begins with _ like an exten pattern
00065    if it is specified.  Note that the search context MUST be a different context
00066    from the current context or the search will not succeed in an effort to reduce
00067    the likelihood of loops (they're still possible if you try hard, so be careful!)
00068 
00069 */
00070 
00071 
00072 #define LOOPBACK_COMMON \
00073    char buf[1024]; \
00074    int res; \
00075    char *newexten=(char *)exten, *newcontext=(char *)context; \
00076    int newpriority=priority; \
00077    char *newpattern=NULL; \
00078    loopback_helper(buf, sizeof(buf), exten, context, priority, data); \
00079    loopback_subst(&newexten, &newcontext, &newpriority, &newpattern, buf); \
00080    ast_log(LOG_DEBUG, "Parsed into %s @ %s priority %d\n", newexten, newcontext, newpriority); \
00081    if (!strcasecmp(newcontext, context)) return -1
00082 
00083 
00084 static char *loopback_helper(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data)
00085 {
00086    struct ast_var_t *newvariable;
00087    struct varshead headp;
00088    char tmp[80];
00089 
00090    snprintf(tmp, sizeof(tmp), "%d", priority);
00091    memset(buf, 0, buflen);
00092    AST_LIST_HEAD_INIT_NOLOCK(&headp);
00093    newvariable = ast_var_assign("EXTEN", exten);
00094    AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00095    newvariable = ast_var_assign("CONTEXT", context);
00096    AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00097    newvariable = ast_var_assign("PRIORITY", tmp);
00098    AST_LIST_INSERT_HEAD(&headp, newvariable, entries);
00099    pbx_substitute_variables_varshead(&headp, data, buf, buflen);
00100    /* Substitute variables */
00101    while (!AST_LIST_EMPTY(&headp)) {           /* List Deletion. */
00102       newvariable = AST_LIST_REMOVE_HEAD(&headp, entries);
00103       ast_var_delete(newvariable);
00104    }
00105    return buf;
00106 }
00107 
00108 static void loopback_subst(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       (*newpattern)++;
00116    }
00117    con = strchr(buf, '@');
00118    if (con) {
00119       *con = '\0';
00120       con++;
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, "%d", 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, int newstack, const char *data)
00151 {
00152    LOOPBACK_COMMON;
00153    if (newstack)
00154       res = ast_spawn_extension(chan, newcontext, newexten, newpriority, callerid);
00155    else
00156       res = ast_exec_extension(chan, newcontext, newexten, newpriority, callerid);
00157    if (newpattern && !ast_extension_match(newpattern, exten))
00158       res = -1;
00159    return res;
00160 }
00161 
00162 static int loopback_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
00163 {
00164    LOOPBACK_COMMON;
00165    res = ast_matchmore_extension(chan, newcontext, newexten, newpriority, callerid);
00166    if (newpattern && !ast_extension_match(newpattern, exten))
00167       res = 0;
00168    return res;
00169 }
00170 
00171 static struct ast_switch loopback_switch =
00172 {
00173         name:                   "Loopback",
00174         description:          "Loopback Dialplan Switch",
00175         exists:                 loopback_exists,
00176         canmatch:               loopback_canmatch,
00177         exec:                   loopback_exec,
00178         matchmore:              loopback_matchmore,
00179 };
00180 
00181 char *description(void)
00182 {
00183    return tdesc;
00184 }
00185 
00186 int usecount(void)
00187 {
00188    return 1;
00189 }
00190 
00191 char *key()
00192 {
00193    return ASTERISK_GPL_KEY;
00194 }
00195 
00196 int unload_module(void)
00197 {
00198    ast_unregister_switch(&loopback_switch);
00199    return 0;
00200 }
00201 
00202 int load_module(void)
00203 {
00204    ast_register_switch(&loopback_switch);
00205    return 0;
00206 }
00207 

Generated on Thu May 24 14:21:12 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.7