00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00067
00068
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
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
00086 while (pat) {
00087
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
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");