Sat Aug 6 00:39:20 2011

Asterisk developer's documentation


app_directed_pickup.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2005, Joshua Colp
00005  *
00006  * Joshua Colp <jcolp@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 Directed Call Pickup Support
00022  *
00023  * \author Joshua Colp <jcolp@digium.com>
00024  *
00025  * \ingroup applications
00026  */
00027 
00028 #include "asterisk.h"
00029 
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 318734 $")
00031 
00032 #include <stdlib.h>
00033 #include <stdio.h>
00034 #include <string.h>
00035 #include <unistd.h>
00036 
00037 #include "asterisk/file.h"
00038 #include "asterisk/logger.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/module.h"
00042 #include "asterisk/lock.h"
00043 #include "asterisk/app.h"
00044 #include "asterisk/options.h"
00045 
00046 #define PICKUPMARK "PICKUPMARK"
00047 
00048 static const char *app = "Pickup";
00049 static const char *synopsis = "Directed Call Pickup";
00050 static const char *descrip =
00051 "  Pickup(extension[@context][&extension2@context...]): This application can pickup any ringing channel\n"
00052 "that is calling the specified extension. If no context is specified, the current\n"
00053 "context will be used. If you use the special string \"PICKUPMARK\" for the context parameter, for example\n"
00054 "10@PICKUPMARK, this application tries to find a channel which has defined a channel variable with the same content\n"
00055 "as \"extension\".";
00056 
00057 /*!
00058  * \internal
00059  * \brief Perform actual pickup between two channels.
00060  * \note Must remain in sync with same function in res/res_features.c.
00061  */
00062 static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
00063 {
00064    if (option_debug)
00065       ast_log(LOG_DEBUG, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
00066 
00067    if (ast_answer(chan)) {
00068       ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
00069       return -1;
00070    }
00071 
00072    if (ast_queue_control(chan, AST_CONTROL_ANSWER)) {
00073       ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
00074       return -1;
00075    }
00076 
00077    if (ast_channel_masquerade(target, chan)) {
00078       ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
00079       return -1;
00080    }
00081 
00082    return 0;
00083 }
00084 
00085 /* Helper function that determines whether a channel is capable of being picked up */
00086 static int can_pickup(struct ast_channel *chan)
00087 {
00088    if (!chan->pbx && !chan->masq &&
00089       !ast_test_flag(chan, AST_FLAG_ZOMBIE) &&
00090       (chan->_state == AST_STATE_RINGING ||
00091        chan->_state == AST_STATE_RING ||
00092        chan->_state == AST_STATE_DOWN)) {
00093       return 1;
00094    }
00095    return 0;
00096 }
00097 
00098 /* Attempt to pick up specified extension with context */
00099 static int pickup_by_exten(struct ast_channel *chan, char *exten, char *context)
00100 {
00101    int res = -1;
00102    struct ast_channel *target = NULL;
00103 
00104    while ((target = ast_channel_walk_locked(target))) {
00105       if ((!strcasecmp(target->macroexten, exten) || !strcasecmp(target->exten, exten)) &&
00106           !strcasecmp(target->dialcontext, context) &&
00107           (chan != target) && can_pickup(target)) {
00108          res = pickup_do(chan, target);
00109          ast_channel_unlock(target);
00110          break;
00111       }
00112       ast_channel_unlock(target);
00113    }
00114 
00115    return res;
00116 }
00117 
00118 /* Attempt to pick up specified mark */
00119 static int pickup_by_mark(struct ast_channel *chan, char *mark)
00120 {
00121    int res = -1;
00122    const char *tmp = NULL;
00123    struct ast_channel *target = NULL;
00124 
00125    while ((target = ast_channel_walk_locked(target))) {
00126       if ((tmp = pbx_builtin_getvar_helper(target, PICKUPMARK)) &&
00127           !strcasecmp(tmp, mark) &&
00128           can_pickup(target)) {
00129          res = pickup_do(chan, target);
00130          ast_channel_unlock(target);
00131          break;
00132       }
00133       ast_channel_unlock(target);
00134    }
00135 
00136    return res;
00137 }
00138 
00139 /* Main application entry point */
00140 static int pickup_exec(struct ast_channel *chan, void *data)
00141 {
00142    int res = 0;
00143    struct ast_module_user *u = NULL;
00144    char *tmp = ast_strdupa(data);
00145    char *exten = NULL, *context = NULL;
00146 
00147    if (ast_strlen_zero(data)) {
00148       ast_log(LOG_WARNING, "Pickup requires an argument (extension)!\n");
00149       return -1;  
00150    }
00151 
00152    u = ast_module_user_add(chan);
00153    
00154    /* Parse extension (and context if there) */
00155    while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
00156       if ((context = strchr(exten, '@')))
00157          *context++ = '\0';
00158       if (context && !strcasecmp(context, PICKUPMARK)) {
00159          if (!pickup_by_mark(chan, exten))
00160             break;
00161       } else {
00162          if (!pickup_by_exten(chan, exten, context ? context : chan->context))
00163             break;
00164       }
00165       ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
00166    }
00167 
00168    ast_module_user_remove(u);
00169 
00170    return res;
00171 }
00172 
00173 static int unload_module(void)
00174 {
00175    int res;
00176 
00177    res = ast_unregister_application(app);
00178    
00179    return res;
00180 }
00181 
00182 static int load_module(void)
00183 {
00184    return ast_register_application(app, pickup_exec, synopsis, descrip);
00185 }
00186 
00187 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Directed Call Pickup Application");

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