Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:55 2009

## 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: 211526 $")
    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, "%30d", 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