Wed Feb 11 11:59:39 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: 162341 $")
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 /* Perform actual pickup between two channels */
00058 static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
00059 {
00060    int res = 0;
00061 
00062    if (option_debug)
00063       ast_log(LOG_DEBUG, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
00064 
00065    if ((res = ast_answer(chan))) {
00066       ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
00067       return -1;
00068    }
00069 
00070    if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
00071       ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
00072       return -1;
00073    }
00074 
00075    if ((res = ast_channel_masquerade(target, chan))) {
00076       ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
00077       return -1;
00078    }
00079 
00080    return res;
00081 }
00082 
00083 /* Helper function that determines whether a channel is capable of being picked up */
00084 static int can_pickup(struct ast_channel *chan)
00085 {
00086    if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
00087       return 1;
00088    else
00089       return 0;
00090 }
00091 
00092 /* Attempt to pick up specified extension with context */
00093 static int pickup_by_exten(struct ast_channel *chan, char *exten, char *context)
00094 {
00095    int res = -1;
00096    struct ast_channel *target = NULL;
00097 
00098    while ((target = ast_channel_walk_locked(target))) {
00099       if ((!strcasecmp(target->macroexten, exten) || !strcasecmp(target->exten, exten)) &&
00100           !strcasecmp(target->dialcontext, context) &&
00101           can_pickup(target)) {
00102          res = pickup_do(chan, target);
00103          ast_channel_unlock(target);
00104          break;
00105       }
00106       ast_channel_unlock(target);
00107    }
00108 
00109    return res;
00110 }
00111 
00112 /* Attempt to pick up specified mark */
00113 static int pickup_by_mark(struct ast_channel *chan, char *mark)
00114 {
00115    int res = -1;
00116    const char *tmp = NULL;
00117    struct ast_channel *target = NULL;
00118 
00119    while ((target = ast_channel_walk_locked(target))) {
00120       if ((tmp = pbx_builtin_getvar_helper(target, PICKUPMARK)) &&
00121           !strcasecmp(tmp, mark) &&
00122           can_pickup(target)) {
00123          res = pickup_do(chan, target);
00124          ast_channel_unlock(target);
00125          break;
00126       }
00127       ast_channel_unlock(target);
00128    }
00129 
00130    return res;
00131 }
00132 
00133 /* Main application entry point */
00134 static int pickup_exec(struct ast_channel *chan, void *data)
00135 {
00136    int res = 0;
00137    struct ast_module_user *u = NULL;
00138    char *tmp = ast_strdupa(data);
00139    char *exten = NULL, *context = NULL;
00140 
00141    if (ast_strlen_zero(data)) {
00142       ast_log(LOG_WARNING, "Pickup requires an argument (extension)!\n");
00143       return -1;  
00144    }
00145 
00146    u = ast_module_user_add(chan);
00147    
00148    /* Parse extension (and context if there) */
00149    while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
00150       if ((context = strchr(exten, '@')))
00151          *context++ = '\0';
00152       if (context && !strcasecmp(context, PICKUPMARK)) {
00153          if (!pickup_by_mark(chan, exten))
00154             break;
00155       } else {
00156          if (!pickup_by_exten(chan, exten, context ? context : chan->context))
00157             break;
00158       }
00159       ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
00160    }
00161 
00162    ast_module_user_remove(u);
00163 
00164    return res;
00165 }
00166 
00167 static int unload_module(void)
00168 {
00169    int res;
00170 
00171    res = ast_unregister_application(app);
00172    
00173    return res;
00174 }
00175 
00176 static int load_module(void)
00177 {
00178    return ast_register_application(app, pickup_exec, synopsis, descrip);
00179 }
00180 
00181 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Directed Call Pickup Application");

Generated on Wed Feb 11 11:59:39 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7