Thu Jul 9 13:40:17 2009

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: 162343 $")
00031 
00032 #include "asterisk/file.h"
00033 #include "asterisk/channel.h"
00034 #include "asterisk/pbx.h"
00035 #include "asterisk/module.h"
00036 #include "asterisk/lock.h"
00037 #include "asterisk/app.h"
00038 #include "asterisk/features.h"
00039 
00040 #define PICKUPMARK "PICKUPMARK"
00041 
00042 static const char *app = "Pickup";
00043 static const char *synopsis = "Directed Call Pickup";
00044 static const char *descrip =
00045 "  Pickup([extension[@context][&extension2@[context]...]]):  This application can\n"
00046 "pickup any ringing channel that is calling the specified extension.  If no\n"
00047 "context is specified, the current context will be used. If you use the special\n"
00048 "string \"PICKUPMARK\" for the context parameter, for example 10@PICKUPMARK,\n"
00049 "this application tries to find a channel which has defined a ${PICKUPMARK}\n"
00050 "channel variable with the same value as \"extension\" (in this example, \"10\").\n"
00051 "When no parameter is specified, the application will pickup a channel matching\n"
00052 "the pickup group of the active channel.";
00053 
00054 /* Perform actual pickup between two channels */
00055 static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
00056 {
00057    int res = 0;
00058 
00059    ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
00060 
00061    if ((res = ast_answer(chan))) {
00062       ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
00063       return -1;
00064    }
00065 
00066    if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
00067       ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
00068       return -1;
00069    }
00070 
00071    if ((res = ast_channel_masquerade(target, chan))) {
00072       ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
00073       return -1;
00074    }
00075 
00076    return res;
00077 }
00078 
00079 /* Helper function that determines whether a channel is capable of being picked up */
00080 static int can_pickup(struct ast_channel *chan)
00081 {
00082    if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
00083       return 1;
00084    else
00085       return 0;
00086 }
00087 
00088 /* Attempt to pick up specified extension with context */
00089 static int pickup_by_exten(struct ast_channel *chan, const char *exten, const char *context)
00090 {
00091    int res = -1;
00092    struct ast_channel *target = NULL;
00093 
00094    while ((target = ast_channel_walk_locked(target))) {
00095       if ((!strcasecmp(target->macroexten, exten) || !strcasecmp(target->exten, exten)) &&
00096          !strcasecmp(target->dialcontext, context) &&
00097          can_pickup(target)) {
00098          res = pickup_do(chan, target);
00099          ast_channel_unlock(target);
00100          break;
00101       }
00102       ast_channel_unlock(target);
00103    }
00104 
00105    return res;
00106 }
00107 
00108 /* Attempt to pick up specified mark */
00109 static int pickup_by_mark(struct ast_channel *chan, const char *mark)
00110 {
00111    int res = -1;
00112    const char *tmp = NULL;
00113    struct ast_channel *target = NULL;
00114 
00115    while ((target = ast_channel_walk_locked(target))) {
00116       if ((tmp = pbx_builtin_getvar_helper(target, PICKUPMARK)) &&
00117          !strcasecmp(tmp, mark) &&
00118          can_pickup(target)) {
00119          res = pickup_do(chan, target);
00120          ast_channel_unlock(target);
00121          break;
00122       }
00123       ast_channel_unlock(target);
00124    }
00125 
00126    return res;
00127 }
00128 
00129 /* Main application entry point */
00130 static int pickup_exec(struct ast_channel *chan, void *data)
00131 {
00132    int res = 0;
00133    char *tmp = ast_strdupa(data);
00134    char *exten = NULL, *context = NULL;
00135 
00136    if (ast_strlen_zero(data)) {
00137       res = ast_pickup_call(chan);
00138       return res;
00139    }
00140    
00141    /* Parse extension (and context if there) */
00142    while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
00143       if ((context = strchr(exten, '@')))
00144          *context++ = '\0';
00145       if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
00146          if (!pickup_by_mark(chan, exten))
00147             break;
00148       } else {
00149          if (!pickup_by_exten(chan, exten, !ast_strlen_zero(context) ? context : chan->context))
00150             break;
00151       }
00152       ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
00153    }
00154 
00155    return res;
00156 }
00157 
00158 static int unload_module(void)
00159 {
00160    int res;
00161 
00162    res = ast_unregister_application(app);
00163 
00164    return res;
00165 }
00166 
00167 static int load_module(void)
00168 {
00169    return ast_register_application(app, pickup_exec, synopsis, descrip);
00170 }
00171 
00172 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Directed Call Pickup Application");

Generated on Thu Jul 9 13:40:17 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7