00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 94826 $")
00029
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <unistd.h>
00034
00035 #include "asterisk/file.h"
00036 #include "asterisk/logger.h"
00037 #include "asterisk/channel.h"
00038 #include "asterisk/pbx.h"
00039 #include "asterisk/module.h"
00040 #include "asterisk/lock.h"
00041 #include "asterisk/app.h"
00042 #include "asterisk/options.h"
00043
00044 static const char *app = "PickupChan";
00045 static const char *synopsis = "Pickup a ringing channel";
00046 static const char *descrip =
00047 " PickupChan(channel[&channel...]): This application can pickup any ringing channel\n";
00048
00049
00050
00051
00052 static int can_pickup(struct ast_channel *chan)
00053 {
00054 ast_debug(3, "Checking Pickup '%s' state '%s ( %d )'\n", chan->name, ast_state2str(chan->_state), chan->_state);
00055
00056 if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING)) {
00057 return 1;
00058 } else {
00059 return 0;
00060 }
00061 }
00062
00063
00064 static struct ast_channel *my_ast_get_channel_by_name_locked(char *channame)
00065 {
00066 struct ast_channel *chan;
00067 char *chkchan = alloca(strlen(channame) + 2);
00068
00069
00070
00071
00072
00073 strcpy(chkchan, channame);
00074 strcat(chkchan, "-");
00075
00076 for (chan = ast_walk_channel_by_name_prefix_locked(NULL, channame, strlen(channame));
00077 chan;
00078 chan = ast_walk_channel_by_name_prefix_locked(chan, channame, strlen(channame))) {
00079 if (!strncasecmp(chan->name, chkchan, strlen(chkchan)) && can_pickup(chan))
00080 return chan;
00081 ast_channel_unlock(chan);
00082 }
00083 return NULL;
00084 }
00085
00086
00087 static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
00088 {
00089 int res = 0;
00090
00091 ast_debug(3, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
00092
00093 if ((res = ast_answer(chan))) {
00094 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
00095 return -1;
00096 }
00097
00098 if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
00099 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
00100 return -1;
00101 }
00102
00103 if ((res = ast_channel_masquerade(target, chan))) {
00104 ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
00105 return -1;
00106 }
00107
00108 return res;
00109 }
00110
00111
00112 static int pickup_by_channel(struct ast_channel *chan, char *pickup)
00113 {
00114 int res = 0;
00115 struct ast_channel *target;
00116
00117 if (!(target = my_ast_get_channel_by_name_locked(pickup)))
00118 return -1;
00119
00120
00121 if (chan->name != target->name && chan != target) {
00122 res = pickup_do(chan, target);
00123 ast_channel_unlock(target);
00124 }
00125
00126 return res;
00127 }
00128
00129
00130 static int pickupchan_exec(struct ast_channel *chan, void *data)
00131 {
00132 int res = 0;
00133 struct ast_module_user *u = NULL;
00134 char *tmp = ast_strdupa(data);
00135 char *pickup = NULL, *context = NULL;
00136
00137 if (ast_strlen_zero(data)) {
00138 ast_log(LOG_WARNING, "Pickup requires an argument (channel)!\n");
00139 return -1;
00140 }
00141
00142 u = ast_module_user_add(chan);
00143
00144
00145 while (!ast_strlen_zero(tmp) && (pickup = strsep(&tmp, "&"))) {
00146 if ((context = strchr(pickup , '@'))) {
00147 *context++ = '\0';
00148 }
00149 if (!strncasecmp(chan->name, pickup , strlen(pickup))) {
00150 ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup);
00151 } else {
00152 if (!pickup_by_channel(chan, pickup)) {
00153 break;
00154 }
00155 ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup);
00156 }
00157 }
00158
00159 ast_module_user_remove(u);
00160
00161 return res;
00162 }
00163
00164 static int unload_module(void)
00165 {
00166 return ast_unregister_application(app);
00167 }
00168
00169 static int load_module(void)
00170 {
00171 return ast_register_application(app, pickupchan_exec, synopsis, descrip);
00172 }
00173
00174 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel Pickup Application");