libiwinfo: support txpwrlist(), freqlist() and countrylist() for radioX pseudodevices...
[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");