diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c index e0de73d3ae0ce552bd48cc8322066488abb5a53d..1ead1d77256b812efd01325e5d1a6aa0c7bcba1a 100644 --- a/apps/app_directed_pickup.c +++ b/apps/app_directed_pickup.c @@ -5,6 +5,9 @@ * * Joshua Colp <jcolp@digium.com> * + * Portions merged from app_pickupchan, which was + * Copyright (C) 2008, Gary Cook + * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; @@ -21,6 +24,7 @@ * \brief Directed Call Pickup Support * * \author Joshua Colp <jcolp@digium.com> + * \author Gary Cook * * \ingroup applications */ @@ -51,6 +55,13 @@ static const char *descrip = "When no parameter is specified, the application will pickup a channel matching\n" "the pickup group of the active channel."; +static const char *app2 = "PickupChan"; +static const char *synopsis2 = "Pickup a ringing channel"; +static const char *descrip2 = +" PickupChan(channel[&channel...]): This application can pickup any ringing channel\n"; + +/*! \todo This application should return a result code, like PICKUPRESULT */ + /* Perform actual pickup between two channels */ static int pickup_do(struct ast_channel *chan, struct ast_channel *target) { @@ -85,6 +96,47 @@ static int can_pickup(struct ast_channel *chan) return 0; } +/*! \brief Helper Function to walk through ALL channels checking NAME and STATE */ +static struct ast_channel *my_ast_get_channel_by_name_locked(char *channame) +{ + struct ast_channel *chan; + char *chkchan = alloca(strlen(channame) + 2); + + /* need to append a '-' for the comparison so we check full channel name, + * i.e SIP/hgc- , use a temporary variable so original stays the same for + * debugging. + */ + strcpy(chkchan, channame); + strcat(chkchan, "-"); + + for (chan = ast_walk_channel_by_name_prefix_locked(NULL, channame, strlen(channame)); + chan; + chan = ast_walk_channel_by_name_prefix_locked(chan, channame, strlen(channame))) { + if (!strncasecmp(chan->name, chkchan, strlen(chkchan)) && can_pickup(chan)) + return chan; + ast_channel_unlock(chan); + } + return NULL; +} + +/*! \brief Attempt to pick up specified channel named , does not use context */ +static int pickup_by_channel(struct ast_channel *chan, char *pickup) +{ + int res = 0; + struct ast_channel *target; + + if (!(target = my_ast_get_channel_by_name_locked(pickup))) + return -1; + + /* Just check that we are not picking up the SAME as target */ + if (chan->name != target->name && chan != target) { + res = pickup_do(chan, target); + ast_channel_unlock(target); + } + + return res; +} + /* Attempt to pick up specified extension with context */ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const char *context) { @@ -126,7 +178,7 @@ static int pickup_by_mark(struct ast_channel *chan, const char *mark) return res; } -/* Main application entry point */ +/* application entry point for Pickup() */ static int pickup_exec(struct ast_channel *chan, void *data) { int res = 0; @@ -155,18 +207,51 @@ static int pickup_exec(struct ast_channel *chan, void *data) return res; } +/* application entry point for PickupChan() */ +static int pickupchan_exec(struct ast_channel *chan, void *data) +{ + int res = 0; + char *tmp = ast_strdupa(data); + char *pickup = NULL; + + if (ast_strlen_zero(data)) { + ast_log(LOG_WARNING, "PickupChan requires an argument (channel)!\n"); + return -1; + } + + /* Parse channel */ + while (!ast_strlen_zero(tmp) && (pickup = strsep(&tmp, "&"))) { + if (!strncasecmp(chan->name, pickup, strlen(pickup))) { + ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup); + } else { + if (!pickup_by_channel(chan, pickup)) { + break; + } + ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup); + } + } + + return res; +} + static int unload_module(void) { int res; res = ast_unregister_application(app); + res |= ast_unregister_application(app2); return res; } static int load_module(void) { - return ast_register_application(app, pickup_exec, synopsis, descrip); + int res; + + res = ast_register_application(app, pickup_exec, synopsis, descrip); + res |= ast_register_application(app2, pickupchan_exec, synopsis2, descrip2); + + return res; } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Directed Call Pickup Application"); diff --git a/apps/app_pickupchan.c b/apps/app_pickupchan.c deleted file mode 100644 index 6c3c4e3eff19a38f6c8bd104a003f501fbe0dd30..0000000000000000000000000000000000000000 --- a/apps/app_pickupchan.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 2008, Gary Cook - * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ - -/*! \file - * - * \brief Pickup a ringing channel - * - * \author Gary Cook - * - * \ingroup applications - */ - -#include "asterisk.h" - -ASTERISK_FILE_VERSION(__FILE__, "$Revision$") - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#include "asterisk/file.h" -#include "asterisk/logger.h" -#include "asterisk/channel.h" -#include "asterisk/pbx.h" -#include "asterisk/module.h" -#include "asterisk/lock.h" -#include "asterisk/app.h" -#include "asterisk/options.h" - -static const char *app = "PickupChan"; -static const char *synopsis = "Pickup a ringing channel"; -static const char *descrip = -" PickupChan(channel[&channel...]): This application can pickup any ringing channel\n"; - -/*! \todo This application should return a result code, like PICKUPRESULT */ - -/*! \brief Helper function that determines whether a channel is capable of being picked up */ -static int can_pickup(struct ast_channel *chan) -{ - ast_debug(3, "Checking Pickup '%s' state '%s ( %d )'\n", chan->name, ast_state2str(chan->_state), chan->_state); - - if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING)) { - return 1; - } else { - return 0; - } -} - -/*! \brief Helper Function to walk through ALL channels checking NAME and STATE */ -static struct ast_channel *my_ast_get_channel_by_name_locked(char *channame) -{ - struct ast_channel *chan; - char *chkchan = alloca(strlen(channame) + 2); - - /* need to append a '-' for the comparison so we check full channel name, - * i.e SIP/hgc- , use a temporary variable so original stays the same for - * debugging. - */ - strcpy(chkchan, channame); - strcat(chkchan, "-"); - - for (chan = ast_walk_channel_by_name_prefix_locked(NULL, channame, strlen(channame)); - chan; - chan = ast_walk_channel_by_name_prefix_locked(chan, channame, strlen(channame))) { - if (!strncasecmp(chan->name, chkchan, strlen(chkchan)) && can_pickup(chan)) - return chan; - ast_channel_unlock(chan); - } - return NULL; -} - -/*! \brief Perform actual pickup between two channels */ -static int pickup_do(struct ast_channel *chan, struct ast_channel *target) -{ - int res = 0; - - ast_debug(3, "Call pickup on '%s' by '%s'\n", target->name, chan->name); - - if ((res = ast_answer(chan))) { - ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); - return -1; - } - - if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) { - ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); - return -1; - } - - if ((res = ast_channel_masquerade(target, chan))) { - ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name); - return -1; - } - - return res; -} - -/*! \brief Attempt to pick up specified channel named , does not use context */ -static int pickup_by_channel(struct ast_channel *chan, char *pickup) -{ - int res = 0; - struct ast_channel *target; - - if (!(target = my_ast_get_channel_by_name_locked(pickup))) - return -1; - - /* Just check that we are not picking up the SAME as target */ - if (chan->name != target->name && chan != target) { - res = pickup_do(chan, target); - ast_channel_unlock(target); - } - - return res; -} - -/*! \brief Main application entry point */ -static int pickupchan_exec(struct ast_channel *chan, void *data) -{ - int res = 0; - struct ast_module_user *u = NULL; - char *tmp = ast_strdupa(data); - char *pickup = NULL, *context = NULL; - - if (ast_strlen_zero(data)) { - ast_log(LOG_WARNING, "Pickup requires an argument (channel)!\n"); - return -1; - } - - u = ast_module_user_add(chan); - - /* Parse channel (and ignore context if there) */ - while (!ast_strlen_zero(tmp) && (pickup = strsep(&tmp, "&"))) { - if ((context = strchr(pickup , '@'))) { - *context++ = '\0'; - } - if (!strncasecmp(chan->name, pickup , strlen(pickup))) { - ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup); - } else { - if (!pickup_by_channel(chan, pickup)) { - break; - } - ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup); - } - } - - ast_module_user_remove(u); - - return res; -} - -static int unload_module(void) -{ - return ast_unregister_application(app); -} - -static int load_module(void) -{ - return ast_register_application(app, pickupchan_exec, synopsis, descrip); -} - -AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel Pickup Application");