00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "asterisk.h"
00017
00018 #include <stdlib.h>
00019 #include <unistd.h>
00020 #include <string.h>
00021 #include <stdio.h>
00022 #include <signal.h>
00023 #include <pthread.h>
00024 #include <asterisk/lock.h>
00025 #include <asterisk/file.h>
00026 #include <asterisk/logger.h>
00027 #include <asterisk/channel.h>
00028 #include <asterisk/pbx.h>
00029 #include <asterisk/module.h>
00030 #include <asterisk/features.h>
00031 #include <asterisk/options.h>
00032
00033
00034 static char *app = "PickUp";
00035
00036 static char *synopsis = "Channel independent call pickup.";
00037
00038 static char *descrip =
00039 " PickDown([group]): Tries to pickup the first ringing channel with callgroup == group.\n"
00040 " If called without the group argument, the pickupgroup of the channel will be used.\n";
00041
00042 static char *app2 = "Steal";
00043
00044 static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
00045
00046 static char *descrip2 =
00047 " Steal([group]): Tries to steal the first bridged channel with callgroup == group.\n"
00048 " If called without the group argument, the pickupgroup of the channel will be used.\n";
00049
00050 static char *app3 = "PickDown";
00051
00052 static char *synopsis3 = "Channel independent call pickdown.";
00053
00054 static char *descrip3 =
00055 " PickDown([group]): Tries to hangup the first ringing channel with callgroup == group.\n"
00056 " If called without the group argument, the pickupgroup of the channel will be used.\n";
00057
00058 static char *app4 = "PickupChan";
00059
00060 static char *synopsis4 = "Channel independent call pickup.";
00061
00062 static char *descrip4 =
00063 " PickupChan(Technology/resource[&Technology2/resource2...]): Tries to pickup the first ringing channel in the parameter list.\n";
00064
00065 static char *app5 = "StealChan";
00066
00067 static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
00068
00069 static char *descrip5 =
00070 " StealChan(Technology/resource[&Technology2/resource2...]): Tries to steal the first ringing channel in the parameter list.\n";
00071
00072
00073 static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
00074 struct ast_channel *cur;
00075 int res = -1;
00076 cur = ast_channel_walk_locked(NULL);
00077 while(cur) {
00078 if ((cur != chan) &&
00079 (pickupgroup & cur->callgroup) &&
00080 (cur->_state == chanstate)) {
00081 break;
00082 }
00083 ast_mutex_unlock(&cur->lock);
00084 cur = ast_channel_walk_locked(cur);
00085 }
00086 if (cur) {
00087 if(option_verbose > 2) {
00088 if (chanstate == AST_STATE_RINGING) {
00089 if (bridge == 1) {
00090 ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
00091 } else {
00092 ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
00093 }
00094 } else {
00095 ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
00096 }
00097 }
00098 if (bridge == 1) {
00099 if (chan->_state != AST_STATE_UP) {
00100 ast_answer(chan);
00101 }
00102 if (ast_channel_masquerade(cur, chan)) {
00103 ast_log(LOG_ERROR, "unable to masquerade\n");
00104 }
00105 ast_mutex_unlock(&cur->lock);
00106 ast_mutex_unlock(&chan->lock);
00107 } else {
00108 cur->_softhangup = AST_SOFTHANGUP_DEV;
00109 ast_mutex_unlock(&cur->lock);
00110 }
00111 } else {
00112 if(option_verbose > 2) {
00113 ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
00114 }
00115 }
00116 return res;
00117 }
00118
00119 static int my_pickup_channel(struct ast_channel *chan, void *data, int chanstate, int bridge) {
00120 struct ast_channel *cur;
00121 char channels[256];
00122 char evalchan[256];
00123 char *endptr;
00124 int res = -1;
00125 cur = ast_channel_walk_locked(NULL);
00126 strncpy(channels, (char *)data, sizeof(channels) - 1);
00127 while(cur) {
00128 if ((cur != chan) &&
00129 (cur->_state == chanstate)) {
00130
00131 strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);
00132
00133 endptr = strrchr(evalchan, '-');
00134 if(endptr) {
00135 *endptr = '\0';
00136 }
00137
00138
00139 if(strstr(channels, evalchan) != NULL) {
00140 ast_verbose(VERBOSE_PREFIX_1 "Nice channel, I'll take it: %s\n",evalchan);
00141 break;
00142 }
00143 }
00144 ast_mutex_unlock(&cur->lock);
00145 cur = ast_channel_walk_locked(cur);
00146 }
00147 if (cur) {
00148 if(option_verbose > 2) {
00149 if (chanstate == AST_STATE_RINGING) {
00150 if (bridge == 1) {
00151 ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
00152 } else {
00153 ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
00154 }
00155 } else {
00156 ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
00157 }
00158 }
00159 if (bridge == 1) {
00160 if (chan->_state != AST_STATE_UP) {
00161 ast_answer(chan);
00162 }
00163 if (ast_channel_masquerade(cur, chan)) {
00164 ast_log(LOG_ERROR, "unable to masquerade\n");
00165 }
00166 ast_mutex_unlock(&cur->lock);
00167 ast_mutex_unlock(&chan->lock);
00168 } else {
00169 cur->_softhangup = AST_SOFTHANGUP_DEV;
00170 ast_mutex_unlock(&cur->lock);
00171 }
00172 } else {
00173 if(option_verbose > 2) {
00174 ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
00175 }
00176 }
00177 return res;
00178 }
00179
00180
00181 static int pickup_exec(struct ast_channel *chan, void *data)
00182 {
00183 int res=0;
00184 unsigned int pickupgroup=0;
00185 struct ast_module_user *u;
00186 if (!data || !strlen(data)) {
00187 pickupgroup = chan->pickupgroup;
00188 } else {
00189 pickupgroup = ast_get_group(data);
00190 }
00191 u = ast_module_user_add(chan);
00192 if (!res) {
00193 res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
00194 }
00195 if (res > 0)
00196 res = 0;
00197 ast_module_user_remove(u);
00198 return res;
00199 }
00200
00201 static int steal_exec(struct ast_channel *chan, void *data)
00202 {
00203 int res=0;
00204 unsigned int pickupgroup=0;
00205 struct ast_module_user *u;
00206 if (!data || !strlen(data)) {
00207 pickupgroup = chan->pickupgroup;
00208 } else {
00209 pickupgroup = ast_get_group(data);
00210 }
00211 u = ast_module_user_add(chan);
00212 if (!res) {
00213 res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
00214 }
00215 if (res > 0)
00216 res = 0;
00217 ast_module_user_remove(u);
00218 return res;
00219 }
00220
00221 static int pickdown_exec(struct ast_channel *chan, void *data)
00222 {
00223 int res=0;
00224 unsigned int pickupgroup=0;
00225 struct ast_module_user *u;
00226 if (!data || !strlen(data)) {
00227 pickupgroup = chan->pickupgroup;
00228 } else {
00229 pickupgroup = ast_get_group(data);
00230 }
00231 u = ast_module_user_add(chan);
00232 if (!res) {
00233 res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
00234 }
00235 if (res > 0)
00236 res = 0;
00237 ast_module_user_remove(u);
00238 return res;
00239 }
00240
00241 static int pickupchan_exec(struct ast_channel *chan, void *data) {
00242 int res=0;
00243 struct ast_module_user *u;
00244 if (!data) {
00245 ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
00246 return -1;
00247 }
00248 u = ast_module_user_add(chan);
00249 if (!res) {
00250 res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
00251 }
00252 if (res > 0)
00253 res = 0;
00254 ast_module_user_remove(u);
00255 return res;
00256 }
00257
00258 static int stealchan_exec(struct ast_channel *chan, void *data)
00259 {
00260 int res=0;
00261 struct ast_module_user *u;
00262 if (!data) {
00263 ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
00264 return -1;
00265 }
00266
00267 u = ast_module_user_add(chan);
00268 if (!res) {
00269 res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
00270 }
00271 if (res > 0)
00272 res = 0;
00273 ast_module_user_remove(u);
00274 return res;
00275 }
00276
00277
00278 static int unload_module(void)
00279 {
00280 ast_module_user_hangup_all();
00281 ast_unregister_application(app5);
00282 ast_unregister_application(app4);
00283 ast_unregister_application(app3);
00284 ast_unregister_application(app2);
00285 return ast_unregister_application(app);
00286 }
00287
00288 static int load_module(void)
00289 {
00290 ast_register_application(app5, stealchan_exec, synopsis5, descrip5);
00291 ast_register_application(app4, pickupchan_exec, synopsis4, descrip4);
00292 ast_register_application(app3, pickdown_exec, synopsis3, descrip3);
00293 ast_register_application(app2, steal_exec, synopsis2, descrip2);
00294 return ast_register_application(app, pickup_exec, synopsis, descrip);
00295 }
00296
00297 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PickUp/PickDown/Steal/PickupChan/StealChan",
00298 .load = load_module,
00299 .unload = unload_module,
00300 );