modules/admin-full: fix wifi join
[project/luci.git] / contrib / package / asterisk-xip / patches / 040-pickup2.patch
1 *** xx/apps/app_pickup2.c 1970-01-01 08:00:00.000000000 +0800
2 --- asterisk-1.4.22/apps/app_pickup2.c 2009-01-19 17:44:07.483909506 +0900
3 ***************
4 *** 0 ****
5 --- 1,279 ----
6 + /*
7 + * Asterisk -- A telephony toolkit for Linux.
8 + *
9 + * Pickup, channel independent call pickup
10 + *
11 + * Copyright (C) 2005-2007, Thorsten Knabe <ast@thorsten-knabe.de>
12 + *
13 + * Copyright (C) 2004, Junghanns.NET GmbH
14 + *
15 + * Klaus-Peter Junghanns <kpj@junghanns.net>
16 + *
17 + * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
18 + *
19 + * This program is free software, distributed under the terms of
20 + * the GNU General Public License
21 + */
22 +
23 + /*** MODULEINFO
24 + <defaultenabled>yes</defaultenabled>
25 + ***/
26 +
27 + #include "asterisk.h"
28 +
29 + ASTERISK_FILE_VERSION(__FILE__, "$Revision: 2 $")
30 +
31 + #include <stdlib.h>
32 + #include <unistd.h>
33 + #include <string.h>
34 + #include <stdio.h>
35 + #include <signal.h>
36 + #include <pthread.h>
37 + #include "asterisk/lock.h"
38 + #include "asterisk/file.h"
39 + #include "asterisk/logger.h"
40 + #include "asterisk/channel.h"
41 + #include "asterisk/pbx.h"
42 + #include "asterisk/module.h"
43 + #include "asterisk/musiconhold.h"
44 + #include "asterisk/features.h"
45 + #include "asterisk/options.h"
46 +
47 + static char *app = "PickUp2";
48 + static char *synopsis = "PickUp ringing channel.";
49 + static char *descrip =
50 + " PickUp2(Technology/resource[&Technology2/resource2&...][|<option>]):\n"
51 + "Matches the list of prefixes in the parameter list against channels in\n"
52 + "state RINGING. If a match is found the channel is picked up and\n"
53 + "PICKUP_CHANNEL is set to the picked up channel name. If no matching\n"
54 + "channel is found PICKUP_CHANNEL is empty.\n"
55 + "Possible options:\n"
56 + "B: match on channel name of bridged channel.\n";
57 +
58 + static char *app2 = "PickDown2";
59 + static char *synopsis2 = "Hangup ringing channel.";
60 + static char *descrip2 =
61 + " PickDown2(Technology/resource[&Technology2/resource2&...][|<option>]):\n"
62 + "Matches the list of prefixes in the parameter list against channels in\n"
63 + "state RINGING. If a match is found the channel is hung up and\n"
64 + "PICKDOWN_CHANNEL is set to the hung up channel name. If no matching\n"
65 + "channel is found PICKDOWN_CHANNEL is empty.\n"
66 + "Possible options:\n"
67 + "B: match on channel name of bridged channel.\n";
68 +
69 + static char *app3 = "Steal2";
70 + static char *synopsis3 = "Steal a connected channel.";
71 +
72 + static char *descrip3 =
73 + " Steal2(Technology/resource[&Technology2/resource2&...][|<option>]):\n"
74 + "Matches the list of prefixes in the parameter list against channels in\n"
75 + "state UP. If a match is found the channel is stolen and\n"
76 + "STEAL_CHANNEL is set to the stolen channel name. If no matching\n"
77 + "channel is found STEAL_CHANNEL is empty.\n"
78 + "Possible options:\n"
79 + "B: match on channel name of bridged channel.\n";
80 +
81 + /* Find channel matching given pattern and state, skipping our own channel.
82 + * Returns locked channel, which has to be unlocked using ast_mutex_unlock().
83 + * Returns NULL when no matching channel is found.
84 + */
85 + static struct ast_channel *find_matching_channel(struct ast_channel *chan,
86 + void *pattern, int chanstate)
87 + {
88 + struct ast_channel *cur;
89 + char *pat = "";
90 + char *next_pat = NULL;
91 + char *option = "";
92 + struct ast_channel *bridged;
93 +
94 + /* copy original pattern or use empty pattern if no pattern has been given*/
95 + if (pattern) {
96 + pat = alloca(strlen(pattern) + 1);
97 + strcpy(pat, pattern);
98 + }
99 + for (option = pat; *option; option++) {
100 + if (*option == '|') {
101 + *option = '\0';
102 + option++;
103 + break;
104 + }
105 + }
106 + ast_verbose(VERBOSE_PREFIX_4
107 + "find_matching_channel: pattern='%s' option='%s' state=%d\n",
108 + (char *)pat, option, chanstate);
109 +
110 + /* match on bridged channel name */
111 + if (!strcmp("B", option)) {
112 + /* Iterate over each part of the pattern */
113 + while (pat) {
114 + /* find pattern for next iteration,
115 + * terminate current pattern */
116 + for (next_pat = pat;
117 + *next_pat && *next_pat != '&'; next_pat++);
118 + if (*next_pat == '&') {
119 + *next_pat = 0;
120 + next_pat++;
121 + } else
122 + next_pat = NULL;
123 + /* Iterate over all channels */
124 + cur = ast_channel_walk_locked(NULL);
125 + while (cur) {
126 + bridged = ast_bridged_channel(cur);
127 + if (bridged) {
128 + ast_verbose(VERBOSE_PREFIX_4
129 + "find_matching_channel: trying channel='%s' bridged='%s' "
130 + "state=%d pattern='%s'\n",
131 + cur->name, bridged->name, cur->_state, pat);
132 + if ((cur != chan) && (bridged != chan) &&
133 + (cur->_state == chanstate) &&
134 + !strncmp(pat, bridged->name, strlen(pat))) {
135 + ast_verbose(VERBOSE_PREFIX_4
136 + "find_matching_channel: "
137 + "found channel='%s' bridged='%s'\n",
138 + cur->name, bridged->name);
139 + return(cur);
140 + }
141 + }
142 + ast_mutex_unlock(&cur->lock);
143 + cur = ast_channel_walk_locked(cur);
144 + }
145 + pat = next_pat;
146 + }
147 + } else {
148 + /* Iterate over each part of the pattern */
149 + while (pat) {
150 + /* find pattern for next iteration,
151 + * terminate current pattern */
152 + for (next_pat = pat;
153 + *next_pat && *next_pat != '&'; next_pat++);
154 + if (*next_pat == '&') {
155 + *next_pat = 0;
156 + next_pat++;
157 + } else
158 + next_pat = NULL;
159 + /* Iterate over all channels */
160 + cur = ast_channel_walk_locked(NULL);
161 + while (cur) {
162 + ast_verbose(VERBOSE_PREFIX_4
163 + "find_matching_channel: trying channel='%s' "
164 + "state=%d pattern='%s'\n",
165 + cur->name, cur->_state, pat);
166 + if ((cur != chan) &&
167 + (cur->_state == chanstate) &&
168 + !strncmp(pat, cur->name, strlen(pat))) {
169 + ast_verbose(VERBOSE_PREFIX_4
170 + "find_matching_channel: "
171 + "found channel='%s'\n",
172 + cur->name);
173 + return(cur);
174 + }
175 + ast_mutex_unlock(&cur->lock);
176 + cur = ast_channel_walk_locked(cur);
177 + }
178 + pat = next_pat;
179 + }
180 + }
181 + return(NULL);
182 + }
183 +
184 + static int pickup_channel(struct ast_channel *chan, void *pattern)
185 + {
186 + int ret = 0;
187 + struct ast_module_user *u;
188 + struct ast_channel *cur;
189 + u = ast_module_user_add(chan);
190 + cur = find_matching_channel(chan, pattern, AST_STATE_RINGING);
191 + if (cur) {
192 + ast_verbose(VERBOSE_PREFIX_3
193 + "Channel %s picked up ringing channel %s\n",
194 + chan->name, cur->name);
195 + pbx_builtin_setvar_helper(chan, "PICKUP_CHANNEL", cur->name);
196 + if (chan->_state != AST_STATE_UP) {
197 + ast_answer(chan);
198 + }
199 + if (ast_channel_masquerade(cur, chan)) {
200 + ast_log(LOG_ERROR, "unable to masquerade\n");
201 + ret = -1;
202 + }
203 + ast_mutex_unlock(&cur->lock);
204 + ast_mutex_unlock(&chan->lock);
205 + } else {
206 + pbx_builtin_setvar_helper(chan, "PICKUP_CHANNEL", "");
207 + }
208 + ast_module_user_remove(u);
209 + return(ret);
210 + }
211 +
212 + static int pickdown_channel(struct ast_channel *chan, void *pattern)
213 + {
214 + int ret = 0;
215 + struct ast_module_user *u;
216 + struct ast_channel *cur;
217 + u = ast_module_user_add(chan);
218 + cur = find_matching_channel(chan, pattern, AST_STATE_RINGING);
219 + if (cur) {
220 + ast_verbose(VERBOSE_PREFIX_3
221 + "Channel %s hung up ringing channel %s\n",
222 + chan->name, cur->name);
223 + pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", cur->name);
224 + ast_softhangup_nolock(cur, AST_SOFTHANGUP_DEV);
225 + ast_mutex_unlock(&cur->lock);
226 + } else {
227 + pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", "");
228 + }
229 + ast_module_user_remove(u);
230 + return(ret);
231 + }
232 +
233 + static int steal_channel(struct ast_channel *chan, void *pattern)
234 + {
235 + int ret = 0;
236 + struct ast_module_user *u;
237 + struct ast_channel *cur;
238 + u = ast_module_user_add(chan);
239 + cur = find_matching_channel(chan, pattern, AST_STATE_UP);
240 + if (cur) {
241 + ast_verbose(VERBOSE_PREFIX_3
242 + "Channel %s stole channel %s\n",
243 + chan->name, cur->name);
244 + pbx_builtin_setvar_helper(chan, "STEAL_CHANNEL", cur->name);
245 + if (chan->_state != AST_STATE_UP) {
246 + ast_answer(chan);
247 + }
248 + if (cur->_bridge) {
249 + if (!ast_mutex_lock(&cur->_bridge->lock)) {
250 + ast_moh_stop(cur->_bridge);
251 + ast_mutex_unlock(&cur->_bridge->lock);
252 + }
253 + }
254 +
255 + if (ast_channel_masquerade(cur, chan)) {
256 + ast_log(LOG_ERROR, "unable to masquerade\n");
257 + ret = -1;
258 + }
259 + ast_mutex_unlock(&cur->lock);
260 + ast_mutex_unlock(&chan->lock);
261 + } else {
262 + pbx_builtin_setvar_helper(chan, "STEAL_CHANNEL", "");
263 + }
264 + ast_module_user_remove(u);
265 + return(ret);
266 + }
267 +
268 + static int unload_module(void)
269 + {
270 + ast_module_user_hangup_all();
271 + ast_unregister_application(app3);
272 + ast_unregister_application(app2);
273 + return ast_unregister_application(app);
274 + }
275 +
276 + static int load_module(void)
277 + {
278 + ast_register_application(app3, steal_channel, synopsis3, descrip3);
279 + ast_register_application(app2, pickdown_channel, synopsis2, descrip2);
280 + return ast_register_application(app, pickup_channel, synopsis, descrip);
281 + }
282 +
283 + AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY,
284 + "PickUp2, PickDown2, Steal2 Application");