Mon Mar 31 07:37:55 2008

Asterisk developer's documentation


app_pickup2.c

Go to the documentation of this file.
00001 /*
00002  * Pickup, channel independent call pickup
00003  *
00004  * This program is free software, distributed under the terms of
00005  * the GNU General Public License
00006  *
00007  * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
00008  * Klaus-Peter Junghanns <kpj@junghanns.net>
00009  * Copyright (C) 2004, Junghanns.NET GmbH
00010  * Copyright (C) 2005-2007, Thorsten Knabe <ast@thorsten-knabe.de>
00011  * Copyright (C) 2007, 1.4 porting by Antonio Gallo (AGX) www.badpenguin.org www.mercuriuspbx.it
00012  *
00013  */
00014 
00015 #include <asterisk.h>
00016 
00017 #include <stdlib.h>
00018 #include <unistd.h>
00019 #include <string.h>
00020 #include <stdio.h>
00021 #include <signal.h>
00022 #include <pthread.h>
00023 
00024 #include <asterisk/file.h>
00025 #include <asterisk/logger.h>
00026 #include <asterisk/channel.h>
00027 #include <asterisk/pbx.h>
00028 #include <asterisk/module.h>
00029 #include <asterisk/adsi.h>
00030 #include <asterisk/musiconhold.h>
00031 #include <asterisk/features.h>
00032 #include <asterisk/options.h>
00033 #include <asterisk/utils.h>
00034 #include <asterisk/lock.h>
00035 
00036 #define  AST_MODULE  "app_pickup2"
00037 
00038 static char *app = "PickUp2";
00039 static char *synopsis = "PickUp ringing channel.";
00040 static char *descrip =
00041 "  PickUp2(Technology/resource[&Technology2/resource2&...]):\n"
00042 "Matches the list of prefixes in the parameter list against channels in\n"
00043 "state RINGING. If a match is found the channel is picked up and\n"
00044 "PICKUP_CHANNEL is set to the picked up channel name. If no matching\n"
00045 "channel is found PICKUP_CHANNEL is empty.\n";
00046 
00047 static char *app2 = "PickDown2";
00048 static char *synopsis2 = "Hangup ringing channel.";
00049 static char *descrip2 =
00050 "  PickDown2(Technology/resource[&Technology2/resource2&...]):\n"
00051 "Matches the list of prefixes in the parameter list against channels in\n"
00052 "state RINGING. If a match is found the channel is hung up and\n"
00053 "PICKDOWN_CHANNEL is set to the hung up channel name. If no matching\n"
00054 "channel is found PICKDOWN_CHANNEL is empty.\n";
00055 
00056 static char *app3 = "Steal2";
00057 static char *synopsis3 = "Steal a connected channel.";
00058 
00059 static char *descrip3 =
00060 "  Steal2(Technology/resource[&Technology2/resource2&...]):\n"
00061 "Matches the list of prefixes in the parameter list against channels in\n"
00062 "state UP. If a match is found the channel is stolen and\n"
00063 "STEAL_CHANNEL is set to the stolen channel name. If no matching\n"
00064 "channel is found STEAL_CHANNEL is empty.\n";
00065 
00066 /* Find channel matching given pattern and state, skipping our own channel.
00067  * Returns locked channel, which has to be unlocked using ast_mutex_unlock().
00068  * Returns NULL when no matching channel is found.
00069  */
00070 static struct ast_channel *find_matching_channel(struct ast_channel *chan, void *pattern, int chanstate)
00071 {
00072    struct ast_channel *cur;
00073    char *pat = NULL;
00074    char *next_pat = NULL;
00075 
00076    /* copy original pattern or use empty pattern if no pattern has been given */
00077    if (pattern) {
00078       pat = alloca(strlen(pattern) + 1);
00079       strcpy(pat, pattern);
00080    } else {
00081       pat = "";
00082    }
00083    ast_verbose(VERBOSE_PREFIX_4 "find_matching_channel: pattern='%s' state=%d\n", (char *) pattern, chanstate);
00084 
00085    /* Iterate over each part of the pattern */
00086    while (pat) {
00087       /* find pattern for next iteration, terminate current pattern */
00088       for (next_pat = pat; *next_pat && *next_pat != '&'; next_pat++);
00089       if (*next_pat == '&') {
00090          *next_pat = 0;
00091          next_pat++;
00092       } else
00093          next_pat = NULL;
00094       /* Iterate over all channels */
00095       cur = ast_channel_walk_locked(NULL);
00096       while (cur) {
00097          ast_verbose(VERBOSE_PREFIX_4 "find_matching_channel: trying channel='%s' " "state=%d pattern='%s'\n", cur->name, cur->_state, pat);
00098          if ((cur != chan) && (cur->_state == chanstate) && !strncmp(pat, cur->name, strlen(pat))) {
00099             ast_verbose(VERBOSE_PREFIX_4 "find_matching_channel: " "found channel='%s'\n", cur->name);
00100             return (cur);
00101          }
00102          ast_mutex_unlock(&cur->lock);
00103          cur = ast_channel_walk_locked(cur);
00104       }
00105       pat = next_pat;
00106    }
00107    return (NULL);
00108 }
00109 
00110 static int pickup_channel(struct ast_channel *chan, void *pattern)
00111 {
00112    int ret = 0;
00113    struct ast_module_user *u;
00114    struct ast_channel *cur;
00115    u = ast_module_user_add(chan);
00116    cur = find_matching_channel(chan, pattern, AST_STATE_RINGING);
00117    if (cur) {
00118       ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n", chan->name, cur->name);
00119       pbx_builtin_setvar_helper(chan, "PICKUP_CHANNEL", cur->name);
00120       if (chan->_state != AST_STATE_UP) {
00121          ast_answer(chan);
00122       }
00123       if (ast_channel_masquerade(cur, chan)) {
00124          ast_log(LOG_ERROR, "unable to masquerade\n");
00125          ret = -1;
00126       }
00127       ast_mutex_unlock(&cur->lock);
00128       ast_mutex_unlock(&chan->lock);
00129    } else {
00130       pbx_builtin_setvar_helper(chan, "PICKUP_CHANNEL", "");
00131    }
00132    ast_module_user_remove(u);
00133    return (ret);
00134 }
00135 
00136 static int pickdown_channel(struct ast_channel *chan, void *pattern)
00137 {
00138    int ret = 0;
00139    struct ast_module_user *u;
00140    struct ast_channel *cur;
00141    u = ast_module_user_add(chan);
00142    cur = find_matching_channel(chan, pattern, AST_STATE_RINGING);
00143    if (cur) {
00144       ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n", chan->name, cur->name);
00145       pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", cur->name);
00146       ast_softhangup_nolock(cur, AST_SOFTHANGUP_DEV);
00147       ast_mutex_unlock(&cur->lock);
00148    } else
00149       pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", "");
00150    ast_module_user_remove(u);
00151    return (ret);
00152 }
00153 
00154 static int steal_channel(struct ast_channel *chan, void *pattern)
00155 {
00156    int ret = 0;
00157    struct ast_module_user *u;
00158    struct ast_channel *cur;
00159    u = ast_module_user_add(chan);
00160    cur = find_matching_channel(chan, pattern, AST_STATE_UP);
00161    if (cur) {
00162       ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n", chan->name, cur->name);
00163       pbx_builtin_setvar_helper(chan, "STEAL_CHANNEL", cur->name);
00164       if (chan->_state != AST_STATE_UP) {
00165          ast_answer(chan);
00166       }
00167       if (cur->_bridge) {
00168          if (!ast_mutex_lock(&cur->_bridge->lock)) {
00169             ast_moh_stop(cur->_bridge);
00170             ast_mutex_unlock(&cur->_bridge->lock);
00171          }
00172       }
00173 
00174       if (ast_channel_masquerade(cur, chan)) {
00175          ast_log(LOG_ERROR, "unable to masquerade\n");
00176          ret = -1;
00177       }
00178       ast_mutex_unlock(&cur->lock);
00179       ast_mutex_unlock(&chan->lock);
00180    } else
00181       pbx_builtin_setvar_helper(chan, "STEAL_CHANNEL", "");
00182    ast_module_user_remove(u);
00183    return (ret);
00184 }
00185 
00186 static int unload_module(void)
00187 {
00188    int res;
00189    ast_module_user_hangup_all();
00190    res |= ast_unregister_application(app3);
00191    res |= ast_unregister_application(app2);
00192    res = ast_unregister_application(app);
00193    return res;
00194 }
00195 
00196 static int load_module(void)
00197 {
00198    ast_register_application(app3, steal_channel, synopsis3, descrip3);
00199    ast_register_application(app2, pickdown_channel, synopsis2, descrip2);
00200    return ast_register_application(app, pickup_channel, synopsis, descrip);
00201 }
00202 
00203 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "PickUp2/PickDown2/Steal2 version 0.1");

Generated on Mon Mar 31 07:37:55 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1