Sat Apr 12 07:12:16 2008

Asterisk developer's documentation


app_pickup.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- A telephony toolkit for Linux.
00003  *
00004  * Pickup, channel independent call pickup
00005  * 
00006  * Copyright (C) 2004, Junghanns.NET GmbH
00007  *
00008  * Klaus-Peter Junghanns <kpj@junghanns.net>
00009  *
00010  * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU General Public License
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                                /* This call is a candidate (correct ringstate and not ourselves), now check if the channel is in our list */
00131                                strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);                             
00132                                /* strip the subchannel tag */
00133                                endptr = strrchr(evalchan, '-');
00134                                if(endptr) {
00135                                        *endptr = '\0';
00136                                }
00137                                /* check for each of the members if they match (probably a stristr will do ?) */
00138                                /* if we match the code, break */
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 );

Generated on Sat Apr 12 07:12:16 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.5