]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/asterisk.patch
Hinzugefuegt:
[people/pmueller/ipfire-2.x.git] / src / patches / asterisk.patch
1 diff -urN asterisk-1.2.10.orig/.version asterisk-1.2.10/.version
2 --- asterisk-1.2.10.orig/.version 2006-07-14 23:29:33.000000000 +0200
3 +++ asterisk-1.2.10/.version 2006-07-31 14:13:27.000000000 +0200
4 @@ -1 +1 @@
5 -1.2.10
6 +1.2.10-BRIstuffed-0.3.0-PRE-1s
7 diff -urN asterisk-1.2.10.orig/HARDWARE asterisk-1.2.10/HARDWARE
8 --- asterisk-1.2.10.orig/HARDWARE 2005-11-29 19:24:39.000000000 +0100
9 +++ asterisk-1.2.10/HARDWARE 2006-07-31 14:13:08.000000000 +0200
10 @@ -37,6 +37,19 @@
11 * Wildcard TE410P - Quad T1/E1 switchable interface. Supports PRI and
12 RBS signalling, as well as PPP, FR, and HDLC data modes.
13
14 +-- Junghanns.NET (Primary author of BRIstuff)
15 + http://www.junghanns.net
16 +
17 + * quadBRI PCI ISDN - 4port BRI ISDN interface, supports NT and TE mode
18 +
19 + * octoBRI PCI ISDN - 8port BRI ISDN interface, supports NT and TE mode
20 +
21 + * singleE1 PCI ISDN - Single E1 interface
22 +
23 + * doubleE1 PCI ISDN - Double E1 interface
24 +
25 + * uno/duo/quad GSM PCI - 1/2/4 channel GSM interface cards
26 +
27 Non-zaptel compatible hardware
28 ==============================
29
30 diff -urN asterisk-1.2.10.orig/LICENSE asterisk-1.2.10/LICENSE
31 --- asterisk-1.2.10.orig/LICENSE 2005-11-29 19:24:39.000000000 +0100
32 +++ asterisk-1.2.10/LICENSE 2006-07-31 14:13:08.000000000 +0200
33 @@ -1,7 +1,7 @@
34 -Asterisk is distributed under the GNU General Public License version 2
35 -and is also available under alternative licenses negotiated directly
36 -with Digium, Inc. If you obtained Asterisk under the GPL, then the GPL
37 -applies to all loadable Asterisk modules used on your system as well,
38 +BRIstuffed Asterisk is distributed under the GNU General Public License version 2
39 +and is not available under any alternative licenses.
40 +If you obtained BRIstuffed Asterisk under the GPL, then the GPL
41 +applies to all loadable BRIstuffed Asterisk modules used on your system as well,
42 except as defined below. The GPL (version 2) is included in this
43 source tree in the file COPYING.
44
45 diff -urN asterisk-1.2.10.orig/Makefile asterisk-1.2.10/Makefile
46 --- asterisk-1.2.10.orig/Makefile 2006-06-29 21:23:18.000000000 +0200
47 +++ asterisk-1.2.10/Makefile 2006-08-10 11:07:53.000000000 +0200
48 @@ -772,6 +772,9 @@
49 echo ";astctlowner = root" ; \
50 echo ";astctlgroup = apache" ; \
51 echo ";astctl = asterisk.ctl" ; \
52 + echo "[options]" ; \
53 + echo "uniquename = `hostname`" ;\
54 + echo "silence_suppression = yes" ;\
55 ) > $(DESTDIR)$(ASTCONFPATH) ; \
56 else \
57 echo "Skipping asterisk.conf creation"; \
58 diff -urN asterisk-1.2.10.orig/README asterisk-1.2.10/README
59 --- asterisk-1.2.10.orig/README 2006-03-03 09:12:33.000000000 +0100
60 +++ asterisk-1.2.10/README 2006-07-31 14:13:08.000000000 +0200
61 @@ -4,6 +4,8 @@
62
63 Copyright (C) 2001-2005 Digium, Inc.
64 and other copyright holders.
65 +Copyright (C) 2002-2005 Junghanns.NET GmbH
66 +and other copyright holders.
67 ================================================================
68
69 * SECURITY
70 diff -urN asterisk-1.2.10.orig/README.chan_capi asterisk-1.2.10/README.chan_capi
71 --- asterisk-1.2.10.orig/README.chan_capi 1970-01-01 01:00:00.000000000 +0100
72 +++ asterisk-1.2.10/README.chan_capi 2006-07-31 14:13:08.000000000 +0200
73 @@ -0,0 +1,146 @@
74 +(CAPI*) chan_capi a Common ISDN API 2.0 implementation for Asterisk
75 +(C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
76 +Klaus-Peter Junghanns <kpj@junghanns.net>
77 +
78 +This program is free software and may be modified and distributed under
79 +the terms of the GNU Public License. There is _NO_ warranty for this!
80 +
81 +Thanks go to the debuggers and bugfixers (listed in chronological order) :)
82 +===========================================================================
83 +Lele Forzani <lele@windmill.it>
84 +Florian Overkamp <florian@obsimref.com>
85 +Gareth Watts <gareth@omnipotent.net>
86 +Jeff Noxon <jeff@planetfall.com>
87 +Petr Michalek <petr.michalek@aca.cz>
88 +Jan Stocker
89 +(...and all the others that i forgot..) :-)
90 +
91 +chan_capi version 0.4.0-PRE1 includes:
92 +======================================
93 +
94 +- multiple controller support
95 +- CID,DNID (callling party, called party)
96 +- CLIR/CLIP
97 +- supplementary services, CD,HOLD,RETRIEVE,ECT
98 +- DTMF (dependend on card) + software DTMF support
99 +- early B3 connects (always,success,never)
100 +- digital audio (what did you think?)
101 +- incoming/outgoing calls
102 +- overlap sending (dialtone)
103 +- E(xplicit) C(all) T(ransfer) (...although it's done implicit .. but dont tell!)
104 +- tuneable latency ;) you can configure the size of B3 blocks at compile time
105 + (in chan_capi_pvt.h, AST_CAPI_MAX_B3_BLOCK_SIZE)
106 + the default is 160 samples, for non-VoIP use you can tune it down to 130
107 +- use asterisk's internal dsp functions for dtmf
108 +- alaw support
109 +- ulaw support!
110 +- Eicon CAPI echo cancelation (echocancel=1)
111 +- reject call waiting (ACO)
112 +- DID for Point to Point mode (a.k.a overlap receiving)
113 +- experimental echo squelching (echosquelch=1)
114 +- call progress, no need to add ||r to your dialstring anymore
115 +- rx/tx gains (rxgain=1.0)
116 +- call deflection on circuitbusy (makefile option) (deflect=12345678)
117 +- (inter)national dialing prefix (for callerid) configurable in capi.conf
118 +- CLI command "capi info" shows B channel status
119 +- capiECT will announce the callerID since it gets lost on most isdn pbxes
120 + the called party can press # to drop the call
121 +- audio syncing (timing outgoing dataB3 on incoming dataB3), supposed to fix
122 + the DATA_B3_REQ (error = 0x1103) problem
123 +- catch all MSN (incomingmsn=*)
124 +- some configuration enhancements (msn=123,124,125 and controller=1,2,3,4)
125 +- accountcode= added.
126 +- finally the echo squelching works!
127 +- callgroup support
128 +- fixed pipe leak
129 +- updated to support the new frame->delivery field
130 +- compiles with latest cvs with a makefile option (LOOK AT THE MAKEFILE)
131 +- fixed channel name bug in p2p mode
132 +- added app_capiNoES for disabling the primitive echo suppressor, use this before
133 + you start recording voicemail or your files may get choppy
134 +- fixed for latest cvs (AST_MUTEX_DEFINE_STATIC)
135 +- fixed for latest cvs (asterisk/parking.h -> asterisk/features.h)
136 +- fixed for latest cvs ast_pthread_create
137 +
138 +- ATTENTION! the dialstring syntax now uses the zaptel dialstring syntax
139 + it used to be: Dial(CAPI/[@]<outgoingMSN>:[b|B]<destination>)
140 +
141 + now it is: Dial(CAPI/g<group>/[b|B]<destination>)
142 + or: Dial(CAPI/contr<controller>/[b|B]<destination>)
143 +
144 + CLIP/CLIR is now uses the calling presentation of the calling channel, this can
145 + be modified using the CallingPres() application. Use CallinPres(32) for CLIR.
146 + That is why the msn= param in capi.conf is now obsolete. The callerID is also
147 + taken from the calling channel.
148 +
149 +- fixes for BSD (Jan Stocker)
150 +
151 +Helper applications
152 +===================
153 +kapejod says: "No No No, dont use those yet....!" (except maybe HOLD,ECT...)
154 +
155 +app_capiCD.c forwards an unanswered call to another phone (does not rely on sservice CD)
156 + example:
157 + exten => s,1,Wait,1
158 + exten => s,2,capiCD,12345678
159 +
160 +app_capiHOLD.c puts an answered call on hold, this has nothing to do with asterisk's onhold thingie (music et al)
161 + after putting a call onhold, never use the Wait application!
162 +
163 +app_capiRETRIEVE.c gets the holded call back
164 +
165 +app_capiECT.c explicit call transfer of the holded call (must put call on hold first!)
166 + example:
167 + exten => s,1,Answer
168 + exten => s,2,capiHOLD
169 + exten => s,3,capiECT,55:50
170 + will ECT the call to 50 using 55 as the callerid/outgoing msn
171 +
172 +
173 +Using CLIR
174 +==========
175 +Use the CallingPres() application before you dial:
176 +exten => _X.,1,CallingPres(32)
177 +exten => _X.,2,Dial(CAPI/contr1/${EXTEN})
178 +
179 +Enjoying early B3 connects (inband call progress, tones and announcements)
180 +==========================================================================
181 +early B3 is now configurable in the dialstring :)
182 +if you prefix the destination number with a 'b' early B3 will always be used, also if the call fails
183 +because the number is unprovisioned, etc ...
184 +if you prefix it with a 'B' early B3 will only be used on successful calls, giving you ring indication,etc...
185 +
186 +dont use indications in the Dial command, your local exchange will do that for you:
187 +exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30) (early B3 on success)
188 +exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30) (always early B3)
189 +exten => _X.,1,Dial(CAPI/contr1/${EXTEN},30,r) (no early B3, fake ring indication)
190 +
191 +exten => _X.,1,Dial(CAPI/contr1/b${EXTEN},30,r) (always early B3, fake indicatons if the exchange
192 + does not give us indications)
193 +exten => _X.,1,Dial(CAPI/contr1/B${EXTEN},30,r) (early B3 on success, fake indicatons if the exchange
194 + does not give us indications)
195 +
196 +you can totally turn B3 off in the Makefile at buildtime (-DNEVER_EVER_EARLY_B3_CONNECTS).
197 +
198 +For normal PBX usage you would use the "b" option, always early B3.
199 +
200 +Overlap sending (a.k.a. real dialtone)
201 +======================================
202 +when you dial an empty number, and have early B3 enabled, with:
203 + Dial(CAPI/g1/b)
204 +the channel will come up at once and give you the dialtone it gets from the local exchange.
205 +at this point the channel is like a legacy phone, now you can send dtmf digits to dial.
206 +
207 +Example context for incoming calls on MSN 12345678:
208 +===================================================
209 +
210 +[capi-in]
211 +exten => 12345678,1,Dial(SIP/phone1)
212 +exten => 12345678,2,Hangup
213 +
214 +
215 +More information/documentation and commercial support can be found at:
216 + http://www.junghanns.net/asterisk/
217 +
218 +
219 +
220 diff -urN asterisk-1.2.10.orig/agi/Makefile asterisk-1.2.10/agi/Makefile
221 --- asterisk-1.2.10.orig/agi/Makefile 2006-03-28 22:22:05.000000000 +0200
222 +++ asterisk-1.2.10/agi/Makefile 2006-07-31 14:13:08.000000000 +0200
223 @@ -11,7 +11,7 @@
224 # the GNU General Public License
225 #
226
227 -AGIS=agi-test.agi eagi-test eagi-sphinx-test
228 +AGIS=agi-test.agi eagi-test eagi-sphinx-test xagi-test
229
230 CFLAGS+=-DNO_AST_MM
231
232 @@ -37,7 +37,7 @@
233 $(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o $(LIBS)
234
235 clean:
236 - rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
237 + rm -f *.so *.o look .depend eagi-test eagi-sphinx-test xagi-test
238
239 %.so : %.o
240 $(CC) -shared -Xlinker -x -o $@ $<
241 diff -urN asterisk-1.2.10.orig/agi/xagi-test.c asterisk-1.2.10/agi/xagi-test.c
242 --- asterisk-1.2.10.orig/agi/xagi-test.c 1970-01-01 01:00:00.000000000 +0100
243 +++ asterisk-1.2.10/agi/xagi-test.c 2006-07-31 14:13:08.000000000 +0200
244 @@ -0,0 +1,175 @@
245 +/*
246 + * Asterisk -- A telephony toolkit for Linux.
247 + *
248 + * XAGI sample script
249 + *
250 + * Copyright (C) 2005 Junghanns.NET GmbH
251 + * Klaus-Peter Junghanns <kpj@junghanns.net>
252 + *
253 + * based on eagi-test.c
254 + *
255 + * This program is free software, distributed under the terms of
256 + * the GNU General Public License
257 + */
258 +
259 +#include <stdio.h>
260 +#include <unistd.h>
261 +#include <stdlib.h>
262 +#include <errno.h>
263 +#include <string.h>
264 +#include <sys/select.h>
265 +#ifdef SOLARIS
266 +#include <solaris-compat/compat.h>
267 +#endif
268 +
269 +#define AUDIO_FILENO_IN (STDERR_FILENO + 1)
270 +#define AUDIO_FILENO_OUT (STDERR_FILENO + 2)
271 +
272 +static int read_environment(void)
273 +{
274 + char buf[256];
275 + char *val;
276 + /* Read environment */
277 + for(;;) {
278 + fgets(buf, sizeof(buf), stdin);
279 + if (feof(stdin))
280 + return -1;
281 + buf[strlen(buf) - 1] = '\0';
282 + /* Check for end of environment */
283 + if (!strlen(buf))
284 + return 0;
285 + val = strchr(buf, ':');
286 + if (!val) {
287 + fprintf(stderr, "Invalid environment: '%s'\n", buf);
288 + return -1;
289 + }
290 + *val = '\0';
291 + val++;
292 + val++;
293 + /* Skip space */
294 + // fprintf(stderr, "Environment: '%s' is '%s'\n", buf, val);
295 +
296 + /* Load into normal environment */
297 + setenv(buf, val, 1);
298 +
299 + }
300 + /* Never reached */
301 + return 0;
302 +}
303 +
304 +static void app_echo(void)
305 +{
306 + fd_set fds;
307 + int res;
308 + int bytes = 0;
309 + static char astresp[256];
310 + char audiobuf[16000]; /* 1 second of audio */
311 + for (;;) {
312 + FD_ZERO(&fds);
313 + FD_SET(STDIN_FILENO, &fds);
314 + FD_SET(AUDIO_FILENO_IN, &fds);
315 + /* Wait for *some* sort of I/O */
316 + res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
317 + if (res < 0) {
318 + fprintf(stderr, "Error in select: %s\n", strerror(errno));
319 + return;
320 + }
321 + if (FD_ISSET(STDIN_FILENO, &fds)) {
322 + fgets(astresp, sizeof(astresp), stdin);
323 + if (feof(stdin)) {
324 + return;
325 + }
326 + astresp[strlen(astresp) - 1] = '\0';
327 + fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
328 + return;
329 + }
330 + if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
331 + /* what goes in.... */
332 + res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
333 + if (res > 0) {
334 + bytes = res;
335 + /* must come out */
336 + write(AUDIO_FILENO_OUT, audiobuf, bytes);
337 + }
338 + }
339 + }
340 +}
341 +
342 +static char *wait_result(void)
343 +{
344 + fd_set fds;
345 + int res;
346 + static char astresp[256];
347 + char audiobuf[4096];
348 + for (;;) {
349 + FD_ZERO(&fds);
350 + FD_SET(STDIN_FILENO, &fds);
351 + FD_SET(AUDIO_FILENO_IN, &fds);
352 + /* Wait for *some* sort of I/O */
353 + res = select(AUDIO_FILENO_IN + 1, &fds, NULL, NULL, NULL);
354 + if (res < 0) {
355 + fprintf(stderr, "Error in select: %s\n", strerror(errno));
356 + return NULL;
357 + }
358 + if (FD_ISSET(STDIN_FILENO, &fds)) {
359 + fgets(astresp, sizeof(astresp), stdin);
360 + if (feof(stdin)) {
361 + fprintf(stderr, "Got hungup on apparently\n");
362 + return NULL;
363 + }
364 + astresp[strlen(astresp) - 1] = '\0';
365 + fprintf(stderr, "Ooh, got a response from Asterisk: '%s'\n", astresp);
366 + return astresp;
367 + }
368 + if (FD_ISSET(AUDIO_FILENO_IN, &fds)) {
369 + res = read(AUDIO_FILENO_IN, audiobuf, sizeof(audiobuf));
370 + /* drop it, like it's hot */
371 + }
372 + }
373 +
374 +}
375 +
376 +static char *run_command(char *command)
377 +{
378 + fprintf(stdout, "%s\n", command);
379 + return wait_result();
380 +}
381 +
382 +
383 +static int run_script(void)
384 +{
385 + char *res;
386 + res = run_command("STREAM FILE demo-echotest \"\"");
387 + if (!res) {
388 + fprintf(stderr, "Failed to execute command\n");
389 + return -1;
390 + }
391 + app_echo();
392 + return 0;
393 +}
394 +
395 +int main(int argc, char *argv[])
396 +{
397 + char *tmp;
398 + int ver = 0;
399 + int subver = 0;
400 + /* Setup stdin/stdout for line buffering */
401 + setlinebuf(stdin);
402 + setlinebuf(stdout);
403 + if (read_environment()) {
404 + fprintf(stderr, "Failed to read environment: %s\n", strerror(errno));
405 + exit(1);
406 + }
407 + tmp = getenv("agi_enhanced");
408 + if (tmp) {
409 + if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
410 + ver = 0;
411 + }
412 + if (ver < 2) {
413 + fprintf(stderr, "No XAGI services available. Use XAGI, not AGI or EAGI\n");
414 + exit(1);
415 + }
416 + if (run_script())
417 + return -1;
418 + exit(0);
419 +}
420 diff -urN asterisk-1.2.10.orig/apps/Makefile asterisk-1.2.10/apps/Makefile
421 --- asterisk-1.2.10.orig/apps/Makefile 2006-04-30 15:38:22.000000000 +0200
422 +++ asterisk-1.2.10/apps/Makefile 2006-07-31 14:13:08.000000000 +0200
423 @@ -28,8 +28,15 @@
424 app_test.so app_forkcdr.so app_math.so app_realtime.so \
425 app_dumpchan.so app_waitforsilence.so app_while.so app_setrdnis.so \
426 app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so \
427 + app_pickup.so app_segfault.so app_callingpres.so app_devstate.so \
428 app_dictate.so app_externalivr.so app_directed_pickup.so \
429 - app_mixmonitor.so app_stack.so
430 + app_mixmonitor.so app_stack.so
431 +
432 +
433 +ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
434 + APPS+= app_capiNoES.so app_capiCD.so app_capiECT.so
435 +endif
436 +
437
438 #
439 # Obsolete things...
440 diff -urN asterisk-1.2.10.orig/apps/app_callingpres.c asterisk-1.2.10/apps/app_callingpres.c
441 --- asterisk-1.2.10.orig/apps/app_callingpres.c 1970-01-01 01:00:00.000000000 +0100
442 +++ asterisk-1.2.10/apps/app_callingpres.c 2006-07-31 14:13:08.000000000 +0200
443 @@ -0,0 +1,70 @@
444 +/*
445 + * An application to change the CallingPresentation for an Asterisk channel.
446 + *
447 + * Copyright (C) 2005 Junghanns.NET GmbH
448 + * Klaus-Peter Junghanns <kpj@junghanns.net>
449 + *
450 + * This program is free software, distributed under the terms of
451 + * the GNU General Public License.
452 + *
453 + */
454 +
455 +#include <stdlib.h>
456 +#include <unistd.h>
457 +#include <string.h>
458 +#include <stdio.h>
459 +#include <asterisk/lock.h>
460 +#include <asterisk/file.h>
461 +#include <asterisk/logger.h>
462 +#include <asterisk/channel.h>
463 +#include <asterisk/pbx.h>
464 +#include <asterisk/module.h>
465 +
466 +static char *synopsis_callingpres = "Change the presentation for the callerid";
467 +static char *descrip_callingpres = "Callingpres(number): Changes the presentation for the callerid. Should be called before placing an outgoing call\n";
468 +static char *app_callingpres = "CallingPres";
469 +STANDARD_LOCAL_USER;
470 +LOCAL_USER_DECL;
471 +
472 +
473 +static int change_callingpres(struct ast_channel *chan, void *data)
474 +{
475 + int mode = 0;
476 + struct localuser *u;
477 + LOCAL_USER_ADD(u);
478 + if (data) {
479 + mode = atoi((char *)data);
480 + chan->cid.cid_pres = mode;
481 + } else
482 + ast_log(LOG_NOTICE, "Application %s requres an argument: %s(number)\n", app_callingpres,app_callingpres);
483 + LOCAL_USER_REMOVE(u);
484 + return 0;
485 +}
486 +
487 +int unload_module(void)
488 +{
489 + STANDARD_HANGUP_LOCALUSERS;
490 + return ast_unregister_application(app_callingpres);
491 +}
492 +
493 +int load_module(void)
494 +{
495 + return ast_register_application(app_callingpres, change_callingpres, synopsis_callingpres, descrip_callingpres);
496 +}
497 +
498 +char *description(void)
499 +{
500 + return descrip_callingpres;
501 +}
502 +
503 +int usecount(void)
504 +{
505 + int res;
506 + STANDARD_USECOUNT(res);
507 + return res;
508 +}
509 +
510 +char *key()
511 +{
512 + return ASTERISK_GPL_KEY;
513 +}
514 diff -urN asterisk-1.2.10.orig/apps/app_capiCD.c asterisk-1.2.10/apps/app_capiCD.c
515 --- asterisk-1.2.10.orig/apps/app_capiCD.c 1970-01-01 01:00:00.000000000 +0100
516 +++ asterisk-1.2.10/apps/app_capiCD.c 2006-07-31 14:13:08.000000000 +0200
517 @@ -0,0 +1,172 @@
518 +/*
519 + * (CAPI*)
520 + *
521 + * An implementation of Common ISDN API 2.0 for Asterisk
522 + *
523 + * Call Deflection, inspired by capircvd by Alexander Brickwedde
524 + *
525 + * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
526 + *
527 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
528 + *
529 + * This program is free software and may be modified and
530 + * distributed under the terms of the GNU Public License.
531 + */
532 +
533 +#include <stdlib.h>
534 +#include <unistd.h>
535 +#include <string.h>
536 +#include <stdio.h>
537 +#include <linux/capi.h>
538 +#include <capi20.h>
539 +
540 +#include <asterisk/file.h>
541 +#include <asterisk/logger.h>
542 +#include <asterisk/channel.h>
543 +#include <asterisk/pbx.h>
544 +#include <asterisk/module.h>
545 +#include <asterisk/chan_capi.h>
546 +#include <asterisk/chan_capi_app.h>
547 +
548 +
549 +
550 +static char *tdesc = "(CAPI*) Call Deflection, the magic thing.";
551 +static char *app = "capiCD";
552 +static char *synopsis = "call deflection";
553 +
554 +STANDARD_LOCAL_USER;
555 +
556 +LOCAL_USER_DECL;
557 +
558 +static int capiCD_exec(struct ast_channel *chan, void *data)
559 +{
560 + struct ast_capi_pvt *i = chan->tech_pvt;
561 + MESSAGE_EXCHANGE_ERROR Info;
562 + _cmsg CMSG;
563 + char bchaninfo[1];
564 + char fac[60];
565 + int res=0;
566 + int ms=3000;
567 + struct localuser *u;
568 +
569 + if (!data) {
570 + ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
571 + return -1;
572 + }
573 + LOCAL_USER_ADD(u);
574 + /* Do our thing here */
575 +
576 + if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
577 + ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
578 + LOCAL_USER_REMOVE(u);
579 + return -1;
580 + }
581 + // wait until the channel is alerting, so we dont drop the call and interfer with msgs
582 + while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
583 + sleep(100);
584 + ms -= 100;
585 + }
586 +
587 + // make sure we hang up correctly
588 + i->state = CAPI_STATE_CONNECTPENDING;
589 +
590 + fac[0]=0; // len
591 + fac[1]=0; //len
592 + fac[2]=0x01; // Use D-Chan
593 + fac[3]=0; // Keypad len
594 + fac[4]=31; // user user data? len = 31 = 29 + 2
595 + fac[5]=0x1c; // magic?
596 + fac[6]=0x1d; // strlen destination + 18 = 29
597 + fac[7]=0x91; // ..
598 + fac[8]=0xA1;
599 + fac[9]=0x1A; // strlen destination + 15 = 26
600 + fac[10]=0x02;
601 + fac[11]=0x01;
602 + fac[12]=0x70;
603 + fac[13]=0x02;
604 + fac[14]=0x01;
605 + fac[15]=0x0d;
606 + fac[16]=0x30;
607 + fac[17]=0x12; // strlen destination + 7 = 18
608 + fac[18]=0x30; // ...hm 0x30
609 + fac[19]=0x0d; // strlen destination + 2
610 + fac[20]=0x80; // CLIP
611 + fac[21]=0x0b; // strlen destination
612 + fac[22]=0x01; // destination start
613 + fac[23]=0x01; //
614 + fac[24]=0x01; //
615 + fac[25]=0x01; //
616 + fac[26]=0x01; //
617 + fac[27]=0x01; //
618 + fac[28]=0x01; //
619 + fac[29]=0x01; //
620 + fac[30]=0x01; //
621 + fac[31]=0x01; //
622 + fac[32]=0x01; //
623 + fac[33]=0x01; // 0x1 = sending complete
624 + fac[34]=0x01;
625 + fac[35]=0x01;
626 +
627 + memcpy((unsigned char *)fac+22,data,strlen(data));
628 + fac[22+strlen(data)]=0x01; // fill with 0x01 if number is only 6 numbers (local call)
629 + fac[23+strlen(data)]=0x01;
630 + fac[24+strlen(data)]=0x01;
631 + fac[25+strlen(data)]=0x01;
632 + fac[26+strlen(data)]=0x01;
633 +
634 + fac[6]=18+strlen(data);
635 + fac[9]=15+strlen(data);
636 + fac[17]=7+strlen(data);
637 + fac[19]=2+strlen(data);
638 + fac[21]=strlen(data);
639 +
640 + bchaninfo[0] = 0x1;
641 + INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
642 + INFO_REQ_CONTROLLER(&CMSG) = i->controller;
643 + INFO_REQ_PLCI(&CMSG) = i->PLCI;
644 + INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
645 + INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
646 + INFO_REQ_USERUSERDATA(&CMSG) = 0;
647 + INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
648 +
649 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
650 + ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
651 + return Info;
652 + } else {
653 + if (capidebug) {
654 + // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
655 + ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
656 + }
657 + }
658 +
659 + LOCAL_USER_REMOVE(u);
660 + return res;
661 +}
662 +
663 +int unload_module(void)
664 +{
665 + STANDARD_HANGUP_LOCALUSERS;
666 + return ast_unregister_application(app);
667 +}
668 +
669 +int load_module(void)
670 +{
671 + return ast_register_application(app, capiCD_exec,synopsis,tdesc);
672 +}
673 +
674 +char *description(void)
675 +{
676 + return tdesc;
677 +}
678 +
679 +int usecount(void)
680 +{
681 + int res;
682 + STANDARD_USECOUNT(res);
683 + return res;
684 +}
685 +
686 +char *key()
687 +{
688 + return ASTERISK_GPL_KEY;
689 +}
690 diff -urN asterisk-1.2.10.orig/apps/app_capiECT.c asterisk-1.2.10/apps/app_capiECT.c
691 --- asterisk-1.2.10.orig/apps/app_capiECT.c 1970-01-01 01:00:00.000000000 +0100
692 +++ asterisk-1.2.10/apps/app_capiECT.c 2006-07-31 14:13:08.000000000 +0200
693 @@ -0,0 +1,210 @@
694 +/*
695 + * (CAPI*)
696 + *
697 + * An implementation of Common ISDN API 2.0 for Asterisk
698 + *
699 + * ECT transfer the held call
700 + *
701 + * Copyright (C) 2002,2003,2004,2005 Junghanns.NET GmbH
702 + *
703 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
704 + *
705 + * This program is free software and may be modified and
706 + * distributed under the terms of the GNU Public License.
707 + */
708 +
709 +#include <stdlib.h>
710 +#include <unistd.h>
711 +#include <string.h>
712 +#include <stdio.h>
713 +#include <linux/capi.h>
714 +#include <capi20.h>
715 +#include <asterisk/file.h>
716 +#include <asterisk/logger.h>
717 +#include <asterisk/channel.h>
718 +#include <asterisk/pbx.h>
719 +#include <asterisk/module.h>
720 +#include <asterisk/say.h>
721 +#include <asterisk/chan_capi.h>
722 +#include <asterisk/chan_capi_app.h>
723 +
724 +
725 +static char *tdesc = "(CAPI*) ECT";
726 +static char *app = "capiECT";
727 +static char *synopsis = "transfer the call that is on hold";
728 +
729 +STANDARD_LOCAL_USER;
730 +
731 +LOCAL_USER_DECL;
732 +
733 +
734 +static int capiECT_exec(struct ast_channel *chan, void *data)
735 +{
736 + struct ast_capi_pvt *i = chan->tech_pvt;
737 + MESSAGE_EXCHANGE_ERROR Info;
738 + _cmsg CMSG;
739 + unsigned char fac[8];
740 + int res=0;
741 + struct localuser *u;
742 + char *ecodes = "*#";
743 +
744 + if (!data) {
745 + ast_log(LOG_WARNING, "ECT requires an argument (destination phone number)\n");
746 + return -1;
747 + }
748 + LOCAL_USER_ADD(u);
749 + /* Do our thing here */
750 + if (i->onholdPLCI <= 0) {
751 + ast_log(LOG_WARNING, "no call on hold that could be transfered\n");
752 + return -1;
753 + }
754 +
755 + ast_log(LOG_NOTICE,"ECT to %s\n",(char *)data);
756 + capi_call(chan,data,0);
757 +
758 + while ((i->state != CAPI_STATE_BCONNECTED) && (i->onholdPLCI != 0)) {
759 + usleep(10000);
760 + }
761 +
762 +
763 + if (i->state == CAPI_STATE_BCONNECTED) {
764 + ast_log(LOG_NOTICE,"call was answered\n");
765 +
766 + capi_detect_dtmf(chan,1);
767 +
768 + // put the stuff to play announcement message here ---> <-----
769 + res = ast_say_digit_str(chan,i->cid,ecodes,chan->language);
770 + if ( res == '#') {
771 + ast_log(LOG_NOTICE,"res = %d\n",res);
772 + // user pressed #, hangup
773 + // first the holded user
774 +// ast_exec("capiRETRIEVE",chan);
775 +
776 + DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
777 + DISCONNECT_REQ_PLCI(&CMSG) = i->onholdPLCI;
778 +
779 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
780 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
781 + } else {
782 + ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->onholdPLCI);
783 + }
784 +
785 + // then the destination
786 +
787 + DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
788 + DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
789 +
790 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
791 + ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
792 + } else {
793 + ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
794 + }
795 +
796 + // wait for the B3 layer to go down
797 + while (i->state != CAPI_STATE_CONNECTED) {
798 + usleep(10000);
799 + }
800 +
801 + DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
802 + DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
803 +
804 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
805 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
806 + } else {
807 + ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
808 + }
809 +
810 +
811 + LOCAL_USER_REMOVE(u);
812 + return -1;
813 +
814 + } else {
815 + // now drop the bchannel
816 + DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
817 + DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
818 +
819 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
820 + ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
821 + } else {
822 + ast_log(LOG_NOTICE, "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
823 + }
824 +
825 + // wait for the B3 layer to go down
826 + while (i->state != CAPI_STATE_CONNECTED) {
827 + usleep(10000);
828 + }
829 + }
830 + }
831 +
832 + // the caller onhold hungup or died away, drop the answered call
833 + if (i->onholdPLCI == 0) {
834 + DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
835 + DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
836 +
837 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
838 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
839 + } else {
840 + ast_log(LOG_NOTICE, "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
841 + }
842 + return -1;
843 + }
844 +
845 + ast_log(LOG_NOTICE,"onholdPLCI = %d\n",i->onholdPLCI);
846 +
847 +
848 + fac[0] = 7; // len
849 + fac[1] = 0x06; // ECT (function)
850 + fac[2] = 0x00;
851 + fac[3] = 4; //len //sservice specific parameter , cstruct
852 + fac[4] = (i->onholdPLCI << 8 ) >> 8;
853 + fac[5] = i->onholdPLCI >> 8;
854 + fac[6] = 0;
855 + fac[7] = 0;
856 +
857 + FACILITY_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
858 + FACILITY_REQ_CONTROLLER(&CMSG) = i->controller;
859 + FACILITY_REQ_PLCI(&CMSG) = i->onholdPLCI;
860 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
861 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
862 +
863 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
864 + ast_log(LOG_ERROR,"Error sending FACILITY_REQ\n");
865 + return Info;
866 + } else {
867 + ast_log(LOG_NOTICE,"sent FACILITY_REQ PLCI = %#x (%#x %#x) onholdPLCI = %#x\n ",i->PLCI,fac[4],fac[5],i->onholdPLCI);
868 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
869 + }
870 +
871 +// i->outgoing = -1; // incoming + outgoing, this is a magic channel :)
872 +
873 + LOCAL_USER_REMOVE(u);
874 + return res;
875 +}
876 +
877 +int unload_module(void)
878 +{
879 + STANDARD_HANGUP_LOCALUSERS;
880 + return ast_unregister_application(app);
881 +}
882 +
883 +int load_module(void)
884 +{
885 + return ast_register_application(app, capiECT_exec,synopsis,tdesc);
886 +}
887 +
888 +char *description(void)
889 +{
890 + return tdesc;
891 +}
892 +
893 +int usecount(void)
894 +{
895 + int res;
896 + STANDARD_USECOUNT(res);
897 + return res;
898 +}
899 +
900 +char *key()
901 +{
902 + return ASTERISK_GPL_KEY;
903 +}
904 diff -urN asterisk-1.2.10.orig/apps/app_capiNoES.c asterisk-1.2.10/apps/app_capiNoES.c
905 --- asterisk-1.2.10.orig/apps/app_capiNoES.c 1970-01-01 01:00:00.000000000 +0100
906 +++ asterisk-1.2.10/apps/app_capiNoES.c 2006-07-31 14:13:08.000000000 +0200
907 @@ -0,0 +1,96 @@
908 +/*
909 + * (CAPI*)
910 + *
911 + * An implementation of Common ISDN API 2.0 for Asterisk
912 + *
913 + * Disable echo suppression (useful for fax and voicemail!)
914 + *
915 + * Copyright (C) 2004,2005 Junghanns.NET GmbH
916 + *
917 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
918 + *
919 + * This program is free software and may be modified and
920 + * distributed under the terms of the GNU Public License.
921 + */
922 +
923 +#include <stdlib.h>
924 +#include <unistd.h>
925 +#include <string.h>
926 +#include <stdio.h>
927 +#include <linux/capi.h>
928 +#include <capi20.h>
929 +
930 +#include <asterisk/file.h>
931 +#include <asterisk/logger.h>
932 +#include <asterisk/channel.h>
933 +#include <asterisk/pbx.h>
934 +#include <asterisk/module.h>
935 +#include <asterisk/chan_capi_app.h>
936 +
937 +
938 +
939 +#ifdef CAPI_ES
940 +static char *tdesc = "(CAPI*) No Echo Suppression.";
941 +static char *app = "capiNoES";
942 +static char *synopsis = "Disable Echo Suppression";
943 +#else
944 +static char *tdesc = "(CAPI*) No Echo Suppression at all!";
945 +static char *app = "capiNoES";
946 +static char *synopsis = "Bogus Application";
947 +#endif
948 +STANDARD_LOCAL_USER;
949 +
950 +LOCAL_USER_DECL;
951 +
952 +static int capiNoES_exec(struct ast_channel *chan, void *data)
953 +{
954 + int res=0;
955 + struct localuser *u;
956 + LOCAL_USER_ADD(u);
957 +
958 +#ifdef CAPI_ES
959 + if (strcasecmp("CAPI",chan->type) == 0) {
960 +#ifdef CVS_HEAD
961 + struct ast_capi_pvt *i = chan->tech_pvt;
962 +#else
963 + struct ast_capi_pvt *i = chan->pvt->pvt;
964 +#endif
965 + if (i->doES == 1) {
966 + i->doES = 0;
967 + }
968 + } else {
969 + ast_log(LOG_WARNING, "capiNoES only works on CAPI channels, check your extensions.conf!\n");
970 + }
971 +#endif
972 +
973 + LOCAL_USER_REMOVE(u);
974 + return res;
975 +}
976 +
977 +int unload_module(void)
978 +{
979 + STANDARD_HANGUP_LOCALUSERS;
980 + return ast_unregister_application(app);
981 +}
982 +
983 +int load_module(void)
984 +{
985 + return ast_register_application(app, capiNoES_exec,synopsis,tdesc);
986 +}
987 +
988 +char *description(void)
989 +{
990 + return tdesc;
991 +}
992 +
993 +int usecount(void)
994 +{
995 + int res;
996 + STANDARD_USECOUNT(res);
997 + return res;
998 +}
999 +
1000 +char *key()
1001 +{
1002 + return ASTERISK_GPL_KEY;
1003 +}
1004 diff -urN asterisk-1.2.10.orig/apps/app_chanisavail.c asterisk-1.2.10/apps/app_chanisavail.c
1005 --- asterisk-1.2.10.orig/apps/app_chanisavail.c 2005-11-29 19:24:39.000000000 +0100
1006 +++ asterisk-1.2.10/apps/app_chanisavail.c 2006-07-31 14:13:08.000000000 +0200
1007 @@ -118,7 +118,7 @@
1008 snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
1009 status = inuse = ast_device_state(trychan);
1010 }
1011 - if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
1012 + if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status, NULL))) {
1013 pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
1014 /* Store the originally used channel too */
1015 snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
1016 diff -urN asterisk-1.2.10.orig/apps/app_chanspy.c asterisk-1.2.10/apps/app_chanspy.c
1017 --- asterisk-1.2.10.orig/apps/app_chanspy.c 2006-06-14 16:07:53.000000000 +0200
1018 +++ asterisk-1.2.10/apps/app_chanspy.c 2006-07-31 14:13:08.000000000 +0200
1019 @@ -55,6 +55,7 @@
1020
1021 static const char *synopsis = "Listen to the audio of an active channel\n";
1022 static const char *app = "ChanSpy";
1023 +static const char *app2 = "ChanSpyChan";
1024 static const char *desc =
1025 " ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
1026 "audio from an active Asterisk channel. This includes the audio coming in and\n"
1027 @@ -142,6 +143,19 @@
1028 return ret;
1029 }
1030
1031 +static struct ast_channel *local_get_channel_uniqueid(char *uniqueid)
1032 +{
1033 + struct ast_channel *chan = NULL;
1034 + if (uniqueid) {
1035 + ast_mutex_lock(&modlock);
1036 + if ((chan = ast_get_channel_by_uniqueid_locked(uniqueid))) {
1037 + ast_mutex_unlock(&chan->lock);
1038 + }
1039 + ast_mutex_unlock(&modlock);
1040 + }
1041 + return chan;
1042 +}
1043 +
1044 static void *spy_alloc(struct ast_channel *chan, void *data)
1045 {
1046 /* just store the data pointer in the channel structure */
1047 @@ -554,11 +568,87 @@
1048 ALL_DONE(u, res);
1049 }
1050
1051 +static int chanspychan_exec(struct ast_channel *chan, void *data)
1052 +{
1053 + struct localuser *u;
1054 + struct ast_channel *peer=NULL;
1055 + char *args,
1056 + *uniqueid = NULL,
1057 + *argv[5];
1058 + int res = -1,
1059 + volfactor = 0,
1060 + argc = 0,
1061 + oldrf = 0,
1062 + oldwf = 0,
1063 + fd = 0;
1064 + signed char zero_volume = 0;
1065 +
1066 + if (!(args = ast_strdupa((char *)data))) {
1067 + ast_log(LOG_ERROR, "Out of memory!\n");
1068 + return -1;
1069 + }
1070 +
1071 + LOCAL_USER_ADD(u);
1072 +
1073 + oldrf = chan->readformat;
1074 + oldwf = chan->writeformat;
1075 + if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
1076 + ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
1077 + LOCAL_USER_REMOVE(u);
1078 + return -1;
1079 + }
1080 +
1081 + if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
1082 + ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1083 + LOCAL_USER_REMOVE(u);
1084 + return -1;
1085 + }
1086 +
1087 +
1088 + if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
1089 + uniqueid = argv[0];
1090 + if (ast_strlen_zero(uniqueid)) {
1091 + LOCAL_USER_REMOVE(u);
1092 + return -1;
1093 + }
1094 + }
1095 +
1096 + ast_answer(chan);
1097 +
1098 + ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
1099 +
1100 + peer = local_get_channel_uniqueid(uniqueid);
1101 + if (peer && (peer != chan) && !ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
1102 + res = channel_spy(chan, peer, &volfactor, fd);
1103 + } else {
1104 + ast_log(LOG_NOTICE, "no channel found with uniqueid %s\n", uniqueid);
1105 + }
1106 +
1107 + if (fd > 0) {
1108 + close(fd);
1109 + }
1110 +
1111 + if (oldrf && ast_set_read_format(chan, oldrf) < 0) {
1112 + ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
1113 + }
1114 +
1115 + if (oldwf && ast_set_write_format(chan, oldwf) < 0) {
1116 + ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1117 + }
1118 +
1119 + ast_clear_flag(chan, AST_FLAG_SPYING);
1120 +
1121 + ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
1122 +
1123 + ALL_DONE(u, res);
1124 +}
1125 +
1126 int unload_module(void)
1127 {
1128 int res;
1129
1130 - res = ast_unregister_application(app);
1131 + ast_unregister_application(app);
1132 + res = ast_unregister_application(app2);
1133
1134 STANDARD_HANGUP_LOCALUSERS;
1135
1136 @@ -567,7 +657,8 @@
1137
1138 int load_module(void)
1139 {
1140 - return ast_register_application(app, chanspy_exec, synopsis, desc);
1141 + ast_register_application(app, chanspy_exec, synopsis, desc);
1142 + return ast_register_application(app2, chanspychan_exec, synopsis, desc);
1143 }
1144
1145 char *description(void)
1146 diff -urN asterisk-1.2.10.orig/apps/app_devstate.c asterisk-1.2.10/apps/app_devstate.c
1147 --- asterisk-1.2.10.orig/apps/app_devstate.c 1970-01-01 01:00:00.000000000 +0100
1148 +++ asterisk-1.2.10/apps/app_devstate.c 2006-07-31 14:13:08.000000000 +0200
1149 @@ -0,0 +1,225 @@
1150 +/*
1151 + * Devstate application
1152 + *
1153 + * Since we like the snom leds so much, a little app to
1154 + * light the lights on the snom on demand ....
1155 + *
1156 + * Copyright (C) 2005, Druid Software
1157 + *
1158 + * This program is free software, distributed under the terms of
1159 + * the GNU General Public License
1160 + */
1161 +
1162 +#include <stdlib.h>
1163 +#include <unistd.h>
1164 +#include <string.h>
1165 +#include <stdio.h>
1166 +#include <asterisk/lock.h>
1167 +#include <asterisk/file.h>
1168 +#include <asterisk/logger.h>
1169 +#include <asterisk/channel.h>
1170 +#include <asterisk/pbx.h>
1171 +#include <asterisk/module.h>
1172 +#include <asterisk/astdb.h>
1173 +#include <asterisk/utils.h>
1174 +#include <asterisk/cli.h>
1175 +#include <asterisk/manager.h>
1176 +#include <asterisk/devicestate.h>
1177 +
1178 +
1179 +static char type[] = "DS";
1180 +static char tdesc[] = "Application for sending device state messages";
1181 +
1182 +static char app[] = "Devstate";
1183 +
1184 +static char synopsis[] = "Generate a device state change event given the input parameters";
1185 +
1186 +static char descrip[] = " Devstate(device|state): Generate a device state change event given the input parameters. Returns 0. State values match the asterisk device states. They are 0 = unknown, 1 = not inuse, 2 = inuse, 3 = busy, 4 = invalid, 5 = unavailable, 6 = ringing\n";
1187 +
1188 +static char devstate_cli_usage[] =
1189 +"Usage: devstate device state\n"
1190 +" Generate a device state change event given the input parameters.\n Mainly used for lighting the LEDs on the snoms.\n";
1191 +
1192 +static int devstate_cli(int fd, int argc, char *argv[]);
1193 +static struct ast_cli_entry cli_dev_state =
1194 + { { "devstate", NULL }, devstate_cli, "Set the device state on one of the \"pseudo devices\".", devstate_cli_usage };
1195 +
1196 +STANDARD_LOCAL_USER;
1197 +
1198 +LOCAL_USER_DECL;
1199 +
1200 +
1201 +static int devstate_cli(int fd, int argc, char *argv[])
1202 +{
1203 + char devName[128];
1204 + if ((argc != 3) && (argc != 4) && (argc != 5))
1205 + return RESULT_SHOWUSAGE;
1206 +
1207 + if (ast_db_put("DEVSTATES", argv[1], argv[2]))
1208 + {
1209 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1210 + }
1211 + snprintf(devName, sizeof(devName), "DS/%s", argv[1]);
1212 + if (argc == 4) {
1213 + ast_log(LOG_NOTICE, "devname %s cid %s\n", devName, argv[3]);
1214 + ast_device_state_changed_literal(devName, argv[3], NULL);
1215 + } else if (argc == 5) {
1216 + ast_log(LOG_NOTICE, "devname %s cid %s cidname %s\n", devName, argv[3], argv[4]);
1217 + ast_device_state_changed_literal(devName, argv[3], argv[4]);
1218 + } else {
1219 + ast_device_state_changed_literal(devName, NULL, NULL);
1220 + }
1221 + return RESULT_SUCCESS;
1222 +}
1223 +
1224 +static int devstate_exec(struct ast_channel *chan, void *data)
1225 +{
1226 + struct localuser *u;
1227 + char *device, *state, *info;
1228 + char devName[128];
1229 + if (!(info = ast_strdupa(data))) {
1230 + ast_log(LOG_WARNING, "Unable to dupe data :(\n");
1231 + return -1;
1232 + }
1233 + LOCAL_USER_ADD(u);
1234 +
1235 + device = info;
1236 + state = strchr(info, '|');
1237 + if (state) {
1238 + *state = '\0';
1239 + state++;
1240 + }
1241 + else
1242 + {
1243 + ast_log(LOG_DEBUG, "No state argument supplied\n");
1244 + return -1;
1245 + }
1246 +
1247 + if (ast_db_put("DEVSTATES", device, state))
1248 + {
1249 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1250 + }
1251 +
1252 + snprintf(devName, sizeof(devName), "DS/%s", device);
1253 + ast_device_state_changed_literal(devName, NULL, NULL);
1254 +
1255 + LOCAL_USER_REMOVE(u);
1256 + return 0;
1257 +}
1258 +
1259 +
1260 +static int ds_devicestate(void *data)
1261 +{
1262 + char *dest = data;
1263 + char stateStr[16];
1264 + if (ast_db_get("DEVSTATES", dest, stateStr, sizeof(stateStr)))
1265 + {
1266 + ast_log(LOG_DEBUG, "ds_devicestate couldnt get state in astdb\n");
1267 + return 0;
1268 + }
1269 + else
1270 + {
1271 + ast_log(LOG_DEBUG, "ds_devicestate dev=%s returning state %d\n",
1272 + dest, atoi(stateStr));
1273 + return (atoi(stateStr));
1274 + }
1275 +}
1276 +
1277 +static struct ast_channel_tech devstate_tech = {
1278 + .type = type,
1279 + .description = tdesc,
1280 + .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
1281 + .devicestate = ds_devicestate,
1282 + .requester = NULL,
1283 + .send_digit = NULL,
1284 + .send_text = NULL,
1285 + .call = NULL,
1286 + .hangup = NULL,
1287 + .answer = NULL,
1288 + .read = NULL,
1289 + .write = NULL,
1290 + .bridge = NULL,
1291 + .exception = NULL,
1292 + .indicate = NULL,
1293 + .fixup = NULL,
1294 + .setoption = NULL,
1295 +};
1296 +
1297 +static char mandescr_devstate[] =
1298 +"Description: Put a value into astdb\n"
1299 +"Variables: \n"
1300 +" Family: ...\n"
1301 +" Key: ...\n"
1302 +" Value: ...\n";
1303 +
1304 +static int action_devstate(struct mansession *s, struct message *m)
1305 +{
1306 + char *devstate = astman_get_header(m, "Devstate");
1307 + char *value = astman_get_header(m, "Value");
1308 + char *id = astman_get_header(m,"ActionID");
1309 + char *cid_num = astman_get_header(m, "CallerID");
1310 + char *cid_name = astman_get_header(m, "CallerIDName");
1311 + char devName[128];
1312 +
1313 + if (!strlen(devstate)) {
1314 + astman_send_error(s, m, "No Devstate specified");
1315 + return 0;
1316 + }
1317 + if (!strlen(value)) {
1318 + astman_send_error(s, m, "No Value specified");
1319 + return 0;
1320 + }
1321 +
1322 + if (!ast_db_put("DEVSTATES", devstate, value)) {
1323 + snprintf(devName, sizeof(devName), "DS/%s", devstate);
1324 +// ast_device_state_changed(devName);
1325 + ast_device_state_changed_literal(devName, cid_num, cid_name);
1326 + ast_cli(s->fd, "Response: Success\r\n");
1327 + } else {
1328 + ast_log(LOG_DEBUG, "ast_db_put failed\n");
1329 + ast_cli(s->fd, "Response: Failed\r\n");
1330 + }
1331 + if (id && !ast_strlen_zero(id))
1332 + ast_cli(s->fd, "ActionID: %s\r\n",id);
1333 + ast_cli(s->fd, "\r\n");
1334 + return 0;
1335 +}
1336 +
1337 +int load_module(void)
1338 +{
1339 + if (ast_channel_register(&devstate_tech)) {
1340 + ast_log(LOG_DEBUG, "Unable to register channel class %s\n", type);
1341 + return -1;
1342 + }
1343 + ast_cli_register(&cli_dev_state);
1344 + ast_manager_register2( "Devstate", EVENT_FLAG_CALL, action_devstate, "Change a device state", mandescr_devstate );
1345 + return ast_register_application(app, devstate_exec, synopsis, descrip);
1346 +}
1347 +
1348 +int unload_module(void)
1349 +{
1350 + int res = 0;
1351 + STANDARD_HANGUP_LOCALUSERS;
1352 + ast_manager_unregister( "Devstate");
1353 + ast_cli_unregister(&cli_dev_state);
1354 + res = ast_unregister_application(app);
1355 + ast_channel_unregister(&devstate_tech);
1356 + return res;
1357 +}
1358 +
1359 +char *description(void)
1360 +{
1361 + return tdesc;
1362 +}
1363 +
1364 +int usecount(void)
1365 +{
1366 + int res;
1367 + STANDARD_USECOUNT(res);
1368 + return res;
1369 +}
1370 +
1371 +char *key()
1372 +{
1373 + return ASTERISK_GPL_KEY;
1374 +}
1375 diff -urN asterisk-1.2.10.orig/apps/app_dial.c asterisk-1.2.10/apps/app_dial.c
1376 --- asterisk-1.2.10.orig/apps/app_dial.c 2006-06-09 20:08:00.000000000 +0200
1377 +++ asterisk-1.2.10/apps/app_dial.c 2006-08-04 11:23:28.000000000 +0200
1378 @@ -11,6 +11,10 @@
1379 * the project provides a web site, mailing lists and IRC
1380 * channels for your use.
1381 *
1382 + * Copyright (C) 2004, Junghanns.NET GmbH
1383 + *
1384 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1385 + *
1386 * This program is free software, distributed under the terms of
1387 * the GNU General Public License Version 2. See the LICENSE file
1388 * at the top of the source tree.
1389 @@ -55,6 +59,7 @@
1390 #include "asterisk/causes.h"
1391 #include "asterisk/manager.h"
1392 #include "asterisk/privacy.h"
1393 +#include "asterisk/transcap.h"
1394
1395 static char *tdesc = "Dialing Application";
1396
1397 @@ -115,7 +120,8 @@
1398 " action post answer options in conjunction with this option.\n"
1399 " h - Allow the called party to hang up by sending the '*' DTMF digit.\n"
1400 " H - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
1401 -" j - Jump to priority n+101 if all of the requested channels were busy.\n"
1402 +" j - Jump to priority n+101 if the called party was busy.\n"
1403 +" Jump to priority n+201 if all of the requested channels were busy.\n"
1404 " L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
1405 " left. Repeat the warning every 'z' ms. The following special\n"
1406 " variables can be used with this option:\n"
1407 @@ -162,8 +168,11 @@
1408 " family/key is not specified.\n"
1409 " r - Indicate ringing to the calling party. Pass no audio to the calling\n"
1410 " party until the called channel has answered.\n"
1411 +" R - indicate ringing to the calling party when the called party indicates\n"
1412 +" ringing, pass no audio until answered.\n"
1413 " S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
1414 -" answered the call.\n"
1415 +" answered the call.\n"
1416 +" c - callback initiation, ring once and hangup.\n"
1417 " t - Allow the called party to transfer the calling party by sending the\n"
1418 " DTMF sequence defined in features.conf.\n"
1419 " T - Allow the calling party to transfer the called party by sending the\n"
1420 @@ -214,6 +223,8 @@
1421 OPT_CALLEE_MONITOR = (1 << 21),
1422 OPT_CALLER_MONITOR = (1 << 22),
1423 OPT_GOTO = (1 << 23),
1424 + OPT_NOINBAND = (1 << 24),
1425 + OPT_CALLBACK_INIT = (1 << 25),
1426 } dial_exec_option_flags;
1427
1428 #define DIAL_STILLGOING (1 << 30)
1429 @@ -252,6 +263,8 @@
1430 AST_APP_OPTION('p', OPT_SCREENING),
1431 AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
1432 AST_APP_OPTION('r', OPT_RINGBACK),
1433 + AST_APP_OPTION('R', OPT_NOINBAND),
1434 + AST_APP_OPTION('c', OPT_CALLBACK_INIT),
1435 AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
1436 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
1437 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
1438 @@ -389,7 +402,7 @@
1439 char *context = NULL;
1440 char cidname[AST_MAX_EXTENSION];
1441
1442 - single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK));
1443 + single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK | OPT_NOINBAND));
1444
1445 if (single) {
1446 /* Turn off hold music, etc */
1447 @@ -468,7 +481,7 @@
1448 if (option_verbose > 2)
1449 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
1450 /* Setup parameters */
1451 - o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
1452 + o->chan = ast_request(tech, in->nativeformats, stuff, &cause, NULL);
1453 if (!o->chan)
1454 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1455 else
1456 @@ -586,12 +599,18 @@
1457 HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
1458 break;
1459 case AST_CONTROL_RINGING:
1460 - if (option_verbose > 2)
1461 - ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1462 - if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
1463 - ast_indicate(in, AST_CONTROL_RINGING);
1464 - (*sentringing)++;
1465 - }
1466 + if (ast_test_flag(peerflags, OPT_CALLBACK_INIT)) {
1467 + if (option_verbose > 2)
1468 + ast_verbose( VERBOSE_PREFIX_3 "%s is ringing, hanging up.\n", o->chan->name);
1469 + return NULL;
1470 + } else {
1471 + if (option_verbose > 2)
1472 + ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
1473 + if (!(*sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
1474 + ast_indicate(in, AST_CONTROL_RINGING);
1475 + (*sentringing)++;
1476 + }
1477 + }
1478 break;
1479 case AST_CONTROL_PROGRESS:
1480 if (option_verbose > 2)
1481 @@ -766,6 +785,7 @@
1482 int digit = 0, result = 0;
1483 time_t start_time, answer_time, end_time;
1484 struct ast_app *app = NULL;
1485 +/* char *aoceunits; */
1486
1487 char *parse;
1488 AST_DECLARE_APP_ARGS(args,
1489 @@ -939,13 +959,13 @@
1490 }
1491
1492 if( privdb_val == AST_PRIVACY_DENY ) {
1493 - strcpy(status, "NOANSWER");
1494 + ast_copy_string(status, "NOANSWER", sizeof(status));
1495 ast_verbose( VERBOSE_PREFIX_3 "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
1496 res=0;
1497 goto out;
1498 }
1499 else if( privdb_val == AST_PRIVACY_KILL ) {
1500 - strcpy(status, "DONTCALL");
1501 + ast_copy_string(status, "DONTCALL", sizeof(status));
1502 if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1503 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1504 }
1505 @@ -953,7 +973,7 @@
1506 goto out; /* Is this right? */
1507 }
1508 else if( privdb_val == AST_PRIVACY_TORTURE ) {
1509 - strcpy(status, "TORTURE");
1510 + ast_copy_string(status, "TORTURE", sizeof(status));
1511 if (option_priority_jumping || ast_test_flag(&opts, OPT_PRIORITY_JUMP)) {
1512 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 301);
1513 }
1514 @@ -1001,7 +1021,7 @@
1515 /* If a channel group has been specified, get it for use when we create peer channels */
1516 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
1517
1518 - ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP);
1519 + ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP| OPT_CALLBACK_INIT | OPT_NOINBAND);
1520 cur = args.peers;
1521 do {
1522 /* Remember where to start next time */
1523 @@ -1043,7 +1063,7 @@
1524 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
1525 }
1526 /* Request the peer */
1527 - tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
1528 + tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause, NULL);
1529 if (!tmp->chan) {
1530 /* If we can't, just go on to the next call */
1531 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n", tech, cause, ast_cause2str(cause));
1532 @@ -1074,7 +1094,7 @@
1533 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
1534 ast_hangup(tmp->chan);
1535 /* Setup parameters */
1536 - tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1537 + tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause, NULL);
1538 if (!tmp->chan)
1539 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1540 else
1541 @@ -1187,7 +1207,7 @@
1542
1543 if (outgoing) {
1544 /* Our status will at least be NOANSWER */
1545 - strcpy(status, "NOANSWER");
1546 + ast_copy_string(status, "NOANSWER", sizeof(status));
1547 if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
1548 moh=1;
1549 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK]);
1550 @@ -1195,8 +1215,11 @@
1551 ast_indicate(chan, AST_CONTROL_RINGING);
1552 sentringing++;
1553 }
1554 - } else
1555 - strcpy(status, "CHANUNAVAIL");
1556 + } else {
1557 + ast_copy_string(status, "CHANUNAVAIL", sizeof(status));
1558 + /* See if there is a special message */
1559 + ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 201);
1560 + }
1561
1562 time(&start_time);
1563 peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, ast_test_flag(&opts, OPT_PRIORITY_JUMP), &result);
1564 @@ -1561,18 +1584,22 @@
1565 ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
1566 if (play_to_callee)
1567 ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
1568 - if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1569 +
1570 + if ((chan->transfercapability != AST_TRANS_CAP_DIGITAL) && (chan->transfercapability != AST_TRANS_CAP_RESTRICTED_DIGITAL)) {
1571 + /* only non-digital calls are allowed to go through userspace */
1572 + if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1573 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1574 - if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1575 + if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1576 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1577 - if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1578 + if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1579 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1580 - if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1581 + if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1582 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1583 - if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1584 + if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1585 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1586 - if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
1587 + if (ast_test_flag(peerflags, OPT_CALLER_MONITOR))
1588 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1589 + }
1590
1591 config.timelimit = timelimit;
1592 config.play_warning = play_warning;
1593 @@ -1608,7 +1635,15 @@
1594 }
1595 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1596 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1597 -
1598 +
1599 + /* forward AOC-E units from peer, if possible */
1600 +/* aoceunits = pbx_builtin_getvar_helper(peer, "AOCEUNITS");
1601 +
1602 + if (aoceunits) {
1603 + snprintf(toast, sizeof(toast), "%d", atoi(aoceunits));
1604 + pbx_builtin_setvar_helper(chan, "AOCEUNITS", toast);
1605 + } */
1606 +
1607 if (res != AST_PBX_NO_HANGUP_PEER) {
1608 if (!chan->_softhangup)
1609 chan->hangupcause = peer->hangupcause;
1610 diff -urN asterisk-1.2.10.orig/apps/app_directed_pickup.c asterisk-1.2.10/apps/app_directed_pickup.c
1611 --- asterisk-1.2.10.orig/apps/app_directed_pickup.c 2006-04-06 19:00:10.000000000 +0200
1612 +++ asterisk-1.2.10/apps/app_directed_pickup.c 2006-07-31 14:13:08.000000000 +0200
1613 @@ -41,7 +41,7 @@
1614 #include "asterisk/app.h"
1615
1616 static const char *tdesc = "Directed Call Pickup Application";
1617 -static const char *app = "Pickup";
1618 +static const char *app = "DPickup";
1619 static const char *synopsis = "Directed Call Pickup";
1620 static const char *descrip =
1621 " Pickup(extension[@context]): This application can pickup any ringing channel\n"
1622 diff -urN asterisk-1.2.10.orig/apps/app_meetme.c asterisk-1.2.10/apps/app_meetme.c
1623 --- asterisk-1.2.10.orig/apps/app_meetme.c 2006-06-11 23:08:04.000000000 +0200
1624 +++ asterisk-1.2.10/apps/app_meetme.c 2006-07-31 14:13:08.000000000 +0200
1625 @@ -453,7 +453,7 @@
1626 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin));
1627 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin));
1628 cnf->markedusers = 0;
1629 - cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL);
1630 + cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL, NULL);
1631 if (cnf->chan) {
1632 cnf->fd = cnf->chan->fds[0]; /* for use by conf_play() */
1633 } else {
1634 @@ -823,8 +823,9 @@
1635 char exitcontext[AST_MAX_CONTEXT] = "";
1636 char recordingtmp[AST_MAX_EXTENSION] = "";
1637 int dtmf;
1638 + int dyna_buff = CONF_SIZE;
1639 ZT_BUFFERINFO bi;
1640 - char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
1641 + char __buf[ZT_MAX_BUF_SPACE / ZT_DEFAULT_NUM_BUFS + AST_FRIENDLY_OFFSET];
1642 char *buf = __buf + AST_FRIENDLY_OFFSET;
1643
1644 if (!user) {
1645 @@ -990,7 +991,7 @@
1646 }
1647 /* Setup buffering information */
1648 memset(&bi, 0, sizeof(bi));
1649 - bi.bufsize = CONF_SIZE/2;
1650 + bi.bufsize = dyna_buff / 2;
1651 bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
1652 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
1653 bi.numbufs = audio_buffers;
1654 @@ -1275,6 +1276,14 @@
1655 f = ast_read(c);
1656 if (!f)
1657 break;
1658 + if (f->datalen && f->datalen != dyna_buff) {
1659 + ast_log(LOG_NOTICE, "Audio bytes: %d Buffer size: %d\n", f->datalen, dyna_buff);
1660 + if (f->datalen < ZT_MAX_BUF_SPACE/audio_buffers) { /* skip too large frame to avoid overflow */
1661 + dyna_buff = f->datalen;
1662 + close(fd);
1663 + goto zapretry;
1664 + }
1665 + }
1666 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
1667 if (user->talk.actual)
1668 ast_frame_adjust_volume(f, user->talk.actual);
1669 @@ -1509,7 +1518,7 @@
1670 }
1671 ast_frfree(f);
1672 } else if (outfd > -1) {
1673 - res = read(outfd, buf, CONF_SIZE);
1674 + res = read(outfd, buf, dyna_buff);
1675 if (res > 0) {
1676 memset(&fr, 0, sizeof(fr));
1677 fr.frametype = AST_FRAME_VOICE;
1678 diff -urN asterisk-1.2.10.orig/apps/app_milliwatt.c asterisk-1.2.10/apps/app_milliwatt.c
1679 --- asterisk-1.2.10.orig/apps/app_milliwatt.c 2006-01-19 05:17:45.000000000 +0100
1680 +++ asterisk-1.2.10/apps/app_milliwatt.c 2006-07-31 14:13:08.000000000 +0200
1681 @@ -74,20 +74,28 @@
1682 {
1683 struct ast_frame wf;
1684 unsigned char buf[AST_FRIENDLY_OFFSET + 640];
1685 + const int maxsamples = (sizeof (buf) - AST_FRIENDLY_OFFSET) / sizeof (buf[0]);
1686 int i,*indexp = (int *) data;
1687
1688 - if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
1689 - {
1690 - ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
1691 - len = sizeof(buf) - AST_FRIENDLY_OFFSET;
1692 - }
1693 + /* Instead of len, use samples, because channel.c generator_force
1694 + * generate(chan, tmp, 0, 160) ignores len. In any case, len is
1695 + * a multiple of samples, given by number of samples times bytes per
1696 + * sample. In the case of ulaw, len = samples. for signed linear
1697 + * len = 2 * samples */
1698 +
1699 + if (samples > maxsamples)
1700 + {
1701 + ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
1702 + samples = maxsamples;
1703 + }
1704 + len = samples * sizeof (buf[0]);
1705 wf.frametype = AST_FRAME_VOICE;
1706 wf.subclass = AST_FORMAT_ULAW;
1707 wf.offset = AST_FRIENDLY_OFFSET;
1708 wf.mallocd = 0;
1709 wf.data = buf + AST_FRIENDLY_OFFSET;
1710 wf.datalen = len;
1711 - wf.samples = wf.datalen;
1712 + wf.samples = samples;
1713 wf.src = "app_milliwatt";
1714 wf.delivery.tv_sec = 0;
1715 wf.delivery.tv_usec = 0;
1716 diff -urN asterisk-1.2.10.orig/apps/app_page.c asterisk-1.2.10/apps/app_page.c
1717 --- asterisk-1.2.10.orig/apps/app_page.c 2006-04-13 19:40:21.000000000 +0200
1718 +++ asterisk-1.2.10/apps/app_page.c 2006-07-31 14:13:08.000000000 +0200
1719 @@ -85,7 +85,7 @@
1720 {
1721 struct calloutdata *cd = data;
1722 ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
1723 - "MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
1724 + "MeetMe", cd->meetmeopts, NULL, 0, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL, NULL);
1725 free(cd);
1726 return NULL;
1727 }
1728 diff -urN asterisk-1.2.10.orig/apps/app_parkandannounce.c asterisk-1.2.10/apps/app_parkandannounce.c
1729 --- asterisk-1.2.10.orig/apps/app_parkandannounce.c 2005-11-29 19:24:39.000000000 +0100
1730 +++ asterisk-1.2.10/apps/app_parkandannounce.c 2006-07-31 14:13:08.000000000 +0200
1731 @@ -183,7 +183,7 @@
1732
1733 memset(&oh, 0, sizeof(oh));
1734 oh.parent_channel = chan;
1735 - dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
1736 + dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, 0, chan->cid.cid_num, chan->cid.cid_name, &oh, NULL);
1737
1738 if(dchan) {
1739 if(dchan->_state == AST_STATE_UP) {
1740 diff -urN asterisk-1.2.10.orig/apps/app_pickup.c asterisk-1.2.10/apps/app_pickup.c
1741 --- asterisk-1.2.10.orig/apps/app_pickup.c 1970-01-01 01:00:00.000000000 +0100
1742 +++ asterisk-1.2.10/apps/app_pickup.c 2006-07-31 14:13:08.000000000 +0200
1743 @@ -0,0 +1,319 @@
1744 +/*
1745 + * Asterisk -- A telephony toolkit for Linux.
1746 + *
1747 + * Pickup, channel independent call pickup
1748 + *
1749 + * Copyright (C) 2004, Junghanns.NET GmbH
1750 + *
1751 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1752 + *
1753 + * Copyright (C) 2004, Florian Overkamp <florian@obsimref.com>
1754 + *
1755 + * This program is free software, distributed under the terms of
1756 + * the GNU General Public License
1757 + */
1758 +
1759 +#include <stdlib.h>
1760 +#include <unistd.h>
1761 +#include <string.h>
1762 +#include <stdio.h>
1763 +#include <signal.h>
1764 +#include <pthread.h>
1765 +#include <asterisk/lock.h>
1766 +#include <asterisk/file.h>
1767 +#include <asterisk/logger.h>
1768 +#include <asterisk/channel.h>
1769 +#include <asterisk/pbx.h>
1770 +#include <asterisk/module.h>
1771 +#include <asterisk/features.h>
1772 +#include <asterisk/options.h>
1773 +
1774 +
1775 +static char *tdesc = "PickUp/PickDown/Steal/PickupChan/StealChan";
1776 +
1777 +static char *app = "PickUp";
1778 +
1779 +static char *synopsis = "Channel independent call pickup.";
1780 +
1781 +static char *descrip =
1782 +" PickDown([group]): Tries to pickup the first ringing channel with callgroup == group.\n"
1783 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
1784 +
1785 +static char *app2 = "Steal";
1786 +
1787 +static char *synopsis2 = "Channel independent call stealing. Just like pickup but for answered channels.";
1788 +
1789 +static char *descrip2 =
1790 +" Steal([group]): Tries to steal the first bridged channel with callgroup == group.\n"
1791 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
1792 +
1793 +static char *app3 = "PickDown";
1794 +
1795 +static char *synopsis3 = "Channel independent call pickdown.";
1796 +
1797 +static char *descrip3 =
1798 +" PickDown([group]): Tries to hangup the first ringing channel with callgroup == group.\n"
1799 +" If called without the group argument, the pickupgroup of the channel will be used.\n";
1800 +
1801 +static char *app4 = "PickupChan";
1802 +
1803 +static char *synopsis4 = "Channel independent call pickup.";
1804 +
1805 +static char *descrip4 =
1806 +" PickupChan(Technology/resource[&Technology2/resource2...]): Tries to pickup the first ringing channel in the parameter list.\n";
1807 +
1808 +static char *app5 = "StealChan";
1809 +
1810 +static char *synopsis5 = "Channel independent call stealing. Just like pickup but for answered channels.";
1811 +
1812 +static char *descrip5 =
1813 +" StealChan(Technology/resource[&Technology2/resource2...]): Tries to steal the first ringing channel in the parameter list.\n";
1814 +
1815 +STANDARD_LOCAL_USER;
1816 +
1817 +LOCAL_USER_DECL;
1818 +
1819 +static int my_pickup_call(struct ast_channel *chan, unsigned int pickupgroup, int chanstate, int bridge) {
1820 + struct ast_channel *cur;
1821 + int res = -1;
1822 + cur = ast_channel_walk_locked(NULL);
1823 + while(cur) {
1824 + if ((cur != chan) &&
1825 + (pickupgroup & cur->callgroup) &&
1826 + (cur->_state == chanstate)) {
1827 + break;
1828 + }
1829 + ast_mutex_unlock(&cur->lock);
1830 + cur = ast_channel_walk_locked(cur);
1831 + }
1832 + if (cur) {
1833 + if(option_verbose > 2) {
1834 + if (chanstate == AST_STATE_RINGING) {
1835 + if (bridge == 1) {
1836 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
1837 + } else {
1838 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
1839 + }
1840 + } else {
1841 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
1842 + }
1843 + }
1844 + if (bridge == 1) {
1845 + if (chan->_state != AST_STATE_UP) {
1846 + ast_answer(chan);
1847 + }
1848 + if (ast_channel_masquerade(cur, chan)) {
1849 + ast_log(LOG_ERROR, "unable to masquerade\n");
1850 + }
1851 + ast_mutex_unlock(&cur->lock);
1852 + ast_mutex_unlock(&chan->lock);
1853 + } else {
1854 + cur->_softhangup = AST_SOFTHANGUP_DEV;
1855 + ast_mutex_unlock(&cur->lock);
1856 + }
1857 + } else {
1858 + if(option_verbose > 2) {
1859 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %d.\n",pickupgroup);
1860 + }
1861 + }
1862 + return res;
1863 +}
1864 +
1865 +static int my_pickup_channel(struct ast_channel *chan, void *data, int chanstate, int bridge) {
1866 + struct ast_channel *cur;
1867 + char channels[256];
1868 + char evalchan[256];
1869 + char *endptr;
1870 + int res = -1;
1871 + cur = ast_channel_walk_locked(NULL);
1872 + strncpy(channels, (char *)data, sizeof(channels) - 1);
1873 + while(cur) {
1874 + if ((cur != chan) &&
1875 + (cur->_state == chanstate)) {
1876 + /* This call is a candidate (correct ringstate and not ourselves), now check if the channel is in our list */
1877 + strncpy(evalchan, (char *)cur->name, sizeof(evalchan) - 1);
1878 + /* strip the subchannel tag */
1879 + endptr = strrchr(evalchan, '-');
1880 + if(endptr) {
1881 + *endptr = '\0';
1882 + }
1883 + endptr = strrchr(evalchan, '/');
1884 + if(endptr) {
1885 + *endptr = '\0';
1886 + }
1887 + /* check for each of the members if they match (probably a stristr will do ?) */
1888 + /* if we match the code, break */
1889 + if(strstr(channels, evalchan) != NULL) {
1890 + ast_verbose(VERBOSE_PREFIX_1 "Nice channel, I'll take it: %s\n",evalchan);
1891 + break;
1892 + }
1893 + }
1894 + ast_mutex_unlock(&cur->lock);
1895 + cur = ast_channel_walk_locked(cur);
1896 + }
1897 + if (cur) {
1898 + if(option_verbose > 2) {
1899 + if (chanstate == AST_STATE_RINGING) {
1900 + if (bridge == 1) {
1901 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s picked up ringing channel %s\n",chan->name,cur->name);
1902 + } else {
1903 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n",chan->name,cur->name);
1904 + }
1905 + } else {
1906 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s stole channel %s\n",chan->name,cur->name);
1907 + }
1908 + }
1909 + if (bridge == 1) {
1910 + if (chan->_state != AST_STATE_UP) {
1911 + ast_answer(chan);
1912 + }
1913 + if (ast_channel_masquerade(cur, chan)) {
1914 + ast_log(LOG_ERROR, "unable to masquerade\n");
1915 + }
1916 + ast_mutex_unlock(&cur->lock);
1917 + ast_mutex_unlock(&chan->lock);
1918 + } else {
1919 + cur->_softhangup = AST_SOFTHANGUP_DEV;
1920 + ast_mutex_unlock(&cur->lock);
1921 + }
1922 + } else {
1923 + if(option_verbose > 2) {
1924 + ast_verbose(VERBOSE_PREFIX_3 "No channel found %s.\n",channels);
1925 + }
1926 + }
1927 + return res;
1928 +}
1929 +
1930 +
1931 +static int pickup_exec(struct ast_channel *chan, void *data)
1932 +{
1933 + int res=0;
1934 + unsigned int pickupgroup=0;
1935 + struct localuser *u;
1936 + if (!data || !strlen(data)) {
1937 + pickupgroup = chan->pickupgroup;
1938 + } else {
1939 + pickupgroup = ast_get_group(data);
1940 + }
1941 + LOCAL_USER_ADD(u);
1942 + if (!res) {
1943 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 1);
1944 + }
1945 + if (res > 0)
1946 + res = 0;
1947 + LOCAL_USER_REMOVE(u);
1948 + return res;
1949 +}
1950 +
1951 +static int steal_exec(struct ast_channel *chan, void *data)
1952 +{
1953 + int res=0;
1954 + unsigned int pickupgroup=0;
1955 + struct localuser *u;
1956 + if (!data || !strlen(data)) {
1957 + pickupgroup = chan->pickupgroup;
1958 + } else {
1959 + pickupgroup = ast_get_group(data);
1960 + }
1961 + LOCAL_USER_ADD(u);
1962 + if (!res) {
1963 + res = my_pickup_call(chan, pickupgroup, AST_STATE_UP, 1);
1964 + }
1965 + if (res > 0)
1966 + res = 0;
1967 + LOCAL_USER_REMOVE(u);
1968 + return res;
1969 +}
1970 +
1971 +static int pickdown_exec(struct ast_channel *chan, void *data)
1972 +{
1973 + int res=0;
1974 + unsigned int pickupgroup=0;
1975 + struct localuser *u;
1976 + if (!data || !strlen(data)) {
1977 + pickupgroup = chan->pickupgroup;
1978 + } else {
1979 + pickupgroup = ast_get_group(data);
1980 + }
1981 + LOCAL_USER_ADD(u);
1982 + if (!res) {
1983 + res = my_pickup_call(chan, pickupgroup, AST_STATE_RINGING, 0);
1984 + }
1985 + if (res > 0)
1986 + res = 0;
1987 + LOCAL_USER_REMOVE(u);
1988 + return res;
1989 +}
1990 +
1991 +static int pickupchan_exec(struct ast_channel *chan, void *data) {
1992 + int res=0;
1993 + struct localuser *u;
1994 + if (!data) {
1995 + ast_log(LOG_WARNING, "PickupChan requires an argument (technology1/number1&technology2/number2...)\n");
1996 + return -1;
1997 + }
1998 + LOCAL_USER_ADD(u);
1999 + if (!res) {
2000 + res = my_pickup_channel(chan, data, AST_STATE_RINGING, 1);
2001 + }
2002 + if (res > 0)
2003 + res = 0;
2004 + LOCAL_USER_REMOVE(u);
2005 + return res;
2006 +}
2007 +
2008 +static int stealchan_exec(struct ast_channel *chan, void *data)
2009 +{
2010 + int res=0;
2011 + struct localuser *u;
2012 + if (!data) {
2013 + ast_log(LOG_WARNING, "StealChan requires an argument (technology1/number1&technology2/number2...)\n");
2014 + return -1;
2015 + }
2016 +
2017 + LOCAL_USER_ADD(u);
2018 + if (!res) {
2019 + res = my_pickup_channel(chan, data, AST_STATE_UP, 1);
2020 + }
2021 + if (res > 0)
2022 + res = 0;
2023 + LOCAL_USER_REMOVE(u);
2024 + return res;
2025 +}
2026 +
2027 +
2028 +int unload_module(void)
2029 +{
2030 + STANDARD_HANGUP_LOCALUSERS;
2031 + ast_unregister_application(app5);
2032 + ast_unregister_application(app4);
2033 + ast_unregister_application(app3);
2034 + ast_unregister_application(app2);
2035 + return ast_unregister_application(app);
2036 +}
2037 +
2038 +int load_module(void)
2039 +{
2040 + ast_register_application(app5, stealchan_exec, synopsis5, descrip5);
2041 + ast_register_application(app4, pickupchan_exec, synopsis4, descrip4);
2042 + ast_register_application(app3, pickdown_exec, synopsis3, descrip3);
2043 + ast_register_application(app2, steal_exec, synopsis2, descrip2);
2044 + return ast_register_application(app, pickup_exec, synopsis, descrip);
2045 +}
2046 +
2047 +char *description(void)
2048 +{
2049 + return tdesc;
2050 +}
2051 +
2052 +int usecount(void)
2053 +{
2054 + int res;
2055 + STANDARD_USECOUNT(res);
2056 + return res;
2057 +}
2058 +
2059 +char *key()
2060 +{
2061 + return ASTERISK_GPL_KEY;
2062 +}
2063 diff -urN asterisk-1.2.10.orig/apps/app_queue.c asterisk-1.2.10/apps/app_queue.c
2064 --- asterisk-1.2.10.orig/apps/app_queue.c 2006-06-23 13:30:17.000000000 +0200
2065 +++ asterisk-1.2.10/apps/app_queue.c 2006-07-31 14:13:08.000000000 +0200
2066 @@ -526,7 +526,7 @@
2067 return NULL;
2068 }
2069
2070 -static int statechange_queue(const char *dev, int state, void *ign)
2071 +static int statechange_queue(const char *dev, int state, void *ign, char *cid_num, char *cid_name)
2072 {
2073 /* Avoid potential for deadlocks by spawning a new thread to handle
2074 the event */
2075 @@ -1509,7 +1509,7 @@
2076 location = "";
2077
2078 /* Request the peer */
2079 - tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
2080 + tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status, NULL);
2081 if (!tmp->chan) { /* If we can't, just go on to the next call */
2082 #if 0
2083 ast_log(LOG_NOTICE, "Unable to create channel of type '%s' for Queue\n", cur->tech);
2084 @@ -1816,7 +1816,7 @@
2085 if (option_verbose > 2)
2086 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
2087 /* Setup parameters */
2088 - o->chan = ast_request(tech, in->nativeformats, stuff, &status);
2089 + o->chan = ast_request(tech, in->nativeformats, stuff, &status, NULL);
2090 if (status != o->oldstatus)
2091 update_dial_status(qe->parent, o->member, status);
2092 if (!o->chan) {
2093 @@ -2360,14 +2360,14 @@
2094 else
2095 which = peer;
2096 if (monitorfilename)
2097 - ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1 );
2098 + ast_monitor_start(which, qe->parent->monfmt, monitorfilename, NULL, NULL, 1 );
2099 else if (qe->chan->cdr)
2100 - ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 );
2101 + ast_monitor_start(which, qe->parent->monfmt, qe->chan->cdr->uniqueid, NULL, NULL, 1 );
2102 else {
2103 /* Last ditch effort -- no CDR, make up something */
2104 char tmpid[256];
2105 snprintf(tmpid, sizeof(tmpid), "chan-%x", rand());
2106 - ast_monitor_start(which, qe->parent->monfmt, tmpid, 1 );
2107 + ast_monitor_start(which, qe->parent->monfmt, tmpid, NULL, NULL, 1 );
2108 }
2109 if (qe->parent->monjoin)
2110 ast_monitor_setjoinfiles(which, 1);
2111 diff -urN asterisk-1.2.10.orig/apps/app_readfile.c asterisk-1.2.10/apps/app_readfile.c
2112 --- asterisk-1.2.10.orig/apps/app_readfile.c 2006-03-23 21:13:48.000000000 +0100
2113 +++ asterisk-1.2.10/apps/app_readfile.c 2006-07-31 14:13:08.000000000 +0200
2114 @@ -40,7 +40,7 @@
2115 #include "asterisk/app.h"
2116 #include "asterisk/module.h"
2117
2118 -static char *tdesc = "Stores output of file into a variable";
2119 +static char *tdesc = "Stores content of file into a variable";
2120
2121 static char *app_readfile = "ReadFile";
2122
2123 diff -urN asterisk-1.2.10.orig/apps/app_segfault.c asterisk-1.2.10/apps/app_segfault.c
2124 --- asterisk-1.2.10.orig/apps/app_segfault.c 1970-01-01 01:00:00.000000000 +0100
2125 +++ asterisk-1.2.10/apps/app_segfault.c 2006-07-31 14:13:08.000000000 +0200
2126 @@ -0,0 +1,75 @@
2127 +/*
2128 + * Segfault application
2129 + *
2130 + * An application to provoke a segmentation fault from the dialplan.
2131 + * (I know what you are thinking now...., but since Asterisk is too stable...
2132 + * I needed something to test my failover switches.)
2133 + *
2134 + * Copyright (C) 2005 Junghanns.NET GmbH
2135 + * Klaus-Peter Junghanns <kpj@junghanns.net>
2136 + *
2137 + * This program is free software, distributed under the terms of
2138 + * the GNU General Public License. THIS APPLICATION _WILL_ CRASH YOUR
2139 + * ASTERISK SERVER SO OF COURSE THERE IS NOT LIABILITY FOR NOTHING!
2140 + */
2141 +
2142 +#include <stdlib.h>
2143 +#include <unistd.h>
2144 +#include <string.h>
2145 +#include <stdio.h>
2146 +#include <asterisk/lock.h>
2147 +#include <asterisk/file.h>
2148 +#include <asterisk/logger.h>
2149 +#include <asterisk/channel.h>
2150 +#include <asterisk/pbx.h>
2151 +#include <asterisk/module.h>
2152 +
2153 +static char *tdesc = "Application for crashing Asterisk with a segmentation fault";
2154 +
2155 +static char *app = "Segfault";
2156 +
2157 +static char *synopsis = "This application will crash Asterisk with a segmentation fault.";
2158 +
2159 +static char *descrip =
2160 +" Segfault(): Crash with a segfault. Never returns nufin.\n";
2161 +
2162 +STANDARD_LOCAL_USER;
2163 +
2164 +LOCAL_USER_DECL;
2165 +
2166 +static int segfault_exec(struct ast_channel *chan, void *data)
2167 +{
2168 + struct localuser *u;
2169 + LOCAL_USER_ADD(u);
2170 + ((char *)0)[0] = 0;
2171 + LOCAL_USER_REMOVE(u);
2172 + return 0;
2173 +}
2174 +
2175 +int unload_module(void)
2176 +{
2177 + STANDARD_HANGUP_LOCALUSERS;
2178 + return ast_unregister_application(app);
2179 +}
2180 +
2181 +int load_module(void)
2182 +{
2183 + return ast_register_application(app, segfault_exec, synopsis, descrip);
2184 +}
2185 +
2186 +char *description(void)
2187 +{
2188 + return tdesc;
2189 +}
2190 +
2191 +int usecount(void)
2192 +{
2193 + int res;
2194 + STANDARD_USECOUNT(res);
2195 + return res;
2196 +}
2197 +
2198 +char *key()
2199 +{
2200 + return ASTERISK_GPL_KEY;
2201 +}
2202 diff -urN asterisk-1.2.10.orig/apps/app_zapras.c asterisk-1.2.10/apps/app_zapras.c
2203 --- asterisk-1.2.10.orig/apps/app_zapras.c 2006-07-12 15:54:10.000000000 +0200
2204 +++ asterisk-1.2.10/apps/app_zapras.c 2006-07-31 14:13:08.000000000 +0200
2205 @@ -180,7 +180,7 @@
2206 }
2207 }
2208 /* Throw back into audio mode */
2209 - x = 1;
2210 + x = 0;
2211 ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
2212
2213 /* Restore saved values */
2214 diff -urN asterisk-1.2.10.orig/apps/app_zapras.c.orig asterisk-1.2.10/apps/app_zapras.c.orig
2215 --- asterisk-1.2.10.orig/apps/app_zapras.c.orig 1970-01-01 01:00:00.000000000 +0100
2216 +++ asterisk-1.2.10/apps/app_zapras.c.orig 2006-07-12 15:54:10.000000000 +0200
2217 @@ -0,0 +1,274 @@
2218 +/*
2219 + * Asterisk -- An open source telephony toolkit.
2220 + *
2221 + * Copyright (C) 1999 - 2005, Digium, Inc.
2222 + *
2223 + * Mark Spencer <markster@digium.com>
2224 + *
2225 + * See http://www.asterisk.org for more information about
2226 + * the Asterisk project. Please do not directly contact
2227 + * any of the maintainers of this project for assistance;
2228 + * the project provides a web site, mailing lists and IRC
2229 + * channels for your use.
2230 + *
2231 + * This program is free software, distributed under the terms of
2232 + * the GNU General Public License Version 2. See the LICENSE file
2233 + * at the top of the source tree.
2234 + */
2235 +
2236 +/*! \file
2237 + *
2238 + * \brief Execute an ISDN RAS
2239 + *
2240 + * \ingroup applications
2241 + */
2242 +
2243 +#include <sys/ioctl.h>
2244 +#include <sys/wait.h>
2245 +#ifdef __linux__
2246 +#include <sys/signal.h>
2247 +#else
2248 +#include <signal.h>
2249 +#endif /* __linux__ */
2250 +
2251 +#include <stdlib.h>
2252 +#include <unistd.h>
2253 +#include <string.h>
2254 +#include <stdlib.h>
2255 +#include <errno.h>
2256 +#include <stdio.h>
2257 +#include <fcntl.h>
2258 +
2259 +/* Need some zaptel help here */
2260 +#ifdef __linux__
2261 +#include <linux/zaptel.h>
2262 +#else
2263 +#include <zaptel.h>
2264 +#endif /* __linux__ */
2265 +
2266 +#include "asterisk.h"
2267 +
2268 +ASTERISK_FILE_VERSION(__FILE__, "$Revision: 37419 $")
2269 +
2270 +#include "asterisk/lock.h"
2271 +#include "asterisk/file.h"
2272 +#include "asterisk/logger.h"
2273 +#include "asterisk/channel.h"
2274 +#include "asterisk/pbx.h"
2275 +#include "asterisk/module.h"
2276 +#include "asterisk/options.h"
2277 +
2278 +static char *tdesc = "Zap RAS Application";
2279 +
2280 +static char *app = "ZapRAS";
2281 +
2282 +static char *synopsis = "Executes Zaptel ISDN RAS application";
2283 +
2284 +static char *descrip =
2285 +" ZapRAS(args): Executes a RAS server using pppd on the given channel.\n"
2286 +"The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
2287 +"channel to be able to use this function (No modem emulation is included).\n"
2288 +"Your pppd must be patched to be zaptel aware. Arguments should be\n"
2289 +"separated by | characters.\n";
2290 +
2291 +STANDARD_LOCAL_USER;
2292 +
2293 +LOCAL_USER_DECL;
2294 +
2295 +#define PPP_MAX_ARGS 32
2296 +#define PPP_EXEC "/usr/sbin/pppd"
2297 +
2298 +static pid_t spawn_ras(struct ast_channel *chan, char *args)
2299 +{
2300 + pid_t pid;
2301 + int x;
2302 + char *c;
2303 +
2304 + char *argv[PPP_MAX_ARGS];
2305 + int argc = 0;
2306 + char *stringp=NULL;
2307 +
2308 + /* Start by forking */
2309 + pid = fork();
2310 + if (pid)
2311 + return pid;
2312 +
2313 + /* Execute RAS on File handles */
2314 + dup2(chan->fds[0], STDIN_FILENO);
2315 +
2316 + /* Drop high priority */
2317 + if (option_highpriority)
2318 + ast_set_priority(0);
2319 +
2320 + /* Close other file descriptors */
2321 + for (x=STDERR_FILENO + 1;x<1024;x++)
2322 + close(x);
2323 +
2324 + /* Restore original signal handlers */
2325 + for (x=0;x<NSIG;x++)
2326 + signal(x, SIG_DFL);
2327 +
2328 + /* Reset all arguments */
2329 + memset(argv, 0, sizeof(argv));
2330 +
2331 + /* First argument is executable, followed by standard
2332 + arguments for zaptel PPP */
2333 + argv[argc++] = PPP_EXEC;
2334 + argv[argc++] = "nodetach";
2335 +
2336 + /* And all the other arguments */
2337 + stringp=args;
2338 + c = strsep(&stringp, "|");
2339 + while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
2340 + argv[argc++] = c;
2341 + c = strsep(&stringp, "|");
2342 + }
2343 +
2344 + argv[argc++] = "plugin";
2345 + argv[argc++] = "zaptel.so";
2346 + argv[argc++] = "stdin";
2347 +
2348 + /* Finally launch PPP */
2349 + execv(PPP_EXEC, argv);
2350 + fprintf(stderr, "Failed to exec PPPD!\n");
2351 + exit(1);
2352 +}
2353 +
2354 +static void run_ras(struct ast_channel *chan, char *args)
2355 +{
2356 + pid_t pid;
2357 + int status;
2358 + int res;
2359 + int signalled = 0;
2360 + struct zt_bufferinfo savebi;
2361 + int x;
2362 +
2363 + res = ioctl(chan->fds[0], ZT_GET_BUFINFO, &savebi);
2364 + if(res) {
2365 + ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
2366 + return;
2367 + }
2368 +
2369 + pid = spawn_ras(chan, args);
2370 + if (pid < 0) {
2371 + ast_log(LOG_WARNING, "Failed to spawn RAS\n");
2372 + } else {
2373 + for (;;) {
2374 + res = wait4(pid, &status, WNOHANG, NULL);
2375 + if (!res) {
2376 + /* Check for hangup */
2377 + if (chan->_softhangup && !signalled) {
2378 + ast_log(LOG_DEBUG, "Channel '%s' hungup. Signalling RAS at %d to die...\n", chan->name, pid);
2379 + kill(pid, SIGTERM);
2380 + signalled=1;
2381 + }
2382 + /* Try again */
2383 + sleep(1);
2384 + continue;
2385 + }
2386 + if (res < 0) {
2387 + ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
2388 + }
2389 + if (option_verbose > 2) {
2390 + if (WIFEXITED(status)) {
2391 + ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
2392 + } else if (WIFSIGNALED(status)) {
2393 + ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with signal %d\n",
2394 + chan->name, WTERMSIG(status));
2395 + } else {
2396 + ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated weirdly.\n", chan->name);
2397 + }
2398 + }
2399 + /* Throw back into audio mode */
2400 + x = 1;
2401 + ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
2402 +
2403 + /* Restore saved values */
2404 + res = ioctl(chan->fds[0], ZT_SET_BUFINFO, &savebi);
2405 + if (res < 0) {
2406 + ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
2407 + }
2408 + break;
2409 + }
2410 + }
2411 +}
2412 +
2413 +static int zapras_exec(struct ast_channel *chan, void *data)
2414 +{
2415 + int res=-1;
2416 + char *args;
2417 + struct localuser *u;
2418 + ZT_PARAMS ztp;
2419 +
2420 + if (!data)
2421 + data = "";
2422 +
2423 + LOCAL_USER_ADD(u);
2424 +
2425 + args = ast_strdupa(data);
2426 + if (!args) {
2427 + ast_log(LOG_ERROR, "Out of memory\n");
2428 + LOCAL_USER_REMOVE(u);
2429 + return -1;
2430 + }
2431 +
2432 + /* Answer the channel if it's not up */
2433 + if (chan->_state != AST_STATE_UP)
2434 + ast_answer(chan);
2435 + if (strcasecmp(chan->type, "Zap")) {
2436 + /* If it's not a zap channel, we're done. Wait a couple of
2437 + seconds and then hangup... */
2438 + if (option_verbose > 1)
2439 + ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a Zap channel\n", chan->name);
2440 + sleep(2);
2441 + } else {
2442 + memset(&ztp, 0, sizeof(ztp));
2443 + if (ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp)) {
2444 + ast_log(LOG_WARNING, "Unable to get zaptel parameters\n");
2445 + } else if (ztp.sigtype != ZT_SIG_CLEAR) {
2446 + if (option_verbose > 1)
2447 + ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a clear channel\n", chan->name);
2448 + } else {
2449 + /* Everything should be okay. Run PPP. */
2450 + if (option_verbose > 2)
2451 + ast_verbose(VERBOSE_PREFIX_3 "Starting RAS on %s\n", chan->name);
2452 + /* Execute RAS */
2453 + run_ras(chan, args);
2454 + }
2455 + }
2456 + LOCAL_USER_REMOVE(u);
2457 + return res;
2458 +}
2459 +
2460 +int unload_module(void)
2461 +{
2462 + int res;
2463 +
2464 + res = ast_unregister_application(app);
2465 +
2466 + STANDARD_HANGUP_LOCALUSERS;
2467 +
2468 + return res;
2469 +}
2470 +
2471 +int load_module(void)
2472 +{
2473 + return ast_register_application(app, zapras_exec, synopsis, descrip);
2474 +}
2475 +
2476 +char *description(void)
2477 +{
2478 + return tdesc;
2479 +}
2480 +
2481 +int usecount(void)
2482 +{
2483 + int res;
2484 + STANDARD_USECOUNT(res);
2485 + return res;
2486 +}
2487 +
2488 +char *key()
2489 +{
2490 + return ASTERISK_GPL_KEY;
2491 +}
2492 diff -urN asterisk-1.2.10.orig/asterisk.c asterisk-1.2.10/asterisk.c
2493 --- asterisk-1.2.10.orig/asterisk.c 2006-07-12 15:54:10.000000000 +0200
2494 +++ asterisk-1.2.10/asterisk.c 2006-07-31 14:13:08.000000000 +0200
2495 @@ -228,6 +228,7 @@
2496 char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH] = "\0";
2497 char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH] = "\0";
2498 char ast_config_AST_CTL[AST_CONFIG_MAX_PATH] = "asterisk.ctl";
2499 +char ast_config_AST_SYMBOLIC_NAME[20];
2500
2501 static char *_argv[256];
2502 static int shuttingdown = 0;
2503 @@ -1877,6 +1878,7 @@
2504 ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
2505 ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
2506 ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
2507 + ast_copy_string(ast_config_AST_SYMBOLIC_NAME, AST_SYMBOLIC_NAME, sizeof(ast_config_AST_SYMBOLIC_NAME));
2508
2509 /* no asterisk.conf? no problem, use buildtime config! */
2510 if (!cfg) {
2511 @@ -1991,6 +1993,8 @@
2512 /* What group to run as */
2513 } else if (!strcasecmp(v->name, "rungroup")) {
2514 ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
2515 + } else if (!strcasecmp(v->name, "uniquename")) {
2516 + strncpy(ast_config_AST_SYMBOLIC_NAME,v->value,sizeof(ast_config_AST_SYMBOLIC_NAME));
2517 }
2518 v = v->next;
2519 }
2520 diff -urN asterisk-1.2.10.orig/build_tools/make_defaults_h asterisk-1.2.10/build_tools/make_defaults_h
2521 --- asterisk-1.2.10.orig/build_tools/make_defaults_h 2005-06-20 19:26:08.000000000 +0200
2522 +++ asterisk-1.2.10/build_tools/make_defaults_h 2006-07-31 14:13:08.000000000 +0200
2523 @@ -16,6 +16,7 @@
2524 #define AST_KEY_DIR "${INSTALL_PATH}${ASTVARLIBDIR}/keys"
2525 #define AST_DB "${INSTALL_PATH}${ASTVARLIBDIR}/astdb"
2526 #define AST_TMP_DIR "${INSTALL_PATH}${ASTSPOOLDIR}/tmp"
2527 +#define AST_SYMBOLIC_NAME "asterisk"
2528
2529 #define AST_CONFIG_FILE "${INSTALL_PATH}${ASTCONFPATH}"
2530
2531 diff -urN asterisk-1.2.10.orig/channel.c asterisk-1.2.10/channel.c
2532 --- asterisk-1.2.10.orig/channel.c 2006-07-10 23:01:35.000000000 +0200
2533 +++ asterisk-1.2.10/channel.c 2006-07-31 14:13:08.000000000 +0200
2534 @@ -94,8 +94,8 @@
2535 */
2536 static int shutting_down = 0;
2537
2538 -AST_MUTEX_DEFINE_STATIC(uniquelock);
2539 static int uniqueint = 0;
2540 +AST_MUTEX_DEFINE_EXPORTED(uniquelock);
2541
2542 unsigned long global_fin = 0, global_fout = 0;
2543
2544 @@ -512,6 +512,17 @@
2545 .description = "Null channel (should not see this)",
2546 };
2547
2548 +char *ast_alloc_uniqueid(void) {
2549 + char *uniqueid;
2550 + uniqueid = malloc(64);
2551 + if (!uniqueid) return NULL;
2552 + ast_mutex_lock(&uniquelock);
2553 + snprintf(uniqueid, 63, "%s-%d-%li.%d", ast_config_AST_SYMBOLIC_NAME, ast_mainpid, (long)time(NULL), uniqueint++);
2554 + ast_mutex_unlock(&uniquelock);
2555 + return uniqueid;
2556 +}
2557 +
2558 +
2559 /*--- ast_channel_alloc: Create a new channel structure */
2560 struct ast_channel *ast_channel_alloc(int needqueue)
2561 {
2562 @@ -519,6 +530,7 @@
2563 int x;
2564 int flags;
2565 struct varshead *headp;
2566 + char *tmpuniqueid;
2567
2568
2569 /* If shutting down, don't allocate any new channels */
2570 @@ -584,9 +596,12 @@
2571 tmp->data = NULL;
2572 tmp->fin = global_fin;
2573 tmp->fout = global_fout;
2574 - ast_mutex_lock(&uniquelock);
2575 - snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), "%li.%d", (long) time(NULL), uniqueint++);
2576 - ast_mutex_unlock(&uniquelock);
2577 + tmpuniqueid = ast_alloc_uniqueid();
2578 + snprintf(tmp->uniqueid, sizeof(tmp->uniqueid), tmpuniqueid);
2579 + if (tmpuniqueid) {
2580 + free(tmpuniqueid);
2581 + tmpuniqueid = NULL;
2582 + }
2583 headp = &tmp->varshead;
2584 ast_mutex_init(&tmp->lock);
2585 AST_LIST_HEAD_INIT_NOLOCK(headp);
2586 @@ -729,7 +744,7 @@
2587 */
2588 static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
2589 const char *name, const int namelen,
2590 - const char *context, const char *exten)
2591 + const char *context, const char *exten, const char *uniqueid)
2592 {
2593 const char *msg = prev ? "deadlock" : "initial deadlock";
2594 int retries, done;
2595 @@ -740,9 +755,14 @@
2596 for (c = channels; c; c = c->next) {
2597 if (!prev) {
2598 /* want head of list */
2599 - if (!name && !exten)
2600 + if (!name && !exten && !uniqueid)
2601 break;
2602 - if (name) {
2603 + if (uniqueid) {
2604 + if (!strcasecmp(c->uniqueid, uniqueid))
2605 + break;
2606 + else
2607 + continue;
2608 + } else if (name) {
2609 /* want match by full name */
2610 if (!namelen) {
2611 if (!strcasecmp(c->name, name))
2612 @@ -793,33 +813,39 @@
2613 /*--- ast_channel_walk_locked: Browse channels in use */
2614 struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
2615 {
2616 - return channel_find_locked(prev, NULL, 0, NULL, NULL);
2617 + return channel_find_locked(prev, NULL, 0, NULL, NULL, NULL);
2618 }
2619
2620 /*--- ast_get_channel_by_name_locked: Get channel by name and lock it */
2621 struct ast_channel *ast_get_channel_by_name_locked(const char *name)
2622 {
2623 - return channel_find_locked(NULL, name, 0, NULL, NULL);
2624 + return channel_find_locked(NULL, name, 0, NULL, NULL, NULL);
2625 }
2626
2627 /*--- ast_get_channel_by_name_prefix_locked: Get channel by name prefix and lock it */
2628 struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
2629 {
2630 - return channel_find_locked(NULL, name, namelen, NULL, NULL);
2631 + return channel_find_locked(NULL, name, namelen, NULL, NULL, NULL);
2632 }
2633
2634 /*--- ast_walk_channel_by_name_prefix_locked: Get next channel by name prefix and lock it */
2635 struct ast_channel *ast_walk_channel_by_name_prefix_locked(struct ast_channel *chan, const char *name, const int namelen)
2636 {
2637 - return channel_find_locked(chan, name, namelen, NULL, NULL);
2638 + return channel_find_locked(chan, name, namelen, NULL, NULL, NULL);
2639 }
2640
2641 /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
2642 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context)
2643 {
2644 - return channel_find_locked(NULL, NULL, 0, context, exten);
2645 + return channel_find_locked(NULL, NULL, 0, context, exten, NULL);
2646 }
2647
2648 +struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid)
2649 +{
2650 + return channel_find_locked(NULL, NULL, 0, NULL, NULL, uniqueid);
2651 +}
2652 +
2653 +
2654 /*--- ast_safe_sleep_conditional: Wait, look for hangups and condition arg */
2655 int ast_safe_sleep_conditional( struct ast_channel *chan, int ms,
2656 int (*cond)(void*), void *data )
2657 @@ -912,8 +938,10 @@
2658 free(chan->tech_pvt);
2659 }
2660
2661 - if (chan->sched)
2662 - sched_context_destroy(chan->sched);
2663 + if (chan->sched) {
2664 + sched_context_destroy(chan->sched);
2665 + chan->sched = NULL;
2666 + }
2667
2668 ast_copy_string(name, chan->name, sizeof(name));
2669
2670 @@ -956,10 +984,11 @@
2671 while ((vardata = AST_LIST_REMOVE_HEAD(headp, entries)))
2672 ast_var_delete(vardata);
2673
2674 +
2675 free(chan);
2676 ast_mutex_unlock(&chlock);
2677
2678 - ast_device_state_changed_literal(name);
2679 + ast_device_state_changed_literal(name, NULL, NULL);
2680 }
2681
2682 int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy)
2683 @@ -2377,7 +2406,7 @@
2684 &chan->writetrans, 1);
2685 }
2686
2687 -struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
2688 +struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cid_num, const char *cid_name, struct outgoing_helper *oh, char* uniqueid)
2689 {
2690 int state = 0;
2691 int cause = 0;
2692 @@ -2385,7 +2414,7 @@
2693 struct ast_frame *f;
2694 int res = 0;
2695
2696 - chan = ast_request(type, format, data, &cause);
2697 + chan = ast_request(type, format, data, &cause, uniqueid);
2698 if (chan) {
2699 if (oh) {
2700 if (oh->vars)
2701 @@ -2399,6 +2428,7 @@
2702 }
2703 ast_set_callerid(chan, cid_num, cid_name, cid_num);
2704
2705 + chan->cid.cid_pres = callingpres;
2706 if (!ast_call(chan, data, 0)) {
2707 res = 1; /* in case chan->_state is already AST_STATE_UP */
2708 while (timeout && (chan->_state != AST_STATE_UP)) {
2709 @@ -2422,6 +2452,7 @@
2710 if (f->subclass == AST_CONTROL_RINGING)
2711 state = AST_CONTROL_RINGING;
2712 else if ((f->subclass == AST_CONTROL_BUSY) || (f->subclass == AST_CONTROL_CONGESTION)) {
2713 + res = 0;
2714 state = f->subclass;
2715 ast_frfree(f);
2716 break;
2717 @@ -2491,12 +2522,12 @@
2718 return chan;
2719 }
2720
2721 -struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, const char *cidnum, const char *cidname)
2722 +struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *outstate, int callingpres, const char *cidnum, const char *cidname, char *uniqueid)
2723 {
2724 - return __ast_request_and_dial(type, format, data, timeout, outstate, cidnum, cidname, NULL);
2725 + return __ast_request_and_dial(type, format, data, timeout, outstate, 0, cidnum, cidname, NULL, uniqueid);
2726 }
2727
2728 -struct ast_channel *ast_request(const char *type, int format, void *data, int *cause)
2729 +struct ast_channel *ast_request(const char *type, int format, void *data, int *cause, char *uniqueid)
2730 {
2731 struct chanlist *chan;
2732 struct ast_channel *c;
2733 @@ -2533,6 +2564,7 @@
2734 if (!(c = chan->tech->requester(type, capabilities, data, cause)))
2735 return NULL;
2736
2737 + if (uniqueid) strncpy(c->uniqueid, uniqueid, sizeof(c->uniqueid));
2738 if (c->_state == AST_STATE_DOWN) {
2739 manager_event(EVENT_FLAG_CALL, "Newchannel",
2740 "Channel: %s\r\n"
2741 @@ -2808,6 +2840,29 @@
2742 return res;
2743 }
2744
2745 +int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone)
2746 +{
2747 + struct ast_frame null = { AST_FRAME_NULL, };
2748 + int res = -1;
2749 + ast_log(LOG_DEBUG, "Planning to masquerade %s into the structure of %s\n",
2750 + clone->name, original->name);
2751 + if (original->masq) {
2752 + ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
2753 + original->masq->name, original->name);
2754 + } else if (clone->masqr) {
2755 + ast_log(LOG_WARNING, "%s is already going to masquerade as %s\n",
2756 + clone->name, clone->masqr->name);
2757 + } else {
2758 + original->masq = clone;
2759 + clone->masqr = original;
2760 + ast_queue_frame(original, &null);
2761 + ast_queue_frame(clone, &null);
2762 + ast_log(LOG_DEBUG, "Done planning to masquerade %s into the structure of %s\n", original->name, clone->name);
2763 + res = 0;
2764 + }
2765 + return res;
2766 +}
2767 +
2768 void ast_change_name(struct ast_channel *chan, char *newname)
2769 {
2770 char tmp[256];
2771 @@ -2947,7 +3002,7 @@
2772 ast_copy_string(clone->name, masqn, sizeof(clone->name));
2773
2774 /* Notify any managers of the change, first the masq then the other */
2775 - manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", newn, masqn, clone->uniqueid);
2776 + manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\nNewUniqueid: %s\r\n", newn, masqn, clone->uniqueid, original->uniqueid);
2777 manager_event(EVENT_FLAG_CALL, "Rename", "Oldname: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", orig, newn, original->uniqueid);
2778
2779 /* Swap the technlogies */
2780 @@ -3174,15 +3229,14 @@
2781 );
2782 }
2783
2784 -int ast_setstate(struct ast_channel *chan, int state)
2785 -{
2786 +int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name) {
2787 int oldstate = chan->_state;
2788
2789 if (oldstate == state)
2790 return 0;
2791
2792 chan->_state = state;
2793 - ast_device_state_changed_literal(chan->name);
2794 + ast_device_state_changed_literal(chan->name, cid_num, cid_name);
2795 manager_event(EVENT_FLAG_CALL,
2796 (oldstate == AST_STATE_DOWN) ? "Newchannel" : "Newstate",
2797 "Channel: %s\r\n"
2798 @@ -3198,6 +3252,10 @@
2799 return 0;
2800 }
2801
2802 +int ast_setstate(struct ast_channel *chan, int state) {
2803 + return ast_setstate_and_cid(chan, state, NULL, NULL);
2804 +}
2805 +
2806 /*--- Find bridged channel */
2807 struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
2808 {
2809 @@ -3375,6 +3433,7 @@
2810 char callee_warning = 0;
2811 int to;
2812
2813 +
2814 if (c0->_bridge) {
2815 ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
2816 c0->name, c0->_bridge->name);
2817 @@ -3385,6 +3444,10 @@
2818 c1->name, c1->_bridge->name);
2819 return -1;
2820 }
2821 +
2822 + if (IS_DIGITAL(c0->transfercapability) || IS_DIGITAL(c1->transfercapability)) {
2823 + config->flags = 0;
2824 + }
2825
2826 /* Stop if we're a zombie or need a soft hangup */
2827 if (ast_test_flag(c0, AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
2828 diff -urN asterisk-1.2.10.orig/channels/Makefile asterisk-1.2.10/channels/Makefile
2829 --- asterisk-1.2.10.orig/channels/Makefile 2006-04-30 16:27:56.000000000 +0200
2830 +++ asterisk-1.2.10/channels/Makefile 2006-07-31 14:13:08.000000000 +0200
2831 @@ -102,6 +102,11 @@
2832 ZAPR2=-lmfcr2
2833 endif
2834
2835 +ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/lib/libgsmat.so.1)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/lib/libgsmat.so.1),)
2836 + CFLAGS+=-DZAPATA_GSM
2837 + ZAPGSM=-lgsmat
2838 +endif
2839 +
2840 ALSA_SRC=chan_alsa.c
2841
2842 ifneq ($(wildcard alsa-monitor.h),)
2843 @@ -122,6 +127,35 @@
2844 endif
2845 endif # WITHOUT_ZAPTEL
2846
2847 +ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/capi20.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/capi20.h),)
2848 + CHANNEL_LIBS+=chan_capi.so
2849 +# uncomment the following line if you really never ever want early b3 connects,
2850 +# you can also configure it in the dialstring, this is just for performance
2851 +# NOTE: this is probably obsolete by using the "R" dial option
2852 +#CFLAGS+=-DCAPI_NEVER_EVER_EARLY_B3_CONNECTS
2853 +
2854 +# uncommnet next line to force dtmf software detection/generation, can also be configured
2855 +# in capi.conf on a perdevice basis (softdtmf=1)
2856 +#CFLAGS+=-DCAPI_FORCE_SOFTWARE_DTMF
2857 +
2858 +# uncomment the next line if you are in the ulaw world
2859 +#CFLAGS+=-DCAPI_ULAW
2860 +
2861 +# very experimental echo squelching
2862 +CFLAGS+=-DCAPI_ES
2863 +
2864 +#gains
2865 +CFLAGS+=-DCAPI_GAIN
2866 +
2867 +# what do to with call waiting connect indications?
2868 +# uncomment the next line for call deflection in that case
2869 +CFLAGS+=-DCAPI_DEFLECT_ON_CIRCUITBUSY
2870 +
2871 +# audio sync
2872 +CFLAGS+=-DCAPI_SYNC
2873 +
2874 +endif
2875 +
2876 ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/vpbapi.h),)
2877 CHANNEL_LIBS+=chan_vpb.so
2878 CFLAGS+=-DLINUX
2879 @@ -204,7 +238,7 @@
2880 $(CC) -c $(CFLAGS) -o chan_zap.o chan_zap.c
2881
2882 chan_zap.so: chan_zap.o
2883 - $(CC) $(SOLINK) -o $@ $< $(ZAPPRI) $(ZAPR2) -ltonezone
2884 + $(CC) $(SOLINK) -o $@ $< $(ZAPPRI) $(ZAPGSM) $(ZAPR2) -ltonezone
2885
2886 chan_sip.so: chan_sip.o
2887 $(CC) $(SOLINK) -o $@ ${CYGSOLINK} chan_sip.o ${CYGSOLIB}
2888 @@ -220,6 +254,9 @@
2889 chan_nbs.so: chan_nbs.o
2890 $(CC) $(SOLINK) -o $@ $< -lnbs
2891
2892 +chan_capi.so: chan_capi.o
2893 + $(CC) $(SOLINK) -o $@ $< -lcapi20
2894 +
2895 chan_vpb.o: chan_vpb.c
2896 $(CXX) -c $(CFLAGS) -o $@ chan_vpb.c
2897
2898 diff -urN asterisk-1.2.10.orig/channels/chan_agent.c asterisk-1.2.10/channels/chan_agent.c
2899 --- asterisk-1.2.10.orig/channels/chan_agent.c 2006-07-06 22:38:45.000000000 +0200
2900 +++ asterisk-1.2.10/channels/chan_agent.c 2006-07-31 14:13:08.000000000 +0200
2901 @@ -440,7 +440,7 @@
2902 if ((pointer = strchr(filename, '.')))
2903 *pointer = '-';
2904 snprintf(tmp, sizeof(tmp), "%s%s",savecallsin ? savecallsin : "", filename);
2905 - ast_monitor_start(ast, recordformat, tmp, needlock);
2906 + ast_monitor_start(ast, recordformat, tmp, NULL, NULL, needlock);
2907 ast_monitor_setjoinfiles(ast, 1);
2908 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix ? urlprefix : "", filename, recordformatext);
2909 #if 0
2910 @@ -1323,7 +1323,7 @@
2911 chan = agent_new(p, AST_STATE_DOWN);
2912 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) {
2913 /* Adjustable agent */
2914 - p->chan = ast_request("Local", format, p->loginchan, cause);
2915 + p->chan = ast_request("Local", format, p->loginchan, cause, NULL);
2916 if (p->chan)
2917 chan = agent_new(p, AST_STATE_DOWN);
2918 }
2919 diff -urN asterisk-1.2.10.orig/channels/chan_capi.c asterisk-1.2.10/channels/chan_capi.c
2920 --- asterisk-1.2.10.orig/channels/chan_capi.c 1970-01-01 01:00:00.000000000 +0100
2921 +++ asterisk-1.2.10/channels/chan_capi.c 2006-07-31 14:13:08.000000000 +0200
2922 @@ -0,0 +1,2888 @@
2923 +/*
2924 + * (CAPI*)
2925 + *
2926 + * An implementation of Common ISDN API 2.0 for Asterisk
2927 + *
2928 + * Copyright (C) 2002, 2003, 2004, 2005 Junghanns.NET GmbH
2929 + *
2930 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
2931 + *
2932 + * This program is free software and may be modified and
2933 + * distributed under the terms of the GNU Public License.
2934 + */
2935 +
2936 +#include <sys/time.h>
2937 +#include <sys/signal.h>
2938 +#include <stdlib.h>
2939 +#include <stdio.h>
2940 +#include <string.h>
2941 +#include <errno.h>
2942 +#include <unistd.h>
2943 +#include <fcntl.h>
2944 +#include <sys/types.h>
2945 +#include <asterisk/lock.h>
2946 +#include <asterisk/frame.h>
2947 +#include <asterisk/channel.h>
2948 +#include <asterisk/logger.h>
2949 +#include <asterisk/module.h>
2950 +#include <asterisk/pbx.h>
2951 +#include <asterisk/config.h>
2952 +#include <asterisk/options.h>
2953 +#include <asterisk/features.h>
2954 +#include <asterisk/utils.h>
2955 +#include <asterisk/cli.h>
2956 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
2957 +#include <capi_bsd.h>
2958 +#else
2959 +#include <linux/capi.h>
2960 +#endif
2961 +#include <capi20.h>
2962 +#include <asterisk/dsp.h>
2963 +#include <asterisk/xlaw.h>
2964 +#include <asterisk/chan_capi.h>
2965 +
2966 +unsigned ast_capi_ApplID;
2967 +_cword ast_capi_MessageNumber=1;
2968 +static char desc[] = "Common ISDN API for Asterisk";
2969 +#ifdef CAPI_ULAW
2970 +static char tdesc[] = "Common ISDN API Driver (0.4.0) muLaw";
2971 +#else
2972 +static char tdesc[] = "Common ISDN API Driver (0.4.0) aLaw ";
2973 +#endif
2974 +static char type[] = "CAPI";
2975 +
2976 +
2977 +static int usecnt;
2978 +AST_MUTEX_DEFINE_STATIC(usecnt_lock);
2979 +AST_MUTEX_DEFINE_STATIC(iflock);
2980 +AST_MUTEX_DEFINE_STATIC(pipelock);
2981 +AST_MUTEX_DEFINE_STATIC(monlock);
2982 +AST_MUTEX_DEFINE_STATIC(contrlock);
2983 +AST_MUTEX_DEFINE_STATIC(capi_send_buffer_lock);
2984 +AST_MUTEX_DEFINE_STATIC(capi_put_lock);
2985 +
2986 +#ifdef CAPI_ULAW
2987 +static int capi_capability = AST_FORMAT_ULAW;
2988 +#else
2989 +static int capi_capability = AST_FORMAT_ALAW;
2990 +#endif
2991 +
2992 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
2993 +static CAPIProfileBuffer_t profile;
2994 +#else
2995 +static struct ast_capi_profile profile;
2996 +#endif
2997 +static pthread_t monitor_thread = -1;
2998 +
2999 +static struct ast_capi_pvt *iflist = NULL;
3000 +static struct capi_pipe *pipelist = NULL;
3001 +static int capi_last_plci = 0;
3002 +static struct ast_capi_controller *capi_controllers[AST_CAPI_MAX_CONTROLLERS];
3003 +static int capi_num_controllers = 0;
3004 +static int capi_counter = 0;
3005 +static unsigned long capi_used_controllers=0;
3006 +
3007 +static char capi_send_buffer[AST_CAPI_MAX_B3_BLOCKS * AST_CAPI_MAX_B3_BLOCK_SIZE];
3008 +static int capi_send_buffer_handle = 0;
3009 +
3010 +char capi_national_prefix[AST_MAX_EXTENSION];
3011 +char capi_international_prefix[AST_MAX_EXTENSION];
3012 +
3013 +int capidebug = 0;
3014 +
3015 +static const struct ast_channel_tech capi_tech;
3016 +
3017 +MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG) {
3018 + MESSAGE_EXCHANGE_ERROR error;
3019 + if (ast_mutex_lock(&capi_put_lock)) {
3020 + ast_log(LOG_WARNING,"Unable to lock capi put!\n");
3021 + return -1;
3022 + }
3023 + error = capi20_put_cmsg(CMSG);
3024 + if (ast_mutex_unlock(&capi_put_lock)) {
3025 + ast_log(LOG_WARNING,"Unable to unlock capi put!\n");
3026 + return -1;
3027 + }
3028 + return error;
3029 +}
3030 +
3031 +
3032 +MESSAGE_EXCHANGE_ERROR check_wait_get_cmsg(_cmsg *CMSG) {
3033 + MESSAGE_EXCHANGE_ERROR Info;
3034 + struct timeval tv;
3035 + tv.tv_sec = 0;
3036 + tv.tv_usec = 10000;
3037 + Info = capi20_waitformessage(ast_capi_ApplID,&tv);
3038 + if ((Info != 0x0000) && (Info != 0x1104)) {
3039 + if (capidebug) {
3040 + ast_log(LOG_DEBUG, "Error waiting for cmsg... INFO = %#x\n", Info);
3041 + }
3042 + return Info;
3043 + }
3044 +
3045 + if (Info == 0x0000) {
3046 + Info = capi_get_cmsg(CMSG,ast_capi_ApplID);
3047 + }
3048 + return Info;
3049 +}
3050 +
3051 +
3052 +unsigned ListenOnController(unsigned long CIPmask,unsigned controller) {
3053 + MESSAGE_EXCHANGE_ERROR error;
3054 + _cmsg CMSG,CMSG2;
3055 +
3056 + LISTEN_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, controller);
3057 +#ifdef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
3058 + LISTEN_REQ_INFOMASK(&CMSG) = 0x00ff; // lots of info ;)
3059 +#else
3060 + LISTEN_REQ_INFOMASK(&CMSG) = 0x03ff; // lots of info ;) + early B3 connect
3061 +#endif
3062 + LISTEN_REQ_CIPMASK(&CMSG) = CIPmask;
3063 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3064 + return error;
3065 + }
3066 + while (!IS_LISTEN_CONF(&CMSG2)) {
3067 + error = check_wait_get_cmsg(&CMSG2);
3068 + }
3069 + return 0;
3070 +}
3071 +
3072 +// Echo cancellation is for cards w/ integrated echo cancellation only
3073 +// (i.e. Eicon active cards support it)
3074 +
3075 +#define EC_FUNCTION_ENABLE 1
3076 +#define EC_FUNCTION_DISABLE 2
3077 +#define EC_FUNCTION_FREEZE 3
3078 +#define EC_FUNCTION_RESUME 4
3079 +#define EC_FUNCTION_RESET 5
3080 +#define EC_OPTION_DISABLE_NEVER 0
3081 +#define EC_OPTION_DISABLE_G165 (1<<1)
3082 +#define EC_OPTION_DISABLE_G164_OR_G165 (1<<1 | 1<<2)
3083 +#define EC_DEFAULT_TAIL 64
3084 +
3085 +static int capi_echo_canceller(struct ast_channel *c, int function) {
3086 + struct ast_capi_pvt *i = c->tech_pvt;
3087 + MESSAGE_EXCHANGE_ERROR error;
3088 + _cmsg CMSG;
3089 + unsigned char buf[7];
3090 +
3091 + /* If echo cancellation is not requested or supported, don't attempt to enable it */
3092 + ast_mutex_lock(&contrlock);
3093 + if (!capi_controllers[i->controller]->echocancel || !i->doEC) {
3094 + ast_mutex_unlock(&contrlock);
3095 + return 0;
3096 + }
3097 + ast_mutex_unlock(&contrlock);
3098 +
3099 + if (option_verbose > 2)
3100 + ast_verbose(VERBOSE_PREFIX_3 "Setting up echo canceller (PLCI=%#x, function=%d, options=%d, tail=%d)\n",i->PLCI,function,i->ecOption,i->ecTail);
3101 +
3102 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3103 + FACILITY_REQ_NCCI(&CMSG) = i->NCCI;
3104 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 6; /* Echo canceller */
3105 +
3106 + buf[0]=6; /* msg size */
3107 + buf[1]=function;
3108 + if (function == EC_FUNCTION_ENABLE) {
3109 + buf[3]=i->ecOption; /* bit field - ignore echo canceller disable tone */
3110 + buf[5]=i->ecTail; /* Tail length, ms */
3111 + }
3112 + else {
3113 + buf[3]=0;
3114 + buf[5]=0;
3115 + }
3116 +
3117 + // Always null:
3118 + buf[2]=0;
3119 + buf[4]=0;
3120 + buf[6]=0;
3121 +
3122 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
3123 +
3124 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3125 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
3126 + return error;
3127 + }
3128 +
3129 + if (option_verbose > 5)
3130 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
3131 +
3132 + return 0;
3133 +}
3134 +
3135 +int capi_detect_dtmf(struct ast_channel *c, int flag) {
3136 + struct ast_capi_pvt *i = c->tech_pvt;
3137 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3138 + MESSAGE_EXCHANGE_ERROR error;
3139 + _cmsg CMSG;
3140 + unsigned char buf[9];
3141 + // does the controller support dtmf? and do we want to use it?
3142 + ast_mutex_lock(&contrlock);
3143 + if ((capi_controllers[i->controller]->dtmf == 1) && (i->doDTMF == 0)) {
3144 + ast_mutex_unlock(&contrlock);
3145 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3146 + FACILITY_REQ_PLCI(&CMSG) = i->PLCI;
3147 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
3148 + buf[0] = 8;
3149 + if (flag == 1) {
3150 + buf[1] = 1;
3151 + } else {
3152 + buf[1] = 2;
3153 + }
3154 + buf[2] = 0;
3155 + buf[3] = AST_CAPI_DTMF_DURATION;
3156 + buf[4] = 0;
3157 + buf[5] = AST_CAPI_DTMF_DURATION;
3158 + buf[6] = 0;
3159 + buf[7] = 0;
3160 + buf[8] = 0;
3161 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
3162 +
3163 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3164 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
3165 + return error;
3166 + } else {
3167 + if (option_verbose > 5) {
3168 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (PLCI=%#x)\n",i->PLCI);
3169 + }
3170 + }
3171 + } else {
3172 + ast_mutex_unlock(&contrlock);
3173 +
3174 +#endif
3175 + // do software dtmf detection
3176 + i->doDTMF = 1; // just being paranoid again...
3177 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3178 + }
3179 +#endif
3180 + return 0;
3181 +}
3182 +static int capi_send_digit(struct ast_channel *c,char digit) {
3183 + struct ast_capi_pvt *i = c->tech_pvt;
3184 + MESSAGE_EXCHANGE_ERROR error;
3185 + _cmsg CMSG;
3186 + unsigned char buf[10];
3187 +
3188 + if (i->state != CAPI_STATE_BCONNECTED) {
3189 + return 0;
3190 + }
3191 +
3192 +
3193 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
3194 + if(i->earlyB3 == 1)
3195 + /* we should really test for the network saying the number is incomplete
3196 + since i'm only doing a test and this is true at the right time
3197 + i'm going with this */
3198 + {
3199 +
3200 + INFO_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3201 + INFO_REQ_PLCI(&CMSG) = i->PLCI;
3202 + buf[0] = 2;
3203 + buf[1] = 0x80;
3204 + buf[2] = digit;
3205 + INFO_REQ_CALLEDPARTYNUMBER(&CMSG) = buf;
3206 +
3207 +
3208 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3209 + ast_log(LOG_ERROR,"error sending CALLEDPARTYNUMBER INFO (error=%#x)\n",error);
3210 + return error;
3211 + } else {
3212 + if (option_verbose > 5) {
3213 + ast_verbose(VERBOSE_PREFIX_4 "sent CALLEDPARTYNUMBER INFO digit = %c (PLCI=%#x)\n", digit, i->PLCI);
3214 + }
3215 + }
3216 +
3217 + } else {
3218 +#endif
3219 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3220 + ast_mutex_lock(&contrlock);
3221 + if ((capi_controllers[i->controller]->dtmf == 0) || (i->doDTMF == 1)) {
3222 +#endif
3223 + // let * fake it
3224 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3225 + ast_mutex_unlock(&contrlock);
3226 +#endif
3227 + return -1;
3228 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3229 + }
3230 + ast_mutex_unlock(&contrlock);
3231 +
3232 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3233 + FACILITY_REQ_PLCI(&CMSG) = i->NCCI;
3234 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 1;
3235 + buf[0] = 8;
3236 +
3237 + buf[1] = 3;
3238 + buf[2] = 0;
3239 +
3240 + buf[3] = AST_CAPI_DTMF_DURATION;
3241 + buf[4] = 0;
3242 +
3243 + buf[5] = AST_CAPI_DTMF_DURATION;
3244 + buf[6] = 0;
3245 +
3246 + buf[7] = 1;
3247 + buf[8] = digit;
3248 + buf[9] = 0;
3249 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = buf;
3250 +
3251 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3252 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
3253 + return error;
3254 + } else {
3255 + if (option_verbose > 4) {
3256 + ast_verbose(VERBOSE_PREFIX_3 "sent dtmf '%c'\n",digit);
3257 + }
3258 + }
3259 +#endif
3260 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
3261 + }
3262 +#endif
3263 + return 0;
3264 +}
3265 +
3266 +static int capi_alert(struct ast_channel *c) {
3267 + struct ast_capi_pvt *i = c->tech_pvt;
3268 + MESSAGE_EXCHANGE_ERROR error;
3269 + _cmsg CMSG;
3270 +
3271 + ALERT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
3272 + ALERT_REQ_PLCI(&CMSG) = i->PLCI;
3273 +
3274 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3275 + ast_log(LOG_ERROR,"error sending ALERT_REQ PLCI = %#x\n",i->PLCI);
3276 + return -1;
3277 + } else {
3278 + if (option_verbose > 5) {
3279 + ast_verbose(VERBOSE_PREFIX_4 "sent ALERT_REQ PLCI = %#x\n",i->PLCI);
3280 + }
3281 + }
3282 +
3283 + i->state = CAPI_STATE_ALERTING;
3284 + return 0;
3285 +}
3286 +
3287 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
3288 +static int capi_deflect(struct ast_channel *chan, void *data)
3289 +{
3290 + struct ast_capi_pvt *i = chan->tech_pvt;
3291 + MESSAGE_EXCHANGE_ERROR Info;
3292 + _cmsg CMSG;
3293 + char bchaninfo[1];
3294 + char fac[60];
3295 + int res=0;
3296 + int ms=3000;
3297 +
3298 + if (!data) {
3299 + ast_log(LOG_WARNING, "cd requires an argument (destination phone number)\n");
3300 + return -1;
3301 + }
3302 +
3303 + if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_BCONNECTED)) {
3304 + ast_log(LOG_ERROR, "call deflection does not work with calls that are already connected!\n");
3305 + return -1;
3306 + }
3307 + // wait until the channel is alerting, so we dont drop the call and interfer with msgs
3308 + while ((ms > 0) && (i->state != CAPI_STATE_ALERTING)) {
3309 + sleep(100);
3310 + ms -= 100;
3311 + }
3312 +
3313 + // make sure we hang up correctly
3314 + i->state = CAPI_STATE_CONNECTPENDING;
3315 +
3316 + fac[0]=0; // len
3317 + fac[1]=0; //len
3318 + fac[2]=0x01; // Use D-Chan
3319 + fac[3]=0; // Keypad len
3320 + fac[4]=31; // user user data? len = 31 = 29 + 2
3321 + fac[5]=0x1c; // magic?
3322 + fac[6]=0x1d; // strlen destination + 18 = 29
3323 + fac[7]=0x91; // ..
3324 + fac[8]=0xA1;
3325 + fac[9]=0x1A; // strlen destination + 15 = 26
3326 + fac[10]=0x02;
3327 + fac[11]=0x01;
3328 + fac[12]=0x70;
3329 + fac[13]=0x02;
3330 + fac[14]=0x01;
3331 + fac[15]=0x0d;
3332 + fac[16]=0x30;
3333 + fac[17]=0x12; // strlen destination + 7 = 18
3334 + fac[18]=0x30; // ...hm 0x30
3335 + fac[19]=0x0d; // strlen destination + 2
3336 + fac[20]=0x80; // CLIP
3337 + fac[21]=0x0b; // strlen destination
3338 + fac[22]=0x01; // destination start
3339 + fac[23]=0x01; //
3340 + fac[24]=0x01; //
3341 + fac[25]=0x01; //
3342 + fac[26]=0x01; //
3343 + fac[27]=0x01; //
3344 + fac[28]=0x01; //
3345 + fac[29]=0x01; //
3346 + fac[30]=0x01; //
3347 + fac[31]=0x01; //
3348 + fac[32]=0x01; //
3349 + fac[33]=0x01; // 0x1 = sending complete
3350 + fac[34]=0x01;
3351 + fac[35]=0x01;
3352 +
3353 + memcpy((unsigned char *)fac+22,data,strlen(data));
3354 + fac[22+strlen(data)]=0x01; // fill with 0x01 if number is only 6 numbers (local call)
3355 + fac[23+strlen(data)]=0x01;
3356 + fac[24+strlen(data)]=0x01;
3357 + fac[25+strlen(data)]=0x01;
3358 + fac[26+strlen(data)]=0x01;
3359 +
3360 + fac[6]=18+strlen(data);
3361 + fac[9]=15+strlen(data);
3362 + fac[17]=7+strlen(data);
3363 + fac[19]=2+strlen(data);
3364 + fac[21]=strlen(data);
3365 +
3366 + bchaninfo[0] = 0x1;
3367 + INFO_REQ_HEADER(&CMSG,ast_capi_ApplID,ast_capi_MessageNumber++,0);
3368 + INFO_REQ_CONTROLLER(&CMSG) = i->controller;
3369 + INFO_REQ_PLCI(&CMSG) = i->PLCI;
3370 + INFO_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char*)bchaninfo; // use D-Channel
3371 + INFO_REQ_KEYPADFACILITY(&CMSG) = 0;
3372 + INFO_REQ_USERUSERDATA(&CMSG) = 0;
3373 + INFO_REQ_FACILITYDATAARRAY(&CMSG) = (unsigned char*) fac + 4;
3374 +
3375 + if ((Info = _capi_put_cmsg(&CMSG)) != 0) {
3376 + ast_log(LOG_ERROR,"Error sending INFO_REQ\n");
3377 + return Info;
3378 + } else {
3379 + if (capidebug) {
3380 + // ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(&CMSG));
3381 + ast_log(LOG_NOTICE,"sent INFO_REQ PLCI = %#x\n",i->PLCI);
3382 + }
3383 + }
3384 +
3385 + return res;
3386 +}
3387 +#endif
3388 +
3389 +void remove_pipe(int PLCI) {
3390 + struct capi_pipe *p,*ptmp;
3391 +
3392 + ast_mutex_lock(&pipelock);
3393 + p = pipelist;
3394 + ptmp = NULL;
3395 + while (p) {
3396 + if (p->PLCI == PLCI) {
3397 + if (ptmp == NULL) {
3398 + // mypipe == head of pipelist
3399 + pipelist = p->next;
3400 + if(p->fd > -1) close(p->fd);
3401 + if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
3402 + free(p);
3403 + if (option_verbose > 4) {
3404 + ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
3405 + }
3406 + break;
3407 + } else {
3408 + // somehwere inbetween or at the end
3409 + ptmp->next = p->next;
3410 + if (p->next == NULL) {
3411 + capi_last_plci = p->PLCI;
3412 + }
3413 + if(p->fd > -1) close(p->fd);
3414 + if(p->i != NULL && p->i->fd > -1) close(p->i->fd);
3415 + free(p);
3416 + if (option_verbose > 4) {
3417 + ast_verbose(VERBOSE_PREFIX_3 "removed pipe for PLCI = %#x\n",PLCI);
3418 + }
3419 + break;
3420 + }
3421 + }
3422 + ptmp = p;
3423 + p = p->next;
3424 + }
3425 + ast_mutex_unlock(&pipelock);
3426 +}
3427 +
3428 +static int capi_activehangup(struct ast_channel *c) {
3429 + struct ast_capi_pvt *i = c->tech_pvt;
3430 + MESSAGE_EXCHANGE_ERROR error;
3431 + _cmsg CMSG;
3432 +
3433 + if (option_verbose > 2) {
3434 + if (capidebug)
3435 + ast_verbose(VERBOSE_PREFIX_4 "activehangingup\n");
3436 + }
3437 +
3438 + if (i == NULL) {
3439 + return 0;
3440 + }
3441 +
3442 + if (c->_state == AST_STATE_RING) {
3443 + CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
3444 + CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
3445 + CONNECT_RESP_REJECT(&CMSG) = 2;
3446 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3447 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",i->PLCI);
3448 + } else {
3449 + if (option_verbose > 5) {
3450 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",i->PLCI);
3451 + }
3452 + }
3453 + return 0;
3454 + }
3455 +
3456 + // active disconnect
3457 + if (i->state == CAPI_STATE_BCONNECTED) {
3458 + DISCONNECT_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3459 + DISCONNECT_B3_REQ_NCCI(&CMSG) = i->NCCI;
3460 +
3461 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3462 + ast_log(LOG_ERROR, "error sending DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
3463 + } else {
3464 + if (option_verbose > 5) {
3465 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_REQ NCCI=%#x\n",i->NCCI);
3466 + }
3467 + }
3468 + // wait for the B3 layer to go down
3469 + while (i->state != CAPI_STATE_CONNECTED) {
3470 + usleep(10000);
3471 + }
3472 + }
3473 + if ((i->state == CAPI_STATE_CONNECTED) || (i->state == CAPI_STATE_CONNECTPENDING)){
3474 + DISCONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3475 + DISCONNECT_REQ_PLCI(&CMSG) = i->PLCI;
3476 +
3477 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3478 + ast_log(LOG_ERROR, "error sending DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
3479 + } else {
3480 + if (option_verbose > 5) {
3481 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",i->PLCI);
3482 + }
3483 + }
3484 + // wait for the B1 layer to go down
3485 + while (i->state != CAPI_STATE_DISCONNECTED) {
3486 + usleep(10000);
3487 + }
3488 + }
3489 + return 0;
3490 +}
3491 +
3492 +static int capi_hangup(struct ast_channel *c) {
3493 + struct ast_capi_pvt *i = c->tech_pvt;
3494 +
3495 + // hmm....ok...this is called to free the capi interface (passive disconnect)
3496 + // or to bring down the channel (active disconnect)
3497 +
3498 + if (option_verbose > 3)
3499 + ast_verbose(VERBOSE_PREFIX_3 "CAPI Hangingup\n");
3500 +
3501 + if (i == NULL) {
3502 + ast_log(LOG_ERROR,"channel has no interface!\n");
3503 + return -1;
3504 + }
3505 +
3506 + // are we down, yet?
3507 + if (i->state != CAPI_STATE_DISCONNECTED) {
3508 + // no
3509 + capi_activehangup(c);
3510 + }
3511 +
3512 + remove_pipe(i->PLCI);
3513 + i->PLCI = 0;
3514 + i->NCCI = 0;
3515 + if ((i->doDTMF == 1) && (i->vad != NULL)) {
3516 + ast_dsp_free(i->vad);
3517 + }
3518 + ast_smoother_free(i->smoother); // discard any frames left hanging
3519 + i->smoother=ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE * 2);
3520 + memset(i->cid,0,sizeof(i->cid));
3521 + i->owner=NULL;
3522 + ast_mutex_lock(&usecnt_lock);
3523 + usecnt--;
3524 + ast_mutex_unlock(&usecnt_lock);
3525 + ast_update_use_count();
3526 + i->mypipe = NULL;
3527 + i = NULL;
3528 + c->tech_pvt = NULL;
3529 + ast_setstate(c,AST_STATE_DOWN);
3530 + return 0;
3531 +}
3532 +
3533 +static char *capi_number(char *data,int strip) {
3534 + unsigned len = *data;
3535 + // XXX fix me
3536 + // convert a capi struct to a \0 terminated string
3537 + if (!len || len < (unsigned int) strip) return NULL;
3538 + len = len - strip;
3539 + data = (char *)(data + 1 + strip);
3540 + return strndup((char *)data,len);
3541 +}
3542 +
3543 +int capi_call(struct ast_channel *c, char *idest, int timeout)
3544 +{
3545 + struct ast_capi_pvt *i;
3546 + struct capi_pipe *p = NULL;
3547 + int fds[2];
3548 + char *dest,*interface;
3549 + char buffer[AST_MAX_EXTENSION];
3550 + char called[AST_MAX_EXTENSION],calling[AST_MAX_EXTENSION];
3551 + char bchaninfo[3];
3552 + long flags;
3553 +
3554 + _cmsg CMSG;
3555 + MESSAGE_EXCHANGE_ERROR error;
3556 +
3557 + strncpy(buffer,idest,sizeof(buffer)-1);
3558 + interface = strtok(buffer, "/");
3559 + dest = strtok(NULL, "/");
3560 +
3561 +
3562 + if (!dest) {
3563 + ast_log(LOG_WARNING, "Destination %s requires a real destination\n", idest);
3564 + return -1;
3565 + }
3566 + i = c->tech_pvt;
3567 + i->doB3 = AST_CAPI_B3_DONT; // <homer>DOH</homer>
3568 +
3569 + // always B3
3570 + if (((char *)dest)[0] == 'b') {
3571 + i->doB3 = AST_CAPI_B3_ALWAYS;
3572 + }
3573 + // only do B3 on successfull calls
3574 + if (((char *)dest)[0] == 'B') {
3575 + i->doB3 = AST_CAPI_B3_ON_SUCCESS;
3576 + }
3577 +
3578 + if (i->doB3 != AST_CAPI_B3_DONT) {
3579 + dest++;
3580 + }
3581 +
3582 + if (option_verbose > 1) {
3583 + if (capidebug)
3584 + ast_verbose(VERBOSE_PREFIX_2 "CAPI Call %s %s", c->name, i->doB3?"with B3":"");
3585 + }
3586 + switch (c->cid.cid_pres) {
3587 + case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
3588 + case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
3589 + case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
3590 + case PRES_ALLOWED_NETWORK_NUMBER:
3591 + case PRES_NUMBER_NOT_AVAILABLE:
3592 + i->CLIR = 0;
3593 + break;
3594 + case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
3595 + case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
3596 + case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
3597 + case PRES_PROHIB_NETWORK_NUMBER:
3598 + i->CLIR = 1;
3599 + break;
3600 + default:
3601 + i->CLIR = 0;
3602 + }
3603 +
3604 + if (pipe(fds) == 0) {
3605 + ast_mutex_lock(&pipelock);
3606 + i->fd = fds[0];
3607 + flags = fcntl(i->fd,F_GETFL);
3608 + fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
3609 + p = malloc(sizeof(struct capi_pipe));
3610 + memset(p, 0, sizeof(struct capi_pipe));
3611 + p->fd = fds[1];
3612 + flags = fcntl(i->fd,F_GETFL);
3613 + fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
3614 + c->fds[0] = i->fd;
3615 + p->PLCI = -1;
3616 + p->i = i;
3617 + p->c = c;
3618 + i->mypipe = p;
3619 + p->next = pipelist;
3620 + pipelist = p;
3621 + if (option_verbose > 4) {
3622 + ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=-1\n");
3623 + }
3624 + ast_mutex_unlock(&pipelock);
3625 + }
3626 + i->outgoing = 1;
3627 +
3628 + i->MessageNumber = ast_capi_MessageNumber++;
3629 + CONNECT_REQ_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, i->controller);
3630 + CONNECT_REQ_CONTROLLER(&CMSG) = i->controller;
3631 + CONNECT_REQ_CIPVALUE(&CMSG) = 0x10; // Telephony, could also use 0x04 (3.1Khz audio)
3632 + called[0] = strlen(dest)+1;
3633 + called[1] = 0x80;
3634 + strncpy(&called[2],dest,sizeof(called)-2);
3635 + CONNECT_REQ_CALLEDPARTYNUMBER(&CMSG) = (unsigned char *)called;
3636 + CONNECT_REQ_CALLEDPARTYSUBADDRESS(&CMSG) = NULL;
3637 +
3638 + if (c->cid.cid_num) {
3639 + calling[0] = strlen(c->cid.cid_num)+2;
3640 + calling[1] = 0x0;
3641 + } else {
3642 + calling[0] = 0x0;
3643 + calling[1] = 0x0;
3644 + }
3645 +
3646 + if (i->CLIR == 1) {
3647 + calling[2] = 0xA0; // CLIR
3648 + } else {
3649 + calling[2] = 0x80; // CLIP
3650 + }
3651 +
3652 + if (c->cid.cid_num) {
3653 + strncpy(&calling[3],c->cid.cid_num,sizeof(calling)-3);
3654 + }
3655 + CONNECT_REQ_CALLINGPARTYNUMBER(&CMSG) = (unsigned char *)calling;
3656 + CONNECT_REQ_CALLINGPARTYSUBADDRESS(&CMSG) = NULL;
3657 +
3658 + CONNECT_REQ_B1PROTOCOL(&CMSG) = 1;
3659 + CONNECT_REQ_B2PROTOCOL(&CMSG) = 1; // 1
3660 + CONNECT_REQ_B3PROTOCOL(&CMSG) = 0;
3661 +
3662 + bchaninfo[0] = 2;
3663 + bchaninfo[1] = 0x0;
3664 + bchaninfo[2] = 0x0;
3665 + CONNECT_REQ_BCHANNELINFORMATION(&CMSG) = (unsigned char *)bchaninfo; // 0
3666 +
3667 + if ((error = _capi_put_cmsg(&CMSG))) {
3668 + ast_log(LOG_ERROR,"error sending CONNECT_REQ (error=%#x)\n",error);
3669 + return error;
3670 + } else {
3671 + if (option_verbose > 5) {
3672 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_REQ MN =%#x\n",CMSG.Messagenumber);
3673 + }
3674 + }
3675 +
3676 + i->state = CAPI_STATE_CONNECTPENDING;
3677 +
3678 + ast_setstate(c, AST_STATE_DIALING);
3679 +
3680 + // XXX fixme, not nice:
3681 +/* if (i->controller > 0) {
3682 + capi_controllers[i->controller]->nfreebchannels--;
3683 + } */
3684 +
3685 + // now we shall return .... the rest has to be done by handle_msg
3686 + return 0;
3687 +}
3688 +
3689 +
3690 +static int capi_answer(struct ast_channel *c) {
3691 + struct ast_capi_pvt *i = c->tech_pvt;
3692 + MESSAGE_EXCHANGE_ERROR error;
3693 + _cmsg CMSG;
3694 + char buf[AST_MAX_EXTENSION];
3695 + char *dnid;
3696 +
3697 + if (i->isdnmode && (strlen(i->incomingmsn)<strlen(i->dnid)))
3698 + dnid = i->dnid + strlen(i->incomingmsn);
3699 + else
3700 + dnid = i->dnid;
3701 +
3702 + CONNECT_RESP_HEADER(&CMSG, ast_capi_ApplID, i->MessageNumber, 0);
3703 + CONNECT_RESP_PLCI(&CMSG) = i->PLCI;
3704 + CONNECT_RESP_REJECT(&CMSG) = 0;
3705 + buf[0] = strlen(dnid)+2;
3706 + buf[1] = 0x0;
3707 + buf[2] = 0x80;
3708 + strncpy(&buf[3],dnid,sizeof(buf)-4);
3709 + CONNECT_RESP_CONNECTEDNUMBER(&CMSG) = (unsigned char *)buf;
3710 + CONNECT_RESP_CONNECTEDSUBADDRESS(&CMSG) = NULL;
3711 + CONNECT_RESP_LLC(&CMSG) = NULL;
3712 + CONNECT_RESP_B1PROTOCOL(&CMSG) = 1;
3713 + CONNECT_RESP_B2PROTOCOL(&CMSG) = 1;
3714 + CONNECT_RESP_B3PROTOCOL(&CMSG) = 0;
3715 +
3716 + if (option_verbose > 3)
3717 + ast_verbose(VERBOSE_PREFIX_3 "CAPI Answering for MSN %s\n", dnid);
3718 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3719 + return -1;
3720 + } else {
3721 + if (option_verbose > 5) {
3722 + if (capidebug)
3723 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP PLCI = %#x DNID = %s\n",i->PLCI,i->dnid);
3724 + }
3725 + }
3726 +
3727 + i->state = CAPI_STATE_ANSWERING;
3728 + i->doB3 = AST_CAPI_B3_DONT;
3729 + i->outgoing = 0;
3730 + i->earlyB3 = -1;
3731 +
3732 + return 0;
3733 +}
3734 +
3735 +struct ast_frame *capi_read(struct ast_channel *c) {
3736 + struct ast_capi_pvt *i = c->tech_pvt;
3737 + int readsize = 0;
3738 +
3739 + if ((i->state == CAPI_STATE_REMOTE_HANGUP)) {
3740 + ast_log(LOG_ERROR,"this channel is not connected\n");
3741 + return NULL;
3742 + }
3743 + if (i->state == CAPI_STATE_ONHOLD) {
3744 + i->fr.frametype = AST_FRAME_NULL;
3745 + return &i->fr;
3746 + }
3747 +
3748 + if (i == NULL) {
3749 + ast_log(LOG_ERROR,"channel has no interface\n");
3750 + return NULL;
3751 + }
3752 + i->fr.frametype = AST_FRAME_NULL;
3753 + i->fr.subclass = 0;
3754 + i->fr.delivery.tv_sec = 0;
3755 + i->fr.delivery.tv_usec = 0;
3756 + readsize = read(i->fd,&i->fr,sizeof(struct ast_frame));
3757 + if (readsize != sizeof(struct ast_frame)) {
3758 + ast_log(LOG_ERROR,"did not read a whole frame\n");
3759 + }
3760 + if (i->fr.frametype == AST_FRAME_VOICE) {
3761 + readsize = read(i->fd,i->fr.data,i->fr.datalen);
3762 + if (readsize != i->fr.datalen) {
3763 + ast_log(LOG_ERROR,"did not read whole frame data\n");
3764 + }
3765 + }
3766 + i->fr.mallocd = 0;
3767 + if (i->fr.frametype == AST_FRAME_NULL) {
3768 + return NULL;
3769 + }
3770 + if ((i->fr.frametype == AST_FRAME_DTMF) && (i->fr.subclass == 'f')) {
3771 + if (strcmp(c->exten, "fax")) {
3772 + if (ast_exists_extension(c, ast_strlen_zero(c->macrocontext) ? c->context : c->macrocontext, "fax", 1, c->cid.cid_num)) {
3773 + if (option_verbose > 2)
3774 + ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", c->name);
3775 + /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3776 + pbx_builtin_setvar_helper(c,"FAXEXTEN",c->exten);
3777 + if (ast_async_goto(c, c->context, "fax", 1))
3778 + ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", c->name, c->context);
3779 + } else {
3780 + ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3781 + }
3782 + } else {
3783 + ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3784 + }
3785 + }
3786 + return &i->fr;
3787 +}
3788 +
3789 +int capi_write(struct ast_channel *c, struct ast_frame *f) {
3790 + struct ast_capi_pvt *i = c->tech_pvt;
3791 + _cmsg CMSG;
3792 + MESSAGE_EXCHANGE_ERROR error;
3793 + int j=0;
3794 + char buf[1000];
3795 + struct ast_frame *fsmooth;
3796 +#ifdef CAPI_ES
3797 + int txavg=0;
3798 +#endif
3799 +
3800 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
3801 + // dont send audio to the local exchange!
3802 + if (i->earlyB3 == 1 || !i->NCCI) {
3803 + return 0;
3804 + }
3805 +#endif
3806 +
3807 + if (!i) {
3808 + ast_log(LOG_ERROR,"channel has no interface\n");
3809 + return -1;
3810 + }
3811 +
3812 + if (f->frametype == AST_FRAME_NULL) {
3813 + return 0;
3814 + }
3815 + if (f->frametype == AST_FRAME_DTMF) {
3816 + ast_log(LOG_ERROR,"dtmf frame should be written\n");
3817 + return 0;
3818 + }
3819 + if (f->frametype != AST_FRAME_VOICE) {
3820 + ast_log(LOG_ERROR,"not a voice frame\n");
3821 + return -1;
3822 + }
3823 + if (f->subclass != capi_capability) {
3824 + ast_log(LOG_ERROR,"dont know how to write subclass %d\n",f->subclass);
3825 + return -1;
3826 + }
3827 +// ast_log(LOG_NOTICE,"writing frame %d %d\n",f->frametype,f->subclass);
3828 +
3829 + if (ast_smoother_feed(i->smoother, f)!=0) {
3830 + ast_log(LOG_ERROR,"failed to fill smoother\n");
3831 + return -1;
3832 + }
3833 +
3834 + fsmooth=ast_smoother_read(i->smoother);
3835 + while(fsmooth != NULL) {
3836 + DATA_B3_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
3837 + DATA_B3_REQ_NCCI(&CMSG) = i->NCCI;
3838 + DATA_B3_REQ_DATALENGTH(&CMSG) = fsmooth->datalen;
3839 + DATA_B3_REQ_FLAGS(&CMSG) = 0;
3840 +
3841 + if (ast_mutex_lock(&capi_send_buffer_lock)) {
3842 + ast_log(LOG_WARNING,"Unable to lock B3 send buffer!\n");
3843 + return -1;
3844 + }
3845 +#ifndef CAPI_ES
3846 +#ifdef CAPI_GAIN
3847 + for (j=0;j<fsmooth->datalen;j++) {
3848 + buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
3849 + }
3850 +#else
3851 + for (j=0;j<fsmooth->datalen;j++) {
3852 + buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3853 + }
3854 +#endif
3855 +#else
3856 + if ((i->doES == 1)) {
3857 + for (j=0;j<fsmooth->datalen;j++) {
3858 + buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3859 + txavg += abs( capiXLAW2INT(reversebits[ ((unsigned char*)fsmooth->data)[j]]) );
3860 + }
3861 + txavg = txavg/j;
3862 + for(j=0;j<ECHO_TX_COUNT-1;j++) {
3863 + i->txavg[j] = i->txavg[j+1];
3864 + }
3865 + i->txavg[ECHO_TX_COUNT-1] = txavg;
3866 +
3867 +// ast_log(LOG_NOTICE,"txavg = %d\n",txavg);
3868 + } else {
3869 +#ifdef CAPI_GAIN
3870 + for (j=0;j<fsmooth->datalen;j++) {
3871 + buf[j] = i->g.txgains[reversebits[((unsigned char *)fsmooth->data)[j]]];
3872 + }
3873 +#else
3874 + for (j=0;j<fsmooth->datalen;j++) {
3875 + buf[j] = reversebits[ ((unsigned char *)fsmooth->data)[j] ];
3876 + }
3877 +#endif
3878 + }
3879 +#endif
3880 +
3881 + DATA_B3_REQ_DATAHANDLE(&CMSG) = capi_send_buffer_handle;
3882 + memcpy((char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE],&buf,fsmooth->datalen);
3883 + DATA_B3_REQ_DATA(&CMSG) = (unsigned char *)&capi_send_buffer[(capi_send_buffer_handle % AST_CAPI_MAX_B3_BLOCKS) * AST_CAPI_MAX_B3_BLOCK_SIZE];
3884 + capi_send_buffer_handle++;
3885 +
3886 + if (ast_mutex_unlock(&capi_send_buffer_lock)) {
3887 + ast_log(LOG_WARNING,"Unable to unlock B3 send buffer!\n");
3888 + return -1;
3889 + }
3890 +
3891 +
3892 +#ifdef CAPI_SYNC
3893 + ast_mutex_lock(&i->lockB3in);
3894 + if ((i->B3in >= 1) && (i->B3in <= AST_CAPI_MAX_B3_BLOCKS)) {
3895 + i->B3in--;
3896 + ast_mutex_unlock(&i->lockB3in);
3897 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3898 + ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d) B3in=%d\n",error,fsmooth->datalen,i->B3in);
3899 +// ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
3900 + } else {
3901 + if (option_verbose > 5) {
3902 + if (capidebug)
3903 + ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
3904 + }
3905 + }
3906 + } else {
3907 + if (i->B3in > 0) i->B3in--;
3908 + ast_mutex_unlock(&i->lockB3in);
3909 + }
3910 +#else
3911 + if ((error = _capi_put_cmsg(&CMSG)) != 0) {
3912 + ast_log(LOG_ERROR,"error sending DATA_B3_REQ (error=%#x, datalen=%d)\n",error,fsmooth->datalen);
3913 +// ast_log(LOG_NOTICE,"f: timelen %d b = %d MN = %d \n",fsmooth->timelen,b,CMSG.Messagenumber);
3914 + } else {
3915 + if (option_verbose > 5) {
3916 + if (capidebug)
3917 + ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_REQ (NCCI=%#x) (%d bytes)\n",i->NCCI,fsmooth->datalen);
3918 + }
3919 + }
3920 +#endif
3921 +
3922 +// ast_frfree(fsmooth);
3923 +
3924 + fsmooth=ast_smoother_read(i->smoother);
3925 + }
3926 + return 0;
3927 +}
3928 +
3929 +static int capi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) {
3930 + struct ast_capi_pvt *p = newchan->tech_pvt;
3931 + p->owner = newchan;
3932 + return 0;
3933 +}
3934 +
3935 +int capi_indicate(struct ast_channel *c,int condition) {
3936 + return -1;
3937 +}
3938 +
3939 +int capi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc) {
3940 + return -1;
3941 +}
3942 +
3943 +
3944 +struct ast_channel *capi_new(struct ast_capi_pvt *i,int state) {
3945 + struct ast_channel *tmp;
3946 + int fmt;
3947 +
3948 + tmp = ast_channel_alloc(1);
3949 + if (tmp != NULL) {
3950 + snprintf(tmp->name,sizeof(tmp->name),"CAPI/contr%d/%s-%d",i->controller,i->dnid,capi_counter++);
3951 + tmp->type = type;
3952 + tmp->tech = &capi_tech;
3953 + tmp->nativeformats = capi_capability;
3954 + ast_setstate(tmp,state);
3955 + tmp->fds[0] = i->fd;
3956 + i->smoother = ast_smoother_new(AST_CAPI_MAX_B3_BLOCK_SIZE);
3957 + if (i->smoother == NULL) {
3958 + ast_log(LOG_ERROR, "smoother NULL!\n");
3959 + }
3960 + i->fr.frametype = 0;
3961 + i->fr.subclass = 0;
3962 + i->fr.delivery.tv_sec = 0;
3963 + i->fr.delivery.tv_usec = 0;
3964 + i->state = CAPI_STATE_DISCONNECTED;
3965 + i->CLIR = 0;
3966 + i->calledPartyIsISDN = 0; // let's be pessimistic
3967 + i->earlyB3 = -1;
3968 + i->doB3 = AST_CAPI_B3_DONT;
3969 + i->outgoing = 0;
3970 + i->onholdPLCI = 0;
3971 +#ifdef CAPI_SYNC
3972 + i->B3in = 0;
3973 + ast_mutex_init(&i->lockB3in);
3974 +#endif
3975 +#ifdef CAPI_ES
3976 + memset(i->txavg,0,ECHO_TX_COUNT);
3977 +#endif
3978 +
3979 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3980 + if (i->doDTMF == 1) {
3981 +#endif
3982 + i->vad = ast_dsp_new();
3983 + ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT);
3984 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
3985 + }
3986 +#endif
3987 +
3988 + tmp->tech_pvt = i;
3989 + tmp->callgroup = i->callgroup;
3990 + tmp->nativeformats = capi_capability;
3991 + fmt = ast_best_codec(tmp->nativeformats);
3992 +// fmt = capi_capability;
3993 + tmp->readformat = fmt;
3994 + tmp->writeformat = fmt;
3995 + tmp->rawreadformat = fmt;
3996 + tmp->rawwriteformat = fmt;
3997 + strncpy(tmp->context,i->context,sizeof(tmp->context)-1);
3998 + tmp->cid.cid_num = strdup(i->cid);
3999 + tmp->cid.cid_dnid = strdup(i->dnid);
4000 + strncpy(tmp->exten,i->dnid,sizeof(tmp->exten)-1);
4001 + strncpy(tmp->accountcode,i->accountcode,sizeof(tmp->accountcode)-1);
4002 + i->owner = tmp;
4003 + ast_mutex_lock(&usecnt_lock);
4004 + usecnt++;
4005 + ast_mutex_unlock(&usecnt_lock);
4006 + ast_update_use_count();
4007 + if (state != AST_STATE_DOWN) {
4008 + // we are alerting (phones ringing)
4009 + if (state == AST_STATE_RING)
4010 + capi_alert(tmp);
4011 + if (ast_pbx_start(tmp)) {
4012 + ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
4013 + ast_hangup(tmp);
4014 + tmp = NULL;
4015 + } else {
4016 + if (option_verbose > 2) {
4017 + ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel (callgroup=%d)!\n",tmp->callgroup);
4018 + }
4019 + }
4020 + }
4021 + } else {
4022 + ast_log(LOG_ERROR,"Unable to allocate channel!\n");
4023 + }
4024 + return tmp;
4025 +}
4026 +
4027 +
4028 +struct ast_channel *capi_request(const char *type, int format, void *data, int *cause)
4029 +{
4030 + struct ast_capi_pvt *i;
4031 + struct ast_channel *tmp = NULL;
4032 + char *dest,*interface;
4033 + char buffer[AST_MAX_EXTENSION];
4034 + unsigned int capigroup=0, controller=0;
4035 + int notfound = 1;
4036 +
4037 + if (option_verbose > 1) {
4038 + if (capidebug)
4039 + ast_verbose(VERBOSE_PREFIX_3 "data = %s\n",(char *)data);
4040 + }
4041 + strncpy(buffer,(char *)data,sizeof(buffer)-1);
4042 +
4043 + interface = strtok(buffer, "/");
4044 + dest = strtok(NULL, "/");
4045 +
4046 +
4047 + if (((char *)interface)[0] == 'g') {
4048 + interface++;
4049 + capigroup = atoi(interface);
4050 + if (option_verbose > 1) {
4051 + if (capidebug)
4052 + ast_verbose(VERBOSE_PREFIX_3 "capi request group = %d\n",capigroup);
4053 + }
4054 + } else if (!strncmp(interface,"contr",5)) {
4055 + interface += 5;
4056 + controller = atoi(interface);
4057 + if (option_verbose > 1) {
4058 + if (capidebug)
4059 + ast_verbose(VERBOSE_PREFIX_3 "capi request controller = %d\n",controller);
4060 + }
4061 + } else {
4062 + ast_log(LOG_ERROR,"Syntax error in dialstring. read the docs!\n");
4063 + }
4064 +
4065 + ast_mutex_lock(&iflock);
4066 + i = iflist;
4067 + while (i && notfound) {
4068 + // unused channel
4069 + if (!i->owner) {
4070 + if (controller && (i->controllers & (1 << controller))) {
4071 + // DIAL(CAPI/contrX/...)
4072 + ast_mutex_lock(&contrlock);
4073 + if (capi_controllers[controller]->nfreebchannels > 0) {
4074 + strncpy(i->dnid,dest,sizeof(i->dnid)-1);
4075 + i->controller = controller;
4076 + tmp = capi_new(i, AST_STATE_DOWN);
4077 + i->PLCI = -1;
4078 + i->datahandle = 0;
4079 + i->outgoing = 1; // this is an outgoing line
4080 + i->earlyB3 = -1;
4081 + // capi_detect_dtmf(tmp,1);
4082 + ast_mutex_unlock(&contrlock);
4083 + ast_mutex_unlock(&iflock);
4084 + return tmp;
4085 + } else {
4086 + // keep on running!
4087 + ast_mutex_unlock(&contrlock);
4088 + }
4089 + } else if (capigroup && (i->group & (1 << capigroup))) {
4090 + int c;
4091 + // DIAL(CAPI/gX/...)
4092 + ast_mutex_lock(&contrlock);
4093 + for (c=1;c<=capi_num_controllers;c++) {
4094 + if (i->controllers & (1 << c)) {
4095 + if (capi_controllers[c]->nfreebchannels > 0) {
4096 + strncpy(i->dnid,dest,sizeof(i->dnid)-1);
4097 + i->controller = c;
4098 + tmp = capi_new(i, AST_STATE_DOWN);
4099 + i->PLCI = -1;
4100 + i->datahandle = 0;
4101 + i->outgoing = 1; // this is an outgoing line
4102 + i->earlyB3 = -1;
4103 + // capi_detect_dtmf(tmp,1);
4104 + ast_mutex_unlock(&contrlock);
4105 + ast_mutex_unlock(&iflock);
4106 + return tmp;
4107 + } else {
4108 + // keep on running!
4109 + }
4110 + }
4111 + }
4112 + ast_mutex_unlock(&contrlock);
4113 + }
4114 + }
4115 +// ast_log(LOG_NOTICE,"not contr %d group %d\n",i->controllers, i->group);
4116 + i = i->next;
4117 + }
4118 + ast_mutex_unlock(&iflock);
4119 + ast_log(LOG_NOTICE,"didn't find capi device with controller = %d or group = %d.\n",controller, capigroup);
4120 + return NULL;
4121 +}
4122 +
4123 +
4124 +struct capi_pipe *find_pipe(int PLCI,int MN) {
4125 + struct capi_pipe *p;
4126 + // find a pipe by PLCI or by MessageNumber (in case this is a CONNECT_CONF)
4127 + ast_mutex_lock(&pipelock);
4128 + p = pipelist;
4129 + if ((p == NULL) && (capi_last_plci != PLCI)){
4130 + if (capidebug) {
4131 + ast_log(LOG_NOTICE,"PLCI doesnt match last pipe (PLCI = %#x)\n",PLCI);
4132 + }
4133 + ast_mutex_unlock(&pipelock);
4134 + return NULL;
4135 + }
4136 + while(p != NULL) {
4137 + if ((p->PLCI == PLCI) || ( (p->PLCI == -1) && (p->i->MessageNumber == MN) ) ){
4138 + ast_mutex_unlock(&pipelock);
4139 + return p;
4140 + }
4141 + p = p->next;
4142 + }
4143 + if (capidebug) {
4144 + ast_log(LOG_ERROR,"unable to find a pipe for PLCI = %#x MN = %#x\n",PLCI,MN);
4145 + }
4146 + ast_mutex_unlock(&pipelock);
4147 + return NULL;
4148 +}
4149 +
4150 +int pipe_frame(struct capi_pipe *p,struct ast_frame *f) {
4151 + fd_set wfds;
4152 + int written=0;
4153 + struct timeval tv;
4154 + FD_ZERO(&wfds);
4155 + FD_SET(p->fd,&wfds);
4156 + tv.tv_sec = 0;
4157 + tv.tv_usec = 10;
4158 + if ((f->frametype == AST_FRAME_VOICE) && (p->i->doDTMF == 1) && (p->i->vad != NULL)) {
4159 + f = ast_dsp_process(p->c,p->i->vad,f);
4160 + if (f->frametype == AST_FRAME_NULL) {
4161 + return 0;
4162 + }
4163 + }
4164 + // we dont want the monitor thread to block
4165 + if (select(p->fd + 1,NULL,&wfds,NULL,&tv) == 1) {
4166 + written = write(p->fd,f,sizeof(struct ast_frame));
4167 + if (written < (signed int) sizeof(struct ast_frame)) {
4168 + ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n", written, (int)sizeof(struct ast_frame));
4169 + return -1;
4170 + }
4171 + if (f->frametype == AST_FRAME_VOICE) {
4172 + written = write(p->fd,f->data,f->datalen);
4173 + if (written < f->datalen) {
4174 + ast_log(LOG_ERROR,"wrote %d bytes instead of %d\n",written,f->datalen);
4175 + return -1;
4176 + }
4177 + }
4178 + } else {
4179 + return 0;
4180 + }
4181 + return -1;
4182 +}
4183 +
4184 +static int search_did(struct ast_channel *c)
4185 +{
4186 + // Returns
4187 + // -1 = Failure
4188 + // 0 = Match
4189 + // 1 = possible match
4190 + struct ast_capi_pvt *i = c->tech_pvt;
4191 + char *exten;
4192 +
4193 + if (strlen(i->dnid)<strlen(i->incomingmsn))
4194 + return -1;
4195 +
4196 +// exten = i->dnid + strlen(i->incomingmsn);
4197 + exten = i->dnid;
4198 +
4199 + if (ast_exists_extension(NULL, c->context, exten, 1, NULL)) {
4200 + c->priority = 1;
4201 + strncpy(c->exten, exten, sizeof(c->exten) - 1);
4202 + return 0;
4203 + }
4204 +
4205 + if (ast_canmatch_extension(NULL, c->context, exten, 1, NULL)) {
4206 + return 1;
4207 + }
4208 +
4209 +
4210 + return -1;
4211 +}
4212 +
4213 +int pipe_msg(int PLCI,_cmsg *CMSG) {
4214 + struct capi_pipe *p;
4215 + _cmsg CMSG2;
4216 + MESSAGE_EXCHANGE_ERROR error;
4217 + struct ast_frame fr;
4218 + char b3buf[1024];
4219 + int j;
4220 + int b3len=0;
4221 + char dtmf;
4222 + unsigned dtmflen;
4223 +#ifdef CAPI_ES
4224 + int rxavg = 0;
4225 + int txavg = 0;
4226 +#endif
4227 +
4228 + p = find_pipe(PLCI,CMSG->Messagenumber);
4229 + if (p == NULL) {
4230 + if (IS_DISCONNECT_IND(CMSG)) {
4231 + DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
4232 + DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
4233 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4234 + ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
4235 + } else {
4236 + if (option_verbose > 5) {
4237 + if (capidebug)
4238 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
4239 + }
4240 + }
4241 + return 0;
4242 + }
4243 + if (capidebug) {
4244 + ast_log(LOG_NOTICE,"%s",capi_cmsg2str(CMSG));
4245 + }
4246 + return -1;
4247 + }
4248 +
4249 + if (CMSG != NULL) {
4250 + switch (CMSG->Subcommand) {
4251 + case CAPI_IND:
4252 + switch (CMSG->Command) {
4253 + case CAPI_DISCONNECT_B3:
4254 +// ast_log(LOG_NOTICE,"DISCONNECT_B3_IND\n");
4255 +
4256 + DISCONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4257 + DISCONNECT_B3_RESP_NCCI(&CMSG2) = DISCONNECT_B3_IND_NCCI(CMSG);
4258 +
4259 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4260 + ast_log(LOG_NOTICE, "error sending DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
4261 + } else {
4262 + if (option_verbose > 5) {
4263 + if (capidebug)
4264 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_B3_RESP NCCI=%#x\n",(int)DISCONNECT_B3_IND_NCCI(CMSG));
4265 + }
4266 + }
4267 + if (p->i->state == CAPI_STATE_BCONNECTED) {
4268 + // passive disconnect
4269 + p->i->state = CAPI_STATE_CONNECTED;
4270 + } else
4271 + if (p->i->state == CAPI_STATE_DISCONNECTING) {
4272 + // active disconnect
4273 + memset(&CMSG2,0,sizeof(_cmsg));
4274 + DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
4275 + DISCONNECT_REQ_PLCI(&CMSG2) = PLCI;
4276 +
4277 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4278 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
4279 + } else {
4280 + if (option_verbose > 5) {
4281 + if (capidebug)
4282 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ PLCI=%#x\n",PLCI);
4283 + }
4284 + }
4285 + } else
4286 + if (p->i->state == CAPI_STATE_ONHOLD) {
4287 + // no hangup
4288 + }
4289 + ast_mutex_lock(&contrlock);
4290 + if (p->i->controller > 0) {
4291 + capi_controllers[p->i->controller]->nfreebchannels++;
4292 + }
4293 + ast_mutex_unlock(&contrlock);
4294 + break;
4295 + case CAPI_DISCONNECT:
4296 +// ast_log(LOG_NOTICE,"DISCONNECT_IND\n");
4297 + DISCONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber , 0);
4298 + DISCONNECT_RESP_PLCI(&CMSG2) = PLCI;
4299 +/* if (p->i->controller > 0) {
4300 + capi_controllers[p->i->controller]->nfreebchannels++;
4301 + } */
4302 +
4303 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4304 + ast_log(LOG_NOTICE, "error sending DISCONNECT_RESP PLCI=%#x\n",PLCI);
4305 + } else {
4306 + if (option_verbose > 5) {
4307 + if (capidebug)
4308 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_RESP PLCI=%#x\n",PLCI);
4309 + }
4310 + }
4311 + if (p->c) {
4312 + p->c->hangupcause = DISCONNECT_IND_REASON(CMSG) - 0x3480;
4313 + }
4314 +
4315 + if (PLCI == p->i->onholdPLCI) {
4316 + // the caller onhold hung up (or ECTed away)
4317 + p->i->onholdPLCI = 0;
4318 + remove_pipe(PLCI);
4319 + return 0;
4320 + }
4321 +
4322 + if (p->i->state == CAPI_STATE_DID) {
4323 + if ((p->c) != NULL) {
4324 + ast_hangup(p->c);
4325 + } else {
4326 + ast_log(LOG_WARNING, "unable to hangup channel on DID. Channel is NULL.\n");
4327 + }
4328 + return 0;
4329 + }
4330 +
4331 + p->i->state = CAPI_STATE_DISCONNECTED;
4332 +
4333 + fr.frametype = AST_FRAME_CONTROL;
4334 + if (DISCONNECT_IND_REASON(CMSG) == 0x34a2) {
4335 + fr.subclass = AST_CONTROL_BUSY;
4336 + } else {
4337 + fr.frametype = AST_FRAME_NULL;
4338 + }
4339 + fr.datalen = 0;
4340 + if (pipe_frame(p,(struct ast_frame *)&fr) == -1) {
4341 + // printf("STATE = %#x\n",p->i->state);
4342 + // in this case * did not read our hangup control frame
4343 + // so we must hangup the channel!
4344 + if ( (p->i->state != CAPI_STATE_DISCONNECTED) && (ast_check_hangup(p->c) == 0)) {
4345 + if (option_verbose > 1) {
4346 + ast_verbose(VERBOSE_PREFIX_3 "soft hangup by capi\n");
4347 + }
4348 + ast_softhangup(p->c,AST_SOFTHANGUP_DEV);
4349 + } else {
4350 + // dont ever hangup while hanging up!
4351 +// ast_log(LOG_NOTICE,"no soft hangup by capi\n");
4352 + }
4353 + return -1;
4354 + } else {
4355 + return 0;
4356 + }
4357 +
4358 +/* fr.frametype = AST_FRAME_NULL;
4359 + fr.datalen = 0;
4360 + pipe_frame(p,(struct ast_frame *)&fr); */
4361 + break;
4362 + case CAPI_DATA_B3:
4363 +
4364 + memcpy(&b3buf[AST_FRIENDLY_OFFSET],(char *)DATA_B3_IND_DATA(CMSG),DATA_B3_IND_DATALENGTH(CMSG));
4365 + b3len = DATA_B3_IND_DATALENGTH(CMSG);
4366 +
4367 + // send a DATA_B3_RESP very quickly to free the buffer in capi
4368 + DATA_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
4369 + DATA_B3_RESP_NCCI(&CMSG2) = DATA_B3_IND_NCCI(CMSG);
4370 + DATA_B3_RESP_DATAHANDLE(&CMSG2) = DATA_B3_IND_DATAHANDLE(CMSG);
4371 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4372 + ast_log(LOG_ERROR,"error sending DATA_B3_RESP (error=%#x)\n",error);
4373 + } else {
4374 + if (option_verbose > 6) {
4375 + if (capidebug)
4376 + ast_verbose(VERBOSE_PREFIX_4 "sent DATA_B3_RESP (NCCI=%#x)\n",(int)DATA_B3_IND_NCCI(CMSG));
4377 + }
4378 + }
4379 +#ifdef CAPI_SYNC
4380 + ast_mutex_lock(&p->i->lockB3in);
4381 + p->i->B3in++;
4382 + if (p->i->B3in > AST_CAPI_MAX_B3_BLOCKS) p->i->B3in = AST_CAPI_MAX_B3_BLOCKS;
4383 + ast_mutex_unlock(&p->i->lockB3in);
4384 +#endif
4385 +#ifdef CAPI_ES
4386 + if ((p->i->doES == 1)) {
4387 + for (j=0;j<b3len;j++) {
4388 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
4389 + rxavg += abs(capiXLAW2INT( reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]));
4390 + }
4391 + rxavg = rxavg/j;
4392 + for(j=0;j<ECHO_EFFECTIVE_TX_COUNT;j++) {
4393 + txavg += p->i->txavg[j];
4394 + }
4395 + txavg = txavg/j;
4396 +
4397 + if( (txavg/ECHO_TXRX_RATIO) > rxavg) {
4398 +#ifdef CAPI_ULAW
4399 + memset(&b3buf[AST_FRIENDLY_OFFSET],255,b3len);
4400 +#else
4401 + memset(&b3buf[AST_FRIENDLY_OFFSET],84,b3len);
4402 +#endif
4403 + if (capidebug) {
4404 + ast_log(LOG_NOTICE,"SUPPRESSING ECHOrx=%d, tx=%d\n",rxavg,txavg);
4405 + }
4406 + }
4407 + } else {
4408 +#ifdef CAPI_GAIN
4409 + for (j=0;j<b3len;j++) {
4410 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]];
4411 + }
4412 +#else
4413 + for (j=0;j<b3len;j++) {
4414 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
4415 + }
4416 +#endif
4417 + }
4418 +#else
4419 +
4420 +#ifdef CAPI_GAIN
4421 + for (j=0;j<b3len;j++) {
4422 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[p->i->g.rxgains[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]]];
4423 + }
4424 +#else
4425 + for (j=0;j<b3len;j++) {
4426 + b3buf[AST_FRIENDLY_OFFSET + j] = reversebits[(unsigned char)b3buf[AST_FRIENDLY_OFFSET + j]];
4427 + }
4428 +#endif
4429 +
4430 +#endif
4431 + // just being paranoid ...
4432 + /* if (p->c->_state != AST_STATE_UP) {
4433 + ast_setstate(p->c,AST_STATE_UP);
4434 + } */
4435 +
4436 + fr.frametype = AST_FRAME_VOICE;
4437 + fr.subclass = capi_capability;
4438 + fr.data = (char *)&b3buf[AST_FRIENDLY_OFFSET];
4439 + fr.datalen = b3len;
4440 + fr.samples = b3len;
4441 + fr.offset = AST_FRIENDLY_OFFSET;
4442 + fr.mallocd = 0;
4443 + fr.delivery.tv_sec = 0;
4444 + fr.delivery.tv_usec = 0;
4445 + fr.src = NULL;
4446 + // ast_verbose(VERBOSE_PREFIX_3 "DATA_B3_IND (len=%d) fr.datalen=%d fr.subclass=%d\n",(int)DATA_B3_IND_DATALENGTH(CMSG),fr.datalen,fr.subclass);
4447 + return pipe_frame(p,(struct ast_frame *)&fr);
4448 + break;
4449 + case CAPI_FACILITY:
4450 + if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0001) {
4451 + // DTMF received
4452 + if (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0] != (0xff)) {
4453 + dtmflen = FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0];
4454 + FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 1;
4455 + } else {
4456 + dtmflen = ((__u16 *) (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) + 1))[0];
4457 + FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG) += 3;
4458 + }
4459 + if (dtmflen == 1) {
4460 + dtmf = (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG))[0];
4461 + fr.frametype = AST_FRAME_DTMF;
4462 + fr.subclass = dtmf;
4463 + if (option_verbose > 1) {
4464 + if (capidebug)
4465 + ast_verbose(VERBOSE_PREFIX_3 "c_dtmf = %c\n",dtmf);
4466 + }
4467 + pipe_frame(p,(struct ast_frame *)&fr);
4468 + }
4469 + }
4470 + if (FACILITY_IND_FACILITYSELECTOR(CMSG) == 0x0003) {
4471 + // sservices
4472 + /* ast_log(LOG_NOTICE,"FACILITY_IND PLCI = %#x\n",(int)FACILITY_IND_PLCI(CMSG));
4473 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[0]);
4474 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1]);
4475 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[2]);
4476 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3]);
4477 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
4478 + ast_log(LOG_NOTICE,"%#x\n",FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5]); */
4479 + // RETRIEVE
4480 + if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x3) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
4481 + p->i->state = CAPI_STATE_CONNECTED;
4482 + p->i->PLCI = p->i->onholdPLCI;
4483 + p->i->onholdPLCI = 0;
4484 + }
4485 + if ( (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3] == 0x2)) {
4486 + if ((FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5] != 0) && (FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4] != 0)) {
4487 + // reason != 0x0000 == problem
4488 + p->i->onholdPLCI = 0;
4489 + p->i->state = CAPI_STATE_ONHOLD;
4490 + ast_log(LOG_WARNING, "unable to put PLCI=%#x onhold, REASON = %#x%#x, maybe you need to subscribe for this...\n",(int)FACILITY_IND_PLCI(CMSG),FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[5],FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
4491 + } else {
4492 + // reason = 0x0000 == call on hold
4493 + p->i->state = CAPI_STATE_ONHOLD;
4494 + if (capidebug)
4495 + ast_log(LOG_NOTICE, "PLCI=%#x put onhold\n",(int)FACILITY_IND_PLCI(CMSG));
4496 + }
4497 + }
4498 + }
4499 +
4500 + error = FACILITY_RESP(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,FACILITY_IND_PLCI(CMSG),FACILITY_IND_FACILITYSELECTOR(CMSG),FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG));
4501 +
4502 + if (error != 0) {
4503 + ast_log(LOG_ERROR,"error sending FACILITY_RESP (error=%#x)\n",error);
4504 + } else {
4505 + if (option_verbose > 5) {
4506 + if (capidebug)
4507 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_RESP (PLCI=%#x)\n",(int)FACILITY_IND_PLCI(CMSG));
4508 + }
4509 + }
4510 + break;
4511 + case CAPI_INFO:
4512 + // ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
4513 +
4514 + memset(&CMSG2,0,sizeof(_cmsg));
4515 + error = INFO_RESP(&CMSG2,ast_capi_ApplID,CMSG->Messagenumber,PLCI);
4516 + if (error != 0) {
4517 + ast_log(LOG_ERROR,"error sending INFO_RESP (error=%#x)\n",error);
4518 + return -1;
4519 + } else {
4520 + if (option_verbose > 5) {
4521 + if (capidebug)
4522 + ast_verbose(VERBOSE_PREFIX_4 "sent INFO_RESP (PLCI=%#x)\n",PLCI);
4523 + }
4524 + }
4525 +/* if ((INFO_IND_INFONUMBER(CMSG) >> 8) == 0x00) {
4526 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[0]);
4527 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[1]);
4528 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[2]);
4529 + ast_log(LOG_ERROR,"%#x\n",INFO_IND_INFOELEMENT(CMSG)[3]);
4530 + } */
4531 +#ifndef CAPI_NEVER_EVER_EARLY_B3_CONNECTS
4532 + if ((INFO_IND_INFONUMBER(CMSG) == 0x001e) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == -1) && (p->i->state != CAPI_STATE_BCONNECTED)){
4533 + // ETSI 300 102-1 Progress Indicator
4534 + // we do early B3 Connect
4535 + if(INFO_IND_INFOELEMENT(CMSG)[0] >= 2) {
4536 + if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x2) {
4537 + p->i->calledPartyIsISDN = 0;
4538 + // ast_log(LOG_NOTICE,"A N A L O G \n");
4539 + } else {
4540 + p->i->calledPartyIsISDN = 1;
4541 + // ast_log(LOG_NOTICE,"I S D N\n");
4542 + }
4543 + if(INFO_IND_INFOELEMENT(CMSG)[2] & 0x88) {
4544 + // in-band info available
4545 + p->i->earlyB3 = 1;
4546 + memset(&CMSG2,0,sizeof(_cmsg));
4547 + CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
4548 + CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
4549 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4550 + ast_log(LOG_ERROR,"error sending early CONNECT_B3_REQ (error=%#x)\n",error);
4551 + return -1;
4552 + } else {
4553 + if (option_verbose > 1) {
4554 + if (capidebug)
4555 + ast_verbose(VERBOSE_PREFIX_4 "sent early CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
4556 + }
4557 + }
4558 + }
4559 + }
4560 + }
4561 + // DISCONNECT
4562 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (PLCI == p->i->onholdPLCI)) {
4563 + // the caller onhold hung up (or ECTed away)
4564 + // send a disconnect_req , we cannot hangup the channel here!!!
4565 + memset(&CMSG2,0,sizeof(_cmsg));
4566 + DISCONNECT_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
4567 + DISCONNECT_REQ_PLCI(&CMSG2) = p->i->onholdPLCI;
4568 +
4569 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4570 + ast_log(LOG_NOTICE, "error sending DISCONNECT_REQ PLCI=%#x\n",PLCI);
4571 + } else {
4572 + if (option_verbose > 1) {
4573 + if (capidebug)
4574 + ast_verbose(VERBOSE_PREFIX_4 "sent DISCONNECT_REQ for onholdPLCI=%#x\n",PLCI);
4575 + }
4576 + }
4577 + return 0;
4578 + }
4579 +
4580 + // case 1: B3 on success or no B3 at all
4581 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_ALWAYS) && (p->i->outgoing == 1)) {
4582 + p->i->earlyB3 = 0; // !!!
4583 + fr.frametype = AST_FRAME_NULL;
4584 + fr.datalen = 0;
4585 + return pipe_frame(p,(struct ast_frame *)&fr);
4586 + }
4587 + // case 2: we are doing B3, and receive the 0x8045 after a successful call
4588 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 != AST_CAPI_B3_DONT) && (p->i->earlyB3 == 0) && (p->i->outgoing == 1)) {
4589 + fr.frametype = AST_FRAME_NULL;
4590 + fr.datalen = 0;
4591 + return pipe_frame(p,(struct ast_frame *)&fr);
4592 + }
4593 + // case 3: this channel is an incoming channel! the user hung up!
4594 + // it is much better to hangup now instead of waiting for a timeout and
4595 + // network caused DISCONNECT_IND!
4596 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->outgoing == 0)) {
4597 + // ast_log(LOG_NOTICE,"case 3\n");
4598 + fr.frametype = AST_FRAME_NULL;
4599 + fr.datalen = 0;
4600 + return pipe_frame(p,(struct ast_frame *)&fr);
4601 + }
4602 + // case 4 (a.k.a. the italian case): B3 always. call is unsuccessful
4603 + if ((INFO_IND_INFONUMBER(CMSG) == 0x8045) && (p->i->doB3 == AST_CAPI_B3_ALWAYS) && (p->i->earlyB3 == -1) && (p->i->outgoing == 1)) {
4604 + // wait for the 0x001e (PROGRESS), play audio and wait for a timeout from the network
4605 + return 0;
4606 + }
4607 +#endif
4608 + // Handle DID digits
4609 + if ((INFO_IND_INFONUMBER(CMSG) == 0x0070) && p->i->isdnmode && (p->c != NULL)) {
4610 + int search = -1;
4611 + char name[AST_CHANNEL_NAME] = "";
4612 + char *did;
4613 +
4614 + did = capi_number((char *)INFO_IND_INFOELEMENT(CMSG),1);
4615 + if (strcasecmp(p->i->dnid, did)) {
4616 + strncat(p->i->dnid, did, sizeof(p->i->dnid)-1);
4617 + }
4618 +
4619 + snprintf(name,sizeof(name),"CAPI/contr%d/%s/-%d",p->i->controller,p->i->dnid,capi_counter++);
4620 + ast_change_name(p->c, name);
4621 +
4622 + search = search_did(p->c);
4623 + if (search != -1) {
4624 + if (!search) {
4625 + ast_setstate(p->c, AST_STATE_RING);
4626 + // we are alerting (phones ringing)
4627 + capi_alert(p->c); // Do this here after pbx_start the Channel can be destroyed
4628 + if (ast_pbx_start(p->c)) {
4629 + ast_log(LOG_ERROR,"Unable to start pbx on channel!\n");
4630 + ast_hangup(p->c);
4631 + } else {
4632 + if (option_verbose > 2) {
4633 + if (capidebug)
4634 + ast_verbose(VERBOSE_PREFIX_3 "started pbx on channel!\n");
4635 + }
4636 + }
4637 + }
4638 + } else {
4639 + ast_log(LOG_ERROR,"did not find device for msn = %s\n",p->i->dnid);
4640 + CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4641 + CONNECT_RESP_PLCI(&CMSG2) = PLCI;
4642 + CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
4643 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4644 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4645 + } else {
4646 + if (option_verbose > 5) {
4647 + if (capidebug)
4648 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4649 + }
4650 + }
4651 +
4652 + return 0;
4653 + }
4654 + }
4655 + if (INFO_IND_INFONUMBER(CMSG) == 0x8001) {
4656 + fr.frametype = AST_FRAME_CONTROL;
4657 + fr.subclass = AST_CONTROL_RINGING;
4658 + return pipe_frame(p,(struct ast_frame *)&fr);
4659 + }
4660 + if (INFO_IND_INFONUMBER(CMSG) == 0x800d) {
4661 + fr.frametype = AST_FRAME_CONTROL;
4662 + fr.subclass = AST_CONTROL_PROGRESS;
4663 + return pipe_frame(p,(struct ast_frame *)&fr);
4664 + }
4665 + if (INFO_IND_INFONUMBER(CMSG) == 0x74) {
4666 + strncpy(p->i->owner->exten,capi_number((char *)INFO_IND_INFOELEMENT(CMSG),3),sizeof(p->i->owner->exten)-1);
4667 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4668 + }
4669 + if (INFO_IND_INFONUMBER(CMSG) == 0x28) {
4670 + // ast_sendtext(p->i->owner,capi_number(INFO_IND_INFOELEMENT(CMSG),0));
4671 + // struct ast_frame ft = { AST_FRAME_TEXT, capi_number(INFO_IND_INFOELEMENT(CMSG),0), };
4672 + // ast_queue_frame(p->i->owner, &ft);
4673 + // ast_log(LOG_NOTICE,"%s\n",capi_number(INFO_IND_INFOELEMENT(CMSG),0));
4674 + }
4675 + break;
4676 + case CAPI_CONNECT_ACTIVE:
4677 +// ast_log(LOG_NOTICE,"CONNECT_ACTIVE_IND PLCI=%#x\n",(int)CONNECT_ACTIVE_IND_PLCI(CMSG));
4678 + CONNECT_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber,0);
4679 + CONNECT_ACTIVE_RESP_PLCI(&CMSG2) = PLCI;
4680 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4681 + ast_log(LOG_ERROR,"error sending CONNECT_ACTIVE_RESP (error=%#x)\n",error);
4682 + return -1;
4683 + } else {
4684 + if (option_verbose > 5) {
4685 + if (capidebug)
4686 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_ACTIVE_RESP (PLCI=%#x)\n",PLCI);
4687 + }
4688 + }
4689 + // normal processing
4690 + if (p->i->earlyB3 != 1) {
4691 + p->i->state = CAPI_STATE_CONNECTED;
4692 +
4693 + // send a CONNECT_B3_REQ
4694 + if (p->i->outgoing == 1) {
4695 + // outgoing call
4696 + memset(&CMSG2,0,sizeof(_cmsg));
4697 + CONNECT_B3_REQ_HEADER(&CMSG2, ast_capi_ApplID, ast_capi_MessageNumber++,0);
4698 + CONNECT_B3_REQ_PLCI(&CMSG2) = PLCI;
4699 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4700 + ast_log(LOG_ERROR,"error sending CONNECT_B3_REQ (error=%#x)\n",error);
4701 + return -1;
4702 + } else {
4703 + if (option_verbose > 1) {
4704 + if (capidebug)
4705 + ast_verbose(VERBOSE_PREFIX_3 "sent CONNECT_B3_REQ (PLCI=%#x)\n",PLCI);
4706 + }
4707 + }
4708 + } else {
4709 + // incoming call
4710 + // RESP already sent ... wait for CONNECT_B3_IND
4711 +// ast_log(LOG_NOTICE,"waiting for CONNECT_B3_IND\n");
4712 + }
4713 + } else {
4714 + // special treatment for early B3 connects
4715 + p->i->state = CAPI_STATE_BCONNECTED;
4716 + if (p->c->_state != AST_STATE_UP) {
4717 + ast_setstate(p->c,AST_STATE_UP);
4718 + }
4719 + p->i->earlyB3 = 0; // not early anymore
4720 + fr.frametype = AST_FRAME_CONTROL;
4721 + fr.subclass = AST_CONTROL_ANSWER;
4722 + fr.datalen = 0;
4723 + return pipe_frame(p,(struct ast_frame *)&fr);
4724 +
4725 + }
4726 + break;
4727 + case CAPI_CONNECT_B3:
4728 + // then send a CONNECT_B3_RESP
4729 + memset(&CMSG2,0,sizeof(_cmsg));
4730 + CONNECT_B3_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4731 + CONNECT_B3_RESP_NCCI(&CMSG2) = CONNECT_B3_IND_NCCI(CMSG);
4732 + p->NCCI = CONNECT_B3_IND_NCCI(CMSG);
4733 + p->i->NCCI = p->NCCI;
4734 + CONNECT_B3_RESP_REJECT(&CMSG2) = 0;
4735 +
4736 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4737 + ast_log(LOG_ERROR,"error sending CONNECT_B3_RESP (error=%#x)\n",error);
4738 + return -1;
4739 + } else {
4740 + if (option_verbose > 5) {
4741 + if (capidebug)
4742 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_RESP (NCCI=%#x)\n",p->i->NCCI);
4743 + }
4744 + }
4745 + /* if (p->i->controller > 0) {
4746 + capi_controllers[p->i->controller]->nfreebchannels--;
4747 + } */
4748 + break;
4749 + case CAPI_CONNECT_B3_ACTIVE:
4750 +// ast_log(LOG_NOTICE,"CONNECT_B3_ACTIVE_IND NCCI=%#x\n",p->i->NCCI);
4751 + // then send a CONNECT_B3__ACTIVERESP
4752 +
4753 + CONNECT_B3_ACTIVE_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4754 + CONNECT_B3_ACTIVE_RESP_NCCI(&CMSG2) = p->i->NCCI;
4755 +
4756 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4757 + ast_log(LOG_ERROR,"error sending CONNECT_B3_ACTIVE_RESP (error=%#x)\n",error);
4758 + return -1;
4759 + } else {
4760 + if (option_verbose > 5) {
4761 + if (capidebug)
4762 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_B3_ACTIVE_RESP (NCCI=%#x)\n",p->i->NCCI);
4763 + }
4764 + }
4765 +
4766 + ast_mutex_lock(&contrlock);
4767 + if (p->i->controller > 0) {
4768 + capi_controllers[p->i->controller]->nfreebchannels--;
4769 + }
4770 + ast_mutex_unlock(&contrlock);
4771 +
4772 + p->i->state = CAPI_STATE_BCONNECTED;
4773 + capi_echo_canceller(p->c,EC_FUNCTION_ENABLE);
4774 + capi_detect_dtmf(p->c,1);
4775 +
4776 + if (p->i->earlyB3 != 1) {
4777 + ast_setstate(p->c,AST_STATE_UP);
4778 + fr.frametype = AST_FRAME_CONTROL;
4779 + fr.subclass = AST_CONTROL_ANSWER;
4780 + fr.datalen = 0;
4781 + return pipe_frame(p,(struct ast_frame *)&fr);
4782 + }
4783 + return 0;
4784 + break;
4785 + }
4786 + break;
4787 +
4788 + case CAPI_CONF:
4789 + switch (CMSG->Command) {
4790 + case CAPI_FACILITY:
4791 + if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 0x3) {
4792 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[1] == 0x2) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[2] == 0x0)) {
4793 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[4] == 0x0) && (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[5] == 0x0)) {
4794 + } else {
4795 + p->i->state = CAPI_STATE_BCONNECTED;
4796 + if (capidebug)
4797 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4798 + }
4799 + }
4800 + }
4801 + break;
4802 + case CAPI_DATA_B3:
4803 +// ast_log(LOG_NOTICE,"DATA_B3_CONF (NCCI %#x) for DATAHANDLE %#x\n",DATA_B3_CONF_NCCI(CMSG),DATA_B3_CONF_DATAHANDLE(CMSG));
4804 + break;
4805 + case CAPI_ALERT:
4806 +// ast_log(LOG_NOTICE,"ALERT_CONF (PLCI=%#x)\n",(int)ALERT_CONF_PLCI(CMSG));
4807 + p->i->state = CAPI_STATE_ALERTING;
4808 + if (p->c->_state == AST_STATE_RING) {
4809 + p->c->rings = 1;
4810 + }
4811 + break;
4812 + case CAPI_CONNECT:
4813 + if (option_verbose > 1) {
4814 + if (capidebug)
4815 + ast_verbose(VERBOSE_PREFIX_2 "received CONNECT_CONF PLCI = %#x INFO = %#x\n",(int)CONNECT_CONF_PLCI(CMSG),CONNECT_CONF_INFO(CMSG));
4816 + }
4817 + if (CONNECT_CONF_INFO(CMSG) == 0) {
4818 + p->i->PLCI = CONNECT_CONF_PLCI(CMSG);
4819 + p->PLCI = p->i->PLCI;
4820 + ast_setstate(p->c,AST_STATE_DIALING);
4821 + } else {
4822 + // here, something has to be done -->
4823 + fr.frametype = AST_FRAME_CONTROL;
4824 + fr.subclass = AST_CONTROL_BUSY;
4825 + fr.datalen = 0;
4826 + return pipe_frame(p,(struct ast_frame *)&fr);
4827 + }
4828 + break;
4829 + case CAPI_CONNECT_B3:
4830 +// ast_log(LOG_NOTICE,"received CONNECT_B3_CONF NCCI = %#x INFO = %#x\n",(int)CONNECT_B3_CONF_NCCI(CMSG),CONNECT_B3_CONF_INFO(CMSG));
4831 + if (CONNECT_B3_CONF_INFO(CMSG) == 0) {
4832 + p->i->NCCI = CONNECT_B3_CONF_NCCI(CMSG);
4833 + } else {
4834 + p->i->earlyB3 = -1;
4835 + p->i->doB3 = AST_CAPI_B3_DONT;
4836 + }
4837 + break;
4838 + }
4839 + break;
4840 + }
4841 + }
4842 +// ast_log(LOG_NOTICE,"returning\n");
4843 + return 0;
4844 +}
4845 +
4846 +static void capi_handle_msg(_cmsg *CMSG) {
4847 + struct ast_capi_pvt *i;
4848 + char *DNID;
4849 + char *CID;
4850 + char *msn;
4851 + _cmsg CMSG2;
4852 + MESSAGE_EXCHANGE_ERROR error;
4853 + int PLCI=0,NCCI;
4854 + int NPLAN=0;
4855 + int fds[2];
4856 + int controller=0;
4857 + char buffer[AST_MAX_EXTENSION];
4858 + struct capi_pipe *p;
4859 + char *magicmsn = "*\0";
4860 + char *emptyid = "\0";
4861 + char *emptydnid = "s\0";
4862 + long flags;
4863 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4864 + int deflect=0;
4865 +#endif
4866 +
4867 + switch (CMSG->Subcommand) {
4868 + // indication msgs
4869 + case CAPI_IND:
4870 +
4871 + switch (CMSG->Command) {
4872 + case CAPI_CONNECT: // only connect_ind are global (not channel specific)
4873 + if (capidebug)
4874 + ast_log(LOG_NOTICE,"%s\n",capi_cmsg2str(CMSG));
4875 + DNID = capi_number((char *)CONNECT_IND_CALLEDPARTYNUMBER(CMSG),1);
4876 + if ((DNID && *DNID == 0) || !DNID) {
4877 + DNID = emptydnid;
4878 + }
4879 + NPLAN = (CONNECT_IND_CALLINGPARTYNUMBER(CMSG)[1] & 0x70);
4880 + CID = capi_number((char *)CONNECT_IND_CALLINGPARTYNUMBER(CMSG),2);
4881 + PLCI = CONNECT_IND_PLCI(CMSG);
4882 + controller = PLCI & 0xff;
4883 + if (option_verbose > 1) {
4884 + if (capidebug)
4885 + ast_verbose(VERBOSE_PREFIX_2 "CONNECT_IND (PLCI=%#x,DID=%s,CID=%s,CIP=%#x,CONTROLLER=%#x)\n",PLCI,DNID,CID,CONNECT_IND_CIPVALUE(CMSG),controller);
4886 + }
4887 + if(CONNECT_IND_BCHANNELINFORMATION(CMSG))
4888 + if ((CONNECT_IND_BCHANNELINFORMATION(CMSG)[1] == 0x02) && (!capi_controllers[controller]->isdnmode)) {
4889 + // this is a call waiting CONNECT_IND with BChannelinformation[1] == 0x02
4890 + // meaning "no B or D channel for this call", since we can't do anything with call waiting now
4891 + // just reject it with "user busy"
4892 + // however...if we are a p2p BRI then the telco switch will allow us to choose the b channel
4893 + // so it will look like a callwaiting connect_ind to us
4894 +
4895 + ast_log(LOG_ERROR,"received a call waiting CONNECT_IND\n");
4896 +#ifndef CAPI_DEFLECT_ON_CIRCUITBUSY
4897 + CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4898 + CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
4899 + CONNECT_RESP_REJECT(&CMSG2) = 3; // user is busy
4900 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4901 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4902 + } else {
4903 + if (option_verbose > 5) {
4904 + if (capidebug)
4905 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
4906 + }
4907 + }
4908 + // no need to pipe this
4909 + PLCI = 0;
4910 + break;
4911 +#else
4912 + deflect = 1;
4913 +#endif
4914 + }
4915 + // well...somebody is calling us. let's set up a channel
4916 + ast_mutex_lock(&iflock);
4917 + i = iflist;
4918 + while(i) {
4919 + //XXX test this!
4920 + // has no owner
4921 + if ((!i->owner) && (i->incomingmsn != NULL)){
4922 + strncpy(buffer,i->incomingmsn,sizeof(buffer)-1);
4923 + msn = strtok(buffer,",");
4924 + while (msn != NULL) {
4925 +// ast_log(LOG_NOTICE,"msn=%s\n",msn);
4926 + if (DNID && ((!strcasecmp(msn,DNID)) ||
4927 + (i->isdnmode && (strlen(msn)<strlen(DNID)) && !strncasecmp(msn, DNID, strlen(msn))) || (!strncasecmp(msn,magicmsn,strlen(msn)))) &&
4928 + (i->controllers & (1 << controller))) {
4929 + if (CID != NULL) {
4930 + if(NPLAN == CAPI_ETSI_NPLAN_NATIONAL)
4931 + snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_national_prefix, CID);
4932 + else if(NPLAN == CAPI_ETSI_NPLAN_INTERNAT)
4933 + snprintf(i->cid, (sizeof(i->cid)-1), "%s%s%s", i->prefix, capi_international_prefix, CID);
4934 + else
4935 + snprintf(i->cid, (sizeof(i->cid)-1), "%s%s", i->prefix, CID);
4936 + } else
4937 + strncpy(i->cid,emptyid,sizeof(i->cid)-1);
4938 +
4939 + if (DNID != NULL)
4940 + strncpy(i->dnid,DNID,sizeof(i->dnid)-1);
4941 + else
4942 + strncpy(i->dnid,emptydnid,sizeof(i->dnid)-1);
4943 +
4944 + i->controller=controller;
4945 + i->PLCI = PLCI;
4946 + i->MessageNumber = CMSG->Messagenumber;
4947 + if (pipe(fds) == 0) {
4948 + if (option_verbose > 4) {
4949 + ast_verbose(VERBOSE_PREFIX_3 "creating pipe for PLCI=%#x msn = %s\n",PLCI,msn);
4950 + }
4951 + i->fd = fds[0];
4952 + flags = fcntl(i->fd,F_GETFL);
4953 + fcntl(i->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
4954 +// ast_log(LOG_NOTICE,"i->fd = %d\n",i->fd);
4955 + p = malloc(sizeof(struct capi_pipe));
4956 + memset(p, 0, sizeof(struct capi_pipe));
4957 + p->fd = fds[1];
4958 + flags = fcntl(i->fd,F_GETFL);
4959 + fcntl(p->fd,F_SETFL,flags | O_SYNC | O_DIRECT);
4960 +// ast_log(LOG_NOTICE,"p->fd = %d\n",p->fd);
4961 + p->PLCI = PLCI;
4962 + p->i = i;
4963 + ast_mutex_init(&(p->lock));
4964 + i->mypipe = p;
4965 + if (i->isdnmode) {
4966 + p->c = capi_new(i,AST_STATE_DOWN);
4967 + i->state = CAPI_STATE_DID;
4968 + } else {
4969 + p->c = capi_new(i,AST_STATE_RING);
4970 + }
4971 + p->next = pipelist;
4972 + pipelist = p;
4973 + // hmmm....
4974 + ast_mutex_unlock(&iflock);
4975 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
4976 + if ((deflect == 1) && (i->deflect2)) {
4977 + capi_deflect(p->c,i->deflect2);
4978 + }
4979 +#endif
4980 + return;
4981 + } else {
4982 + ast_log(LOG_ERROR,"creating pipe for PLCI=%#x failed\n",PLCI);
4983 + }
4984 + break;
4985 + } // if strcasecmp
4986 + msn = strtok(NULL,",");
4987 + } // while strtok
4988 + } // if
4989 + i = i->next;
4990 + } // while interface list
4991 + ast_mutex_unlock(&iflock); // obviously we are not called...so tell capi to ignore this call
4992 + if (capidebug) {
4993 + ast_log(LOG_ERROR,"did not find device for msn = %s\n",DNID);
4994 + }
4995 + CONNECT_RESP_HEADER(&CMSG2, ast_capi_ApplID, CMSG->Messagenumber, 0);
4996 + CONNECT_RESP_PLCI(&CMSG2) = CONNECT_IND_PLCI(CMSG);
4997 + CONNECT_RESP_REJECT(&CMSG2) = 1; // ignore
4998 + if ((error = _capi_put_cmsg(&CMSG2)) != 0) {
4999 + ast_log(LOG_ERROR,"error sending CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
5000 + } else {
5001 + if (option_verbose > 5) {
5002 + if (capidebug)
5003 + ast_verbose(VERBOSE_PREFIX_4 "sent CONNECT_RESP for PLCI = %#x\n",(int)CONNECT_IND_PLCI(CMSG));
5004 + }
5005 + }
5006 + ast_mutex_lock(&pipelock);
5007 + if (pipelist == NULL) {
5008 + capi_last_plci = PLCI;
5009 + }
5010 + ast_mutex_unlock(&pipelock);
5011 + // no need to pipe this
5012 + PLCI = 0;
5013 +// ast_mutex_unlock(&iflock);
5014 +// return;
5015 + break;
5016 + case CAPI_FACILITY:
5017 + PLCI = FACILITY_IND_PLCI(CMSG) & 0xffff; // this is for you eicon
5018 + if (option_verbose > 3) {
5019 + if (capidebug)
5020 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5021 + }
5022 +// ast_log(LOG_ERROR,"FACILITY_IND PLCI=%#x\n",PLCI);
5023 + break;
5024 + case CAPI_INFO:
5025 + PLCI = INFO_IND_PLCI(CMSG);
5026 + if (option_verbose > 3) {
5027 + if (capidebug)
5028 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5029 + }
5030 +// ast_log(LOG_ERROR,"INFO_IND PLCI=%#x INFO# = %#x\n",PLCI,INFO_IND_INFONUMBER(CMSG));
5031 + break;
5032 + case CAPI_CONNECT_ACTIVE:
5033 + PLCI = CONNECT_ACTIVE_IND_PLCI(CMSG);
5034 + if (option_verbose > 3) {
5035 + if (capidebug)
5036 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5037 + }
5038 +// ast_log(LOG_ERROR,"CONNECT_ACTIVE_IND PLCI=%#x\n",PLCI);
5039 + break;
5040 + case CAPI_CONNECT_B3:
5041 + NCCI = CONNECT_B3_IND_NCCI(CMSG);
5042 + PLCI = (NCCI << 16) >> 16;
5043 + if (option_verbose > 3) {
5044 + if (capidebug)
5045 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5046 + }
5047 +// ast_log(LOG_ERROR,"CONNECT_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
5048 + break;
5049 + case CAPI_CONNECT_B3_ACTIVE:
5050 + NCCI = CONNECT_B3_IND_NCCI(CMSG);
5051 + PLCI = (NCCI << 16) >> 16;
5052 + if (option_verbose > 3) {
5053 + if (capidebug)
5054 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5055 + }
5056 +// ast_log(LOG_ERROR,"CONNECT_B3_ACTIVE_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
5057 + break;
5058 + case CAPI_DATA_B3:
5059 + NCCI = DATA_B3_IND_NCCI(CMSG);
5060 + PLCI = (NCCI << 16) >> 16;
5061 +// ast_log(LOG_ERROR,"DATA_B3_IND NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
5062 + break;
5063 + case CAPI_DISCONNECT_B3:
5064 + NCCI = DISCONNECT_B3_IND_NCCI(CMSG);
5065 + PLCI = (NCCI << 16) >> 16;
5066 + if (option_verbose > 1) {
5067 + if (capidebug)
5068 + ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_B3_IND NCCI=%#x\n",NCCI);
5069 + }
5070 + break;
5071 + case CAPI_DISCONNECT:
5072 + PLCI = DISCONNECT_IND_PLCI(CMSG);
5073 + if (option_verbose > 1) {
5074 + if (capidebug)
5075 + ast_verbose(VERBOSE_PREFIX_2 "DISCONNECT_IND PLCI=%#x REASON=%#x\n",PLCI,DISCONNECT_IND_REASON(CMSG));
5076 + }
5077 + break;
5078 + default:
5079 + ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
5080 + }
5081 + break;
5082 + // confirmation msgs
5083 + case CAPI_CONF:
5084 + switch (CMSG->Command) {
5085 + case CAPI_FACILITY:
5086 + NCCI = FACILITY_CONF_NCCI(CMSG);
5087 + PLCI = (NCCI << 16) >> 16;
5088 + if (option_verbose > 2) {
5089 + if (FACILITY_CONF_FACILITYSELECTOR(CMSG) == 6) {
5090 + if (FACILITY_CONF_INFO(CMSG))
5091 + ast_verbose (VERBOSE_PREFIX_3 "Error setting up echo canceller (PLCI=%#x, Info=%#04x)\n", PLCI, FACILITY_CONF_INFO(CMSG));
5092 + else
5093 + ast_verbose (VERBOSE_PREFIX_3 "Echo canceller successfully set up (PLCI=%#x)\n",PLCI);
5094 + }
5095 + }
5096 + if (option_verbose > 3) {
5097 + if (capidebug)
5098 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5099 + }
5100 +// ast_log(LOG_ERROR,"FACILITY_CONF NCCI=%#x INFO=%#x\n",(int)FACILITY_CONF_NCCI(CMSG),FACILITY_CONF_INFO(CMSG));
5101 + break;
5102 + case CAPI_INFO:
5103 + PLCI = INFO_CONF_PLCI(CMSG);
5104 +// ast_log(LOG_ERROR,"INFO_CONF PLCI=%#x INFO=%#x\n",PLCI,INFO_CONF_INFO(CMSG));
5105 + break;
5106 + case CAPI_CONNECT:
5107 + PLCI = CONNECT_CONF_PLCI(CMSG);
5108 + if (option_verbose > 3) {
5109 + if (capidebug)
5110 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5111 + }
5112 +// ast_log(LOG_ERROR,"CONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
5113 + break;
5114 + case CAPI_DISCONNECT:
5115 + PLCI = DISCONNECT_CONF_PLCI(CMSG);
5116 + if (option_verbose > 3) {
5117 + if (capidebug)
5118 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5119 + }
5120 +// ast_log(LOG_ERROR,"DISCONNECT_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,DISCONNECT_CONF_INFO(CMSG),CMSG->Messagenumber);
5121 + break;
5122 + case CAPI_DISCONNECT_B3:
5123 + NCCI = DISCONNECT_B3_CONF_NCCI(CMSG);
5124 + PLCI = (NCCI << 16) >> 16;
5125 + if (option_verbose > 3) {
5126 + if (capidebug)
5127 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5128 + }
5129 +// ast_log(LOG_ERROR,"DISCONNECT_B3_CONF NCCI=%#x INFO=%#x MN=%#x\n",NCCI,DISCONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
5130 + break;
5131 + case CAPI_CONNECT_B3:
5132 + NCCI = CONNECT_B3_CONF_NCCI(CMSG);
5133 + PLCI = (NCCI << 16) >> 16;
5134 + if (option_verbose > 3) {
5135 + if (capidebug)
5136 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5137 + }
5138 +// ast_log(LOG_ERROR,"CONNECT_B3_CONF PLCI=%#x INFO=%#x MN=%#x\n",PLCI,CONNECT_B3_CONF_INFO(CMSG),CMSG->Messagenumber);
5139 + break;
5140 + case CAPI_ALERT:
5141 + PLCI = ALERT_CONF_PLCI(CMSG);
5142 + if (option_verbose > 3) {
5143 + if (capidebug)
5144 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5145 + }
5146 +// ast_log(LOG_ERROR,"ALERT_CONF PLCI=%#x\n",PLCI);
5147 + break;
5148 + case CAPI_DATA_B3:
5149 + NCCI = DATA_B3_CONF_NCCI(CMSG);
5150 + PLCI = (NCCI << 16) >> 16;
5151 + if (option_verbose > 5) {
5152 + if (capidebug)
5153 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(CMSG));
5154 + }
5155 +// ast_log(LOG_ERROR,"DATA_B3_CONF NCCI=%#x PLCI=%#x\n",NCCI,PLCI);
5156 + break;
5157 + default:
5158 + ast_log(LOG_ERROR,"Command.Subcommand = %#x.%#x\n",CMSG->Command,CMSG->Subcommand);
5159 + }
5160 + break;
5161 + }
5162 + if (PLCI > 0) {
5163 + pipe_msg(PLCI,CMSG);
5164 + }
5165 +
5166 +}
5167 +
5168 +// module stuff, monitor...
5169 +
5170 +static void *do_monitor(void *data) {
5171 + unsigned int Info;
5172 + _cmsg *monCMSG;
5173 + for (;;) {
5174 +/*
5175 + if (ast_mutex_lock(&monlock)) {
5176 + ast_log(LOG_ERROR,"Unable to get monitor lock!\n");
5177 + return NULL;
5178 + }
5179 + // do some nifty stuff
5180 + ast_mutex_unlock(&monlock);
5181 +*/
5182 + monCMSG = malloc(sizeof(_cmsg));
5183 + memset(monCMSG,0,sizeof(_cmsg));
5184 + switch(Info = check_wait_get_cmsg(monCMSG)) {
5185 + case 0x0000:
5186 + if (option_verbose > 8) {
5187 + if (capidebug)
5188 + ast_verbose(VERBOSE_PREFIX_3 "%s\n",capi_cmsg2str(monCMSG));
5189 + }
5190 + capi_handle_msg(monCMSG);
5191 + break;
5192 + case 0x1104:
5193 + // CAPI queue is empty
5194 + break;
5195 + default:
5196 + // something is wrong!
5197 + break;
5198 + } //switch
5199 + free(monCMSG);
5200 + } // for
5201 + // never reached
5202 + return NULL;
5203 +}
5204 +
5205 +#ifdef CAPI_GAIN
5206 +static void capi_gains(struct ast_capi_gains *g,float rxgain,float txgain) {
5207 + int i=0;
5208 + int x=0;
5209 + if (rxgain != 1.0) {
5210 + for (i=0;i<256;i++) {
5211 + x = (int)(((float)capiXLAW2INT(i)) * rxgain);
5212 + if (x > 32767) x = 32767;
5213 + if (x < -32767) x = -32767;
5214 + g->rxgains[i] = capiINT2XLAW(x);
5215 + }
5216 + } else {
5217 + for (i=0;i<256;i++) {
5218 + g->rxgains[i] = i;
5219 + }
5220 + }
5221 + if (txgain != 1.0) {
5222 + for (i=0;i<256;i++) {
5223 + x = (int)(((float)capiXLAW2INT(i)) * txgain);
5224 + if (x > 32767) x = 32767;
5225 + if (x < -32767) x = -32767;
5226 + g->txgains[i] = capiINT2XLAW(x);
5227 + }
5228 + } else {
5229 + for (i=0;i<256;i++) {
5230 + g->txgains[i] = i;
5231 + }
5232 + }
5233 +
5234 +}
5235 +#endif
5236 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
5237 +int mkif(char *incomingmsn,char *context,char *controllerstr,int devices,int softdtmf,int echocancel,int ecoption,int ectail, char *prefix, int isdnmode, int es,float rxgain,float txgain, char *deflect2, char *accountcode, unsigned int callgroup, unsigned int group) {
5238 +#else
5239 +int mkif(char *incomingmsn,char *context,char *controllerstr,int devices,int softdtmf,int echocancel,int ecoption,int ectail, char *prefix, int isdnmode, int es,float rxgain,float txgain, char *accountcode, unsigned int callgroup, unsigned int group) {
5240 +#endif
5241 + struct ast_capi_pvt *tmp;
5242 + int i=0;
5243 + char buffer[100];
5244 + char *contr;
5245 + unsigned long contrmap=0;
5246 +
5247 + for (i=0;i<devices;i++) {
5248 + tmp = malloc(sizeof(struct ast_capi_pvt));
5249 + memset(tmp, 0, sizeof(struct ast_capi_pvt));
5250 + if (tmp) {
5251 + ast_mutex_init(&(tmp->lock));
5252 + strncpy(tmp->context, context, sizeof(tmp->context)-1);
5253 + strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
5254 + strncpy(tmp->prefix, prefix, sizeof(tmp->prefix)-1);
5255 + strncpy(tmp->accountcode, accountcode, sizeof(tmp->accountcode)-1);
5256 +
5257 + strncpy(buffer,controllerstr,sizeof(buffer)-1);
5258 + contr = strtok(buffer,",");
5259 + while (contr != NULL) {
5260 + contrmap |= (1 << atoi(contr));
5261 + if (capi_controllers[atoi(contr)]) {
5262 + capi_controllers[atoi(contr)]->isdnmode = isdnmode;
5263 + // ast_log(LOG_NOTICE, "contr %d isdnmode %d\n",atoi(contr),isdnmode);
5264 + }
5265 + contr = strtok(NULL,",");
5266 + }
5267 + tmp->controllers = contrmap;
5268 + capi_used_controllers |= contrmap;
5269 + tmp->controller = 0;
5270 + tmp->CLIR = 0;
5271 + tmp->earlyB3 = -1;
5272 + tmp->onholdPLCI = 0;
5273 + tmp->doEC = echocancel;
5274 + tmp->ecOption = ecoption;
5275 + tmp->ecTail = ectail;
5276 + tmp->isdnmode = isdnmode;
5277 + tmp->doES = es;
5278 + tmp->callgroup = callgroup;
5279 + tmp->group = group;
5280 +#ifdef CAPI_ES
5281 +#endif
5282 +#ifdef CAPI_GAIN
5283 + tmp->rxgain = rxgain;
5284 + tmp->txgain = txgain;
5285 + capi_gains(&tmp->g,rxgain,txgain);
5286 +#endif
5287 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
5288 + strncpy(tmp->deflect2, deflect2, sizeof(tmp->deflect2)-1);
5289 +#endif
5290 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
5291 + if (softdtmf == 1) {
5292 +#endif
5293 + tmp->doDTMF = 1;
5294 +#ifndef CAPI_FORCE_SOFTWARE_DTMF
5295 + } else {
5296 + tmp->doDTMF = 0;
5297 + }
5298 +#endif
5299 + tmp->next = iflist; // prepend
5300 + iflist = tmp;
5301 + // ast_log(LOG_NOTICE, "ast_capi_pvt(%s,%s,%#x,%d) (%d,%d,%d) (%d)(%f/%f) %d\n",tmp->incomingmsn,tmp->context,(int)tmp->controllers,devices,tmp->doEC,tmp->ecOption,tmp->ecTail,tmp->doES,tmp->rxgain,tmp->txgain,callgroup);
5302 + if (option_verbose > 2) {
5303 + ast_verbose(VERBOSE_PREFIX_2 "ast_capi_pvt(%s,%s,%d,%d) (%d,%d,%d)\n",tmp->incomingmsn,tmp->context,tmp->controller,devices,tmp->doEC,tmp->ecOption,tmp->ecTail);
5304 + }
5305 +
5306 + } else {
5307 + return -1;
5308 + }
5309 + }
5310 + return 0;
5311 +}
5312 +
5313 +void supported_sservices(struct ast_capi_controller *cp) {
5314 + MESSAGE_EXCHANGE_ERROR error;
5315 + _cmsg CMSG,CMSG2;
5316 + struct timeval tv;
5317 + char fac[20];
5318 +
5319 + FACILITY_REQ_HEADER(&CMSG, ast_capi_ApplID, ast_capi_MessageNumber++, 0);
5320 + FACILITY_REQ_CONTROLLER(&CMSG) = cp->controller;
5321 + FACILITY_REQ_FACILITYSELECTOR(&CMSG) = 0x0003; // sservices
5322 + fac[0] = 3;
5323 + fac[1] = 0;
5324 + fac[2] = 0;
5325 + fac[3] = 0;
5326 + FACILITY_REQ_FACILITYREQUESTPARAMETER(&CMSG) = (unsigned char *)&fac;
5327 + if ((error= _capi_put_cmsg(&CMSG)) != 0) {
5328 + ast_log(LOG_ERROR,"error sending FACILITY_REQ (error=%#x)\n",error);
5329 + } else {
5330 + if (option_verbose > 5) {
5331 + ast_verbose(VERBOSE_PREFIX_4 "sent FACILITY_REQ (CONTROLLER=%#x)\n",cp->controller);
5332 + }
5333 + }
5334 +
5335 + tv.tv_sec = 1;
5336 + tv.tv_usec = 0;
5337 + for (;;){
5338 + error = capi20_waitformessage(ast_capi_ApplID,&tv);
5339 + error = capi_get_cmsg(&CMSG2,ast_capi_ApplID);
5340 +// error = check_wait_get_cmsg(&CMSG2);
5341 + if (error == 0) {
5342 + if (IS_FACILITY_CONF(&CMSG2)) {
5343 + if (option_verbose > 5) {
5344 + ast_verbose(VERBOSE_PREFIX_4 "FACILITY_CONF INFO = %#x\n",FACILITY_CONF_INFO(&CMSG2));
5345 + }
5346 + break;
5347 + }
5348 + }
5349 + }
5350 + // parse supported sservices
5351 + if (FACILITY_CONF_FACILITYSELECTOR(&CMSG2) == 0x0003) {
5352 + // success
5353 + if (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[4] == 0) {
5354 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 1) == 1) {
5355 + cp->holdretrieve = 1;
5356 + if (option_verbose > 3)
5357 + ast_verbose(VERBOSE_PREFIX_4 "HOLD/RETRIEVE\n");
5358 + } else {
5359 + cp->holdretrieve = 0;
5360 + }
5361 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 2) >> 1) == 1) {
5362 + cp->terminalportability = 1;
5363 + if (option_verbose > 3)
5364 + ast_verbose(VERBOSE_PREFIX_4 "TERMINAL PORTABILITY\n");
5365 + } else {
5366 + cp->terminalportability = 0;
5367 + }
5368 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 4) >> 2) == 1) {
5369 + cp->ECT = 1;
5370 + if (option_verbose > 3)
5371 + ast_verbose(VERBOSE_PREFIX_4 "ECT\n");
5372 + } else {
5373 + cp->ECT = 0;
5374 + }
5375 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 8) >> 3) == 1) {
5376 + cp->threePTY = 1;
5377 + if (option_verbose > 3)
5378 + ast_verbose(VERBOSE_PREFIX_4 "3PTY\n");
5379 + } else {
5380 + cp->threePTY = 0;
5381 + }
5382 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 16) >> 4) == 1) {
5383 + cp->CF = 1;
5384 + if (option_verbose > 3)
5385 + ast_verbose(VERBOSE_PREFIX_4 "CF\n");
5386 + } else {
5387 + cp->CF = 0;
5388 + }
5389 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 32) >> 5) == 1) {
5390 + cp->CD = 1;
5391 + if (option_verbose > 3)
5392 + ast_verbose(VERBOSE_PREFIX_4 "CD\n");
5393 + } else {
5394 + cp->CD = 0;
5395 + }
5396 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 64) >> 6) == 1) {
5397 + cp->MCID = 1;
5398 + if (option_verbose > 3)
5399 + ast_verbose(VERBOSE_PREFIX_4 "MCID\n");
5400 + } else {
5401 + cp->MCID = 0;
5402 + }
5403 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[6] & 128) >> 7) == 1) {
5404 + cp->CCBS = 1;
5405 + if (option_verbose > 3)
5406 + ast_verbose(VERBOSE_PREFIX_4 "CCBS\n");
5407 + } else {
5408 + cp->CCBS = 0;
5409 + }
5410 + if ((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 1) == 1) {
5411 + cp->MWI = 1;
5412 + if (option_verbose > 3)
5413 + ast_verbose(VERBOSE_PREFIX_4 "MWI\n");
5414 + } else {
5415 + cp->MWI = 0;
5416 + }
5417 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 2) >> 1) == 1) {
5418 + cp->CCNR = 1;
5419 + if (option_verbose > 3)
5420 + ast_verbose(VERBOSE_PREFIX_4 "CCNR\n");
5421 + } else {
5422 + cp->CCNR = 0;
5423 + }
5424 + if (((FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[7] & 4) >> 2) == 1) {
5425 + cp->CONF = 1;
5426 + if (option_verbose > 3)
5427 + ast_verbose(VERBOSE_PREFIX_4 "CONF\n");
5428 + } else {
5429 + cp->CONF = 0;
5430 + }
5431 + } else {
5432 + ast_log(LOG_NOTICE,"supplementary services info = %#x\n",(short)FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG2)[1]);
5433 + }
5434 + } else {
5435 + ast_log(LOG_NOTICE,"unexpected FACILITY_SELECTOR = %#x\n",FACILITY_CONF_FACILITYSELECTOR(&CMSG2));
5436 + }
5437 +}
5438 +
5439 +static int capi_info(int fd, int argc, char *argv[])
5440 +{
5441 + int i=0;
5442 + if (argc != 2)
5443 + return RESULT_SHOWUSAGE;
5444 + for (i=1;i<=capi_num_controllers;i++) {
5445 + ast_mutex_lock(&contrlock);
5446 + if (capi_controllers[i] != NULL) {
5447 + ast_cli(fd,"Contr%d: %d B channels total, %d B channels free.\n",i,capi_controllers[i]->nbchannels,capi_controllers[i]->nfreebchannels);
5448 + }
5449 + ast_mutex_unlock(&contrlock);
5450 + }
5451 + return RESULT_SUCCESS;
5452 +}
5453 +
5454 +static int capi_do_debug(int fd, int argc, char *argv[])
5455 +{
5456 + if (argc != 2)
5457 + return RESULT_SHOWUSAGE;
5458 + capidebug = 1;
5459 + ast_cli(fd, "CAPI Debugging Enabled\n");
5460 + return RESULT_SUCCESS;
5461 +}
5462 +
5463 +static int capi_no_debug(int fd, int argc, char *argv[])
5464 +{
5465 + if (argc != 3)
5466 + return RESULT_SHOWUSAGE;
5467 + capidebug = 0;
5468 + ast_cli(fd, "CAPI Debugging Disabled\n");
5469 + return RESULT_SUCCESS;
5470 +}
5471 +
5472 +static char info_usage[] =
5473 +"Usage: capi info\n"
5474 +" Show info about B channels.\n";
5475 +
5476 +static char debug_usage[] =
5477 +"Usage: capi debug\n"
5478 +" Enables dumping of CAPI packets for debugging purposes\n";
5479 +
5480 +static char no_debug_usage[] =
5481 +"Usage: capi no debug\n"
5482 +" Disables dumping of CAPI packets for debugging purposes\n";
5483 +
5484 +static struct ast_cli_entry cli_info =
5485 + { { "capi", "info", NULL }, capi_info, "Show CAPI info", info_usage };
5486 +static struct ast_cli_entry cli_debug =
5487 + { { "capi", "debug", NULL }, capi_do_debug, "Enable CAPI debugging", debug_usage };
5488 +static struct ast_cli_entry cli_no_debug =
5489 + { { "capi", "no", "debug", NULL }, capi_no_debug, "Disable CAPI debugging", no_debug_usage };
5490 +
5491 +static const struct ast_channel_tech capi_tech = {
5492 + .type = type,
5493 + .description = tdesc,
5494 +#ifdef CAPI_ULAW
5495 + .capabilities = AST_FORMAT_ULAW,
5496 +#else
5497 + .capabilities = AST_FORMAT_ALAW,
5498 +#endif
5499 + .requester = capi_request,
5500 + .send_digit = capi_send_digit,
5501 + .send_text = NULL,
5502 + .call = capi_call,
5503 + .hangup = capi_hangup,
5504 + .answer = capi_answer,
5505 + .read = capi_read,
5506 + .write = capi_write,
5507 + .bridge = NULL,
5508 + .exception = NULL,
5509 + .indicate = capi_indicate,
5510 + .fixup = capi_fixup,
5511 + .setoption = NULL,
5512 +};
5513 +
5514 +int load_module(void)
5515 +{
5516 + struct ast_config *cfg;
5517 + struct ast_variable *v;
5518 + char *config = "capi.conf";
5519 + char incomingmsn[AST_MAX_EXTENSION]="";
5520 + char context[AST_MAX_EXTENSION]="";
5521 + char prefix[AST_MAX_EXTENSION]="";
5522 + char accountcode[20]="";
5523 + char *empty = "\0";
5524 + char deflect2[AST_MAX_EXTENSION]="";
5525 + char controllerstr[AST_MAX_EXTENSION]="";
5526 + int res = 0;
5527 + int controller=0;
5528 + int softdtmf=0;
5529 + int echocancel=1;
5530 + int ecoption=EC_OPTION_DISABLE_G165;
5531 + int ectail=EC_DEFAULT_TAIL;
5532 + int es=0;
5533 + float rxgain = 1.0;
5534 + float txgain = 1.0;
5535 + int isdnmode = 0;
5536 + unsigned int callgroup=0;
5537 + unsigned int group=0;
5538 + struct ast_capi_controller *cp;
5539 +
5540 + cfg = ast_config_load(config);
5541 +
5542 + /* We *must* have a config file otherwise stop immediately, well no... */
5543 + if (!cfg) {
5544 + ast_log(LOG_ERROR, "Unable to load config %s, CAPI disabled\n", config);
5545 + return 0;
5546 + }
5547 + if (ast_mutex_lock(&iflock)) {
5548 + ast_log(LOG_ERROR, "Unable to lock interface list???\n");
5549 + return -1;
5550 + }
5551 +
5552 + strncpy(capi_national_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
5553 + strncpy(capi_international_prefix, AST_CAPI_NATIONAL_PREF, sizeof(capi_national_prefix)-1);
5554 + v = ast_variable_browse(cfg, "general");
5555 + while(v) {
5556 + if (!strcasecmp(v->name, "nationalprefix")) {
5557 + strncpy(capi_national_prefix, v->value, sizeof(capi_national_prefix)-1);
5558 + } else if (!strcasecmp(v->name, "internationalprefix")) {
5559 + strncpy(capi_international_prefix, v->value, sizeof(capi_international_prefix)-1);
5560 + } else if (!strcasecmp(v->name, "rxgain")) {
5561 + if (sscanf(v->value,"%f",&rxgain) != 1) {
5562 + ast_log(LOG_ERROR,"invalid rxgain\n");
5563 + }
5564 + } else if (!strcasecmp(v->name, "txgain")) {
5565 + if (sscanf(v->value,"%f",&txgain) != 1) {
5566 + ast_log(LOG_ERROR,"invalid txgain\n");
5567 + }
5568 + }
5569 + v = v->next;
5570 + }
5571 +
5572 +
5573 +
5574 +
5575 + if (capi20_isinstalled() != 0) {
5576 + ast_log(LOG_WARNING,"CAPI not installed, CAPI disabled!\n");
5577 + return 0;
5578 + }
5579 +
5580 + if (capi20_register(AST_CAPI_BCHANS,AST_CAPI_MAX_B3_BLOCKS,AST_CAPI_MAX_B3_BLOCK_SIZE,&ast_capi_ApplID) != 0) {
5581 + ast_log(LOG_NOTICE,"unable to register application at CAPI!\n");
5582 + return -1;
5583 + }
5584 +
5585 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5586 + if (capi20_get_profile(0,&profile) != 0) {
5587 +#else
5588 + if (capi20_get_profile(0,(unsigned char *)&profile) != 0) {
5589 +#endif
5590 + ast_log(LOG_NOTICE,"unable to get CAPI profile!\n");
5591 + return -1;
5592 + } else {
5593 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5594 + capi_num_controllers = profile.wCtlr;
5595 +#else
5596 + capi_num_controllers = profile.ncontrollers;
5597 +#endif
5598 + if (option_verbose > 3)
5599 + ast_verbose(VERBOSE_PREFIX_3 "This box has %d capi controller(s).\n",capi_num_controllers);
5600 + for (controller=1;controller<=capi_num_controllers;controller++) {
5601 +
5602 + memset(&profile,0,sizeof(profile));
5603 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5604 + capi20_get_profile(controller,&profile);
5605 +#else
5606 + capi20_get_profile(controller,(unsigned char *)&profile);
5607 +#endif
5608 + cp = malloc(sizeof(struct ast_capi_controller));
5609 + cp->controller = controller;
5610 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5611 + cp->nbchannels = profile.wNumBChannels;
5612 + cp->nfreebchannels = profile.wNumBChannels;
5613 + if (profile.dwGlobalOptions & CAPI_PROFILE_DTMF_SUPPORT) {
5614 +#else
5615 + cp->nbchannels = profile.nbchannels;
5616 + cp->nfreebchannels = profile.nbchannels;
5617 + if ((profile.globaloptions & 8) >> 3 == 1) {
5618 +#endif
5619 + if (option_verbose > 3)
5620 + ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports DTMF\n",controller);
5621 + cp->dtmf = 1;
5622 + } else {
5623 + cp->dtmf = 0;
5624 + }
5625 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5626 + if (profile.dwGlobalOptions & CAPI_PROFILE_ECHO_CANCELLATION) {
5627 +#else
5628 + if (profile.globaloptions2 & 1) {
5629 +#endif
5630 + if (option_verbose > 3)
5631 + ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports echo cancellation\n",controller);
5632 + cp->echocancel = 1;
5633 + } else {
5634 + cp->echocancel = 0;
5635 + }
5636 +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
5637 + if (profile.dwGlobalOptions & CAPI_PROFILE_SUPPLEMENTARY_SERVICES) {
5638 +#else
5639 + if ((profile.globaloptions & 16) >> 4 == 1) {
5640 +#endif
5641 + cp->sservices = 1;
5642 + } else {
5643 + cp->sservices = 0;
5644 + }
5645 + capi_controllers[controller] = cp;
5646 + if (cp->sservices == 1) {
5647 + if (option_verbose > 3)
5648 + ast_verbose(VERBOSE_PREFIX_3 "CAPI/contr%d supports supplementary services\n",controller);
5649 + supported_sservices(cp);
5650 + }
5651 + }
5652 + }
5653 +
5654 + v = ast_variable_browse(cfg, "interfaces");
5655 + while(v) {
5656 + /* Create the interface list */
5657 + if (!strcasecmp(v->name, "devices")) {
5658 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
5659 + if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,deflect2,accountcode,callgroup, group)) {
5660 +#else
5661 + if (mkif(incomingmsn,context,controllerstr,atoi(v->value),softdtmf,echocancel,ecoption,ectail, prefix, isdnmode, es,rxgain,txgain,accountcode,callgroup, group)) {
5662 +#endif
5663 + ast_log(LOG_ERROR,"Error creating interface list\n");
5664 + return -1;
5665 + }
5666 + es=0;
5667 + strncpy(deflect2, empty, sizeof(deflect2)-1);
5668 + } else if (!strcasecmp(v->name, "context")) {
5669 + strncpy(context, v->value, sizeof(context)-1);
5670 + } else if (!strcasecmp(v->name, "incomingmsn")) {
5671 + strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
5672 + } else if (!strcasecmp(v->name, "controller")) {
5673 + strncpy(controllerstr, v->value, sizeof(controllerstr)-1);
5674 + } else if (!strcasecmp(v->name, "softdtmf")) {
5675 + softdtmf = atoi(v->value);
5676 + } else if (!strcasecmp(v->name, "echosquelch")) {
5677 + es = atoi(v->value);
5678 + } else if (!strcasecmp(v->name, "callgroup")) {
5679 + callgroup = ast_get_group(v->value);
5680 + } else if (!strcasecmp(v->name, "group")) {
5681 + group = ast_get_group(v->value);
5682 + } else if (!strcasecmp(v->name, "deflect")) {
5683 + strncpy(deflect2, v->value, sizeof(deflect2)-1);
5684 + } else if (!strcasecmp(v->name, "rxgain")) {
5685 + if (sscanf(v->value,"%f",&rxgain) != 1) {
5686 + ast_log(LOG_ERROR,"invalid rxgain\n");
5687 + }
5688 + } else if (!strcasecmp(v->name, "txgain")) {
5689 + if (sscanf(v->value,"%f",&txgain) != 1) {
5690 + ast_log(LOG_ERROR,"invalid txgain\n");
5691 + }
5692 + } else if (!strcasecmp(v->name, "echocancel")) {
5693 + if (!strcasecmp(v->value, "yes") || !strcasecmp(v->value, "1") || !strcasecmp(v->value, "on")) {
5694 + echocancel=1;
5695 + ecoption=EC_OPTION_DISABLE_G165;
5696 + }
5697 + else if (!strcasecmp(v->value, "no") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "off")) {
5698 + echocancel=0;
5699 + ecoption=0;
5700 + }
5701 + else if (!strcasecmp(v->value, "g165") || !strcasecmp(v->value, "g.165")) {
5702 + echocancel=1;
5703 + ecoption=EC_OPTION_DISABLE_G165;
5704 + }
5705 + else if (!strcasecmp(v->value, "g164") || !strcasecmp(v->value, "g.164")) {
5706 + echocancel=1;
5707 + ecoption=EC_OPTION_DISABLE_G164_OR_G165;
5708 + }
5709 + else if (!strcasecmp(v->value, "force")) {
5710 + echocancel=1;
5711 + ecoption=EC_OPTION_DISABLE_NEVER;
5712 + }
5713 + else {
5714 + ast_log(LOG_ERROR,"Unknown echocancel parameter \"%s\" -- ignoring\n",v->value);
5715 + }
5716 + } else if (!strcasecmp(v->name, "echotail")) {
5717 + ectail = atoi(v->value);
5718 + if (ectail > 255)
5719 + ectail = 255;
5720 + } else if (!strcasecmp(v->name, "prefix")) {
5721 + strncpy(prefix, v->value, sizeof(prefix)-1);
5722 + } else if (!strcasecmp(v->name, "accountcode")) {
5723 + strncpy(accountcode, v->value, sizeof(accountcode)-1);
5724 + } else if (!strcasecmp(v->name, "isdnmode")) {
5725 + if (!strcasecmp(v->value, "ptp") || !strcasecmp(v->value, "1"))
5726 + isdnmode = 1;
5727 + else if (!strcasecmp(v->value, "ptm") || !strcasecmp(v->value, "0") || !strcasecmp(v->value, "ptmp"))
5728 + isdnmode = 0;
5729 + else
5730 + ast_log(LOG_ERROR,"Unknown isdnmode parameter \"%s\" -- ignoring\n",v->value);
5731 +
5732 + }
5733 +
5734 + v = v->next;
5735 + }
5736 + ast_config_destroy(cfg);
5737 +
5738 + for (controller=1;controller<=capi_num_controllers;controller++) {
5739 + if (capi_used_controllers & (1 << controller)) {
5740 + if (ListenOnController(ALL_SERVICES,controller) != 0) {
5741 + ast_log(LOG_ERROR,"Unable to listen on contr%d\n",controller);
5742 + } else {
5743 + if (option_verbose > 2)
5744 + ast_verbose(VERBOSE_PREFIX_3 "listening on contr%d CIPmask = %#x\n",controller,ALL_SERVICES);
5745 + }
5746 + } else {
5747 + ast_log(LOG_WARNING,"Unused contr%d\n",controller);
5748 + }
5749 + }
5750 +
5751 +
5752 + ast_mutex_unlock(&iflock);
5753 +
5754 + if (ast_channel_register(&capi_tech)) {
5755 + ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
5756 + unload_module();
5757 + return -1;
5758 + }
5759 +
5760 + ast_cli_register(&cli_info);
5761 + ast_cli_register(&cli_debug);
5762 + ast_cli_register(&cli_no_debug);
5763 +
5764 + if (ast_mutex_lock(&monlock)) {
5765 + ast_log(LOG_WARNING,"Unable to get monitor lock!\n");
5766 + return -1;
5767 + }
5768 + if (monitor_thread == pthread_self()) {
5769 + ast_mutex_unlock(&monlock);
5770 + ast_log(LOG_WARNING,"Unable to kill myself!\n");
5771 + return -1;
5772 + }
5773 +
5774 + if (ast_pthread_create(&monitor_thread,NULL,do_monitor,NULL) < 0) {
5775 + ast_mutex_unlock(&monlock);
5776 + ast_log(LOG_ERROR,"Unable to start monitor thread!\n");
5777 + return -1;
5778 + }
5779 +
5780 + return res;
5781 +}
5782 +
5783 +
5784 +int unload_module()
5785 +{
5786 + if (capi20_release(ast_capi_ApplID) != 0)
5787 + ast_log(LOG_WARNING,"Unable to unregister from CAPI!\n");
5788 + ast_channel_unregister(&capi_tech);
5789 + return 0;
5790 +}
5791 +
5792 +int usecount()
5793 +{
5794 + int res;
5795 + ast_mutex_lock(&usecnt_lock);
5796 + res = usecnt;
5797 + ast_mutex_unlock(&usecnt_lock);
5798 + return res;
5799 +}
5800 +
5801 +char *description()
5802 +{
5803 + return desc;
5804 +}
5805 +
5806 +
5807 +char *key()
5808 +{
5809 + return ASTERISK_GPL_KEY;
5810 +}
5811 diff -urN asterisk-1.2.10.orig/channels/chan_features.c asterisk-1.2.10/channels/chan_features.c
5812 --- asterisk-1.2.10.orig/channels/chan_features.c 2006-07-03 06:19:09.000000000 +0200
5813 +++ asterisk-1.2.10/channels/chan_features.c 2006-07-31 14:13:08.000000000 +0200
5814 @@ -427,7 +427,7 @@
5815 }
5816 ast_mutex_unlock(&featurelock);
5817 if (!tmp) {
5818 - chan = ast_request(tech, format, dest, &status);
5819 + chan = ast_request(tech, format, dest, &status, NULL);
5820 if (!chan) {
5821 ast_log(LOG_NOTICE, "Unable to allocate subchannel '%s/%s'\n", tech, dest);
5822 return NULL;
5823 diff -urN asterisk-1.2.10.orig/channels/chan_iax2.c asterisk-1.2.10/channels/chan_iax2.c
5824 --- asterisk-1.2.10.orig/channels/chan_iax2.c 2006-07-12 17:23:59.000000000 +0200
5825 +++ asterisk-1.2.10/channels/chan_iax2.c 2006-07-31 14:13:08.000000000 +0200
5826 @@ -11,6 +11,9 @@
5827 * the project provides a web site, mailing lists and IRC
5828 * channels for your use.
5829 *
5830 + * Hangup cause signalling implementation by
5831 + * Levent Guendogdu <levon@feature-it.com>
5832 + *
5833 * This program is free software, distributed under the terms of
5834 * the GNU General Public License Version 2. See the LICENSE file
5835 * at the top of the source tree.
5836 @@ -3089,7 +3092,7 @@
5837 memset(&ied, 0, sizeof(ied));
5838 ast_mutex_lock(&iaxsl[callno]);
5839 if (callno && iaxs[callno]) {
5840 - ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name);
5841 + ast_log(LOG_DEBUG, "We're hanging up %s with cause %i now...\n", c->name, c->hangupcause);
5842 alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE);
5843 /* Send the hangup unless we have had a transmission error or are already gone */
5844 iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause);
5845 @@ -3141,7 +3144,8 @@
5846 static struct ast_frame *iax2_read(struct ast_channel *c)
5847 {
5848 static struct ast_frame f = { AST_FRAME_NULL, };
5849 - ast_log(LOG_NOTICE, "I should never be called!\n");
5850 + if (option_verbose > 3)
5851 + ast_log(LOG_NOTICE, "I should never be called!\n");
5852 return &f;
5853 }
5854
5855 diff -urN asterisk-1.2.10.orig/channels/chan_sip.c asterisk-1.2.10/channels/chan_sip.c
5856 --- asterisk-1.2.10.orig/channels/chan_sip.c 2006-07-13 18:44:23.000000000 +0200
5857 +++ asterisk-1.2.10/channels/chan_sip.c 2006-07-31 14:53:09.000000000 +0200
5858 @@ -603,6 +603,7 @@
5859 unsigned int flags; /*!< SIP_ flags */
5860 int timer_t1; /*!< SIP timer T1, ms rtt */
5861 unsigned int sipoptions; /*!< Supported SIP sipoptions on the other end */
5862 + int dialog_established; /*!< SIP dialog established */
5863 int capability; /*!< Special capability (codec) */
5864 int jointcapability; /*!< Supported capability at both ends (codecs ) */
5865 int peercapability; /*!< Supported peer capability */
5866 @@ -626,6 +627,7 @@
5867 char refer_to[AST_MAX_EXTENSION]; /*!< Place to store REFER-TO extension */
5868 char referred_by[AST_MAX_EXTENSION]; /*!< Place to store REFERRED-BY extension */
5869 char refer_contact[SIP_LEN_CONTACT]; /*!< Place to store Contact info from a REFER extension */
5870 + char refer_replaces[AST_MAX_EXTENSION]; /*!< Place to store Replaces header of REFER-TO header */
5871 struct sip_pvt *refer_call; /*!< Call we are referring */
5872 struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
5873 int route_persistant; /*!< Is this the "real" route? */
5874 @@ -645,6 +647,7 @@
5875 char peername[256]; /*!< [peer] name, not set if [user] */
5876 char authname[256]; /*!< Who we use for authentication */
5877 char uri[256]; /*!< Original requested URI */
5878 + char origuri[SIP_LEN_CONTACT]; /*!< REAL! Original requested URI */
5879 char okcontacturi[SIP_LEN_CONTACT]; /*!< URI from the 200 OK on INVITE */
5880 char peersecret[256]; /*!< Password */
5881 char peermd5secret[256];
5882 @@ -768,6 +771,9 @@
5883 int callingpres; /*!< Calling id presentation */
5884 int inUse; /*!< Number of calls in use */
5885 int call_limit; /*!< Limit of concurrent calls */
5886 + int max_regs; /*!< Limit of concurrent registrations */
5887 + int subpeer; /*!< Peer entry used for multiple registrations */
5888 + char reg_callid[80]; /*!< Call-ID used for registration */
5889 char vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/
5890 char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox setting for MWI checks */
5891 char language[MAX_LANGUAGE]; /*!< Default language for prompts */
5892 @@ -928,7 +934,7 @@
5893 static int determine_firstline_parts(struct sip_request *req);
5894 static void sip_dump_history(struct sip_pvt *dialog); /* Dump history to LOG_DEBUG at end of dialog, before destroying data */
5895 static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
5896 -static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate);
5897 +static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name);
5898 static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tagbufsize);
5899
5900 /*! \brief Definition of this channel for PBX channel registration */
5901 @@ -1311,7 +1317,7 @@
5902 /* If this is a subscription, tell the phone that we got a timeout */
5903 if (p->subscribed) {
5904 p->subscribed = TIMEOUT;
5905 - transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1); /* Send first notification */
5906 + transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, 1, NULL, NULL); /* Send first notification */
5907 p->subscribed = NONE;
5908 append_history(p, "Subscribestatus", "timeout");
5909 return 10000; /* Reschedule this destruction so that we know that it's gone */
5910 @@ -3144,16 +3150,30 @@
5911
5912 /*! \brief find_call: Connect incoming SIP message to current dialog or create new dialog structure */
5913 /* Called by handle_request, sipsock_read */
5914 -static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method)
5915 +static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *sin, const int intended_method, const int replaces_callid)
5916 {
5917 struct sip_pvt *p;
5918 char *callid;
5919 char *tag = "";
5920 + char *replaces;
5921 char totag[128];
5922 char fromtag[128];
5923 + char *c;
5924
5925 callid = get_header(req, "Call-ID");
5926
5927 + if (replaces_callid) {
5928 + replaces = get_header(req, "Replaces");
5929 + c = strchr(replaces, ';');
5930 + if (c)
5931 + *c = '\0';
5932 + if (!ast_strlen_zero(replaces)) {
5933 + callid = replaces;
5934 + } else {
5935 + return NULL;
5936 + }
5937 + }
5938 +
5939 if (pedanticsipchecking) {
5940 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy
5941 we need more to identify a branch - so we have to check branch, from
5942 @@ -4135,6 +4155,7 @@
5943 if (sipmethod == SIP_CANCEL) {
5944 c = p->initreq.rlPart2; /* Use original URI */
5945 } else if (sipmethod == SIP_ACK) {
5946 +// XXX+ } else if (!strcasecmp(msg, "ACK") && !p->dialog_established) {
5947 /* Use URI from Contact: in 200 OK (if INVITE)
5948 (we only have the contacturi on INVITEs) */
5949 if (!ast_strlen_zero(p->okcontacturi))
5950 @@ -4901,13 +4922,15 @@
5951 ast_build_string(&invite, &invite_max, ";%s", p->options->uri_options);
5952
5953 ast_copy_string(p->uri, invite_buf, sizeof(p->uri));
5954 + ast_copy_string(p->origuri, invite, sizeof(p->origuri));
5955
5956 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) {
5957 /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */
5958 snprintf(to, sizeof(to), "<sip:%s>;tag=%s", p->uri, p->theirtag);
5959 } else if (p->options && p->options->vxml_url) {
5960 /* If there is a VXML URL append it to the SIP URL */
5961 - snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
5962 +// snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
5963 + snprintf(to, sizeof(to), "<%s;%s>", p->uri, p->options->vxml_url);
5964 } else {
5965 snprintf(to, sizeof(to), "<%s>", p->uri);
5966 }
5967 @@ -4964,6 +4987,11 @@
5968 if (!ast_strlen_zero(p->referred_by))
5969 add_header(&req, "Referred-By", p->referred_by);
5970 }
5971 + if (sipmethod == SIP_INVITE) {
5972 + if (!ast_strlen_zero(p->refer_replaces)) {
5973 + add_header(&req, "Replaces", p->refer_replaces);
5974 + }
5975 + }
5976 #ifdef OSP_SUPPORT
5977 if ((req.method != SIP_OPTIONS) && p->options && !ast_strlen_zero(p->options->osptoken)) {
5978 ast_log(LOG_DEBUG,"Adding OSP Token: %s\n", p->options->osptoken);
5979 @@ -5038,8 +5066,7 @@
5980 }
5981
5982 /*! \brief transmit_state_notify: Used in the SUBSCRIBE notification subsystem ----*/
5983 -static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate)
5984 -{
5985 +static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate, char *cid_num, char *cid_name) {
5986 char tmp[4000], from[256], to[256];
5987 char *t = tmp, *c, *a, *mfrom, *mto;
5988 size_t maxbytes = sizeof(tmp);
5989 @@ -5183,10 +5210,19 @@
5990 case DIALOG_INFO_XML: /* SNOM subscribes in this format */
5991 ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
5992 ast_build_string(&t, &maxbytes, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full":"partial", mto);
5993 - if ((state & AST_EXTENSION_RINGING) && global_notifyringing)
5994 - ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
5995 - else
5996 + if ((state & AST_EXTENSION_RINGING) && global_notifyringing) {
5997 + ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
5998 + if (cid_num) {
5999 + ast_build_string(&t, &maxbytes, "<local><identity display=\"%s\">%s</identity><target uri=\"%s\"/></local>\n", p->exten, p->exten, mfrom);
6000 + if (cid_name && !ast_strlen_zero(cid_name)) {
6001 + ast_build_string(&t, &maxbytes, "<remote><identity display=\"%s\">sip:%s@%s</identity><target uri=\"sip:%s%s@%s\"/></remote>\n", cid_name, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain);
6002 + } else {
6003 + ast_build_string(&t, &maxbytes, "<remote><identity display=\"%s\">sip:%s@%s</identity><target uri=\"sip:%s%s@%s\"/></remote>\n", cid_num, cid_num, p->fromdomain, ast_pickup_ext(), p->exten, p->fromdomain);
6004 + }
6005 + }
6006 + } else {
6007 ast_build_string(&t, &maxbytes, "<dialog id=\"%s\">\n", p->exten);
6008 + }
6009 ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring);
6010 ast_build_string(&t, &maxbytes, "</dialog>\n</dialog-info>\n");
6011 break;
6012 @@ -6013,8 +6049,10 @@
6013 p->expire = -1;
6014 pvt->expiry = expiry;
6015 snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(iabuf, sizeof(iabuf), p->addr.sin_addr), ntohs(p->addr.sin_port), expiry, p->username, p->fullcontact);
6016 - if (!ast_test_flag((&p->flags_page2), SIP_PAGE2_RT_FROMCONTACT))
6017 + if (!ast_test_flag((&p->flags_page2), SIP_PAGE2_RT_FROMCONTACT)) {
6018 + // ast_log(LOG_NOTICE, "updating SIP/Registry for peer %s with data %s\n", p->name, data);
6019 ast_db_put("SIP/Registry", p->name, data);
6020 + }
6021 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Registered\r\n", p->name);
6022 if (inaddrcmp(&p->addr, &oldsin)) {
6023 sip_poke_peer(p);
6024 @@ -6405,7 +6443,7 @@
6025 /*! \brief cb_extensionstate: Callback for the devicestate notification (SUBSCRIBE) support subsystem ---*/
6026 /* If you add an "hint" priority to the extension in the dial plan,
6027 you will get notifications on device state changes */
6028 -static int cb_extensionstate(char *context, char* exten, int state, void *data)
6029 +static int cb_extensionstate(char *context, char* exten, int state, void *data, char *cid_num, char *cid_name)
6030 {
6031 struct sip_pvt *p = data;
6032
6033 @@ -6424,7 +6462,7 @@
6034 p->laststate = state;
6035 break;
6036 }
6037 - transmit_state_notify(p, state, 1, 1);
6038 + transmit_state_notify(p, state, 1, 1, cid_num, cid_name);
6039
6040 if (option_debug > 1)
6041 ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->username);
6042 @@ -6450,7 +6488,13 @@
6043 char *name, *c;
6044 char *t;
6045 char *domain;
6046 -
6047 + char *callid;
6048 + struct sip_peer *clone;
6049 + char clone_name[256];
6050 + int found = 0;
6051 + struct sip_peer *recycle_peer = NULL;
6052 + char peer_name[256];
6053 +
6054 /* Terminate URI */
6055 t = uri;
6056 while(*t && (*t > 32) && (*t != ';'))
6057 @@ -6499,9 +6543,68 @@
6058 if (!ast_test_flag(&peer->flags_page2, SIP_PAGE2_DYNAMIC)) {
6059 ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name);
6060 } else {
6061 + callid = get_header(req, "Call-ID");
6062 + ast_copy_string(peer_name, peer->name, sizeof(peer_name));
6063 + if (peer->max_regs > 1) {
6064 + int i = 0;
6065 + /* check if peer matches callid */
6066 + if ((peer->expire > -1) && (!strncmp(peer->reg_callid, callid, strlen(callid)))) {
6067 + // ast_log(LOG_NOTICE, "peer->reg_callid %s, req->callid %s found in peer\n", peer->reg_callid, callid);
6068 + found++;
6069 + } else {
6070 + /* otherwise check subpeers for callid */
6071 + for (i=0; i<peer->max_regs - 1; i++) {
6072 + snprintf(clone_name, sizeof(clone_name), "%s@%d", peer->name, i);
6073 + // ast_log(LOG_NOTICE, "checking subpeer %s\n", clone_name);
6074 + clone = find_peer(clone_name, NULL, 1);
6075 + if (clone && (clone->expire > -1)) {
6076 + if (!strncmp(clone->reg_callid, callid, strlen(callid))) {
6077 + // ast_log(LOG_NOTICE, "clone->reg_callid %s, req->callid %s found in subpeer\n", clone->reg_callid, callid);
6078 + found++;
6079 + peer = clone;
6080 + break;
6081 + }
6082 + }
6083 + }
6084 + }
6085 + if (!found) {
6086 + // ast_log(LOG_NOTICE, "did not find callid in peer or subpeer\n");
6087 + /* choose the next best peer or subpeer (that means: find the peer with the smalles expiry time */
6088 + if (peer->expire == -1) {
6089 + recycle_peer = peer;
6090 + // ast_log(LOG_NOTICE, "peer %s expiry %d\n", peer->name, peer->expire);
6091 + } else {
6092 + for (i=0; i<peer->max_regs - 1; i++) {
6093 + snprintf(clone_name, sizeof(clone_name), "%s@%d", peer->name, i);
6094 + clone = find_peer(clone_name, NULL, 1);
6095 + if (clone) {
6096 + if (clone->expire == -1) {
6097 + recycle_peer = clone;
6098 + break;
6099 + }
6100 + // ast_log(LOG_NOTICE, "clone %s expiry %d\n", clone->name, clone->expire);
6101 + }
6102 + }
6103 + }
6104 + if (recycle_peer) {
6105 + peer = recycle_peer;
6106 + ast_copy_string(peer_name, peer->name, sizeof(peer_name));
6107 + // ast_log(LOG_NOTICE, "recycling peer %s\n", peer->name);
6108 + if (peer->subpeer) {
6109 + i = strchr(peer_name, '@') - peer_name;
6110 + if (i < sizeof(peer_name))
6111 + peer_name[i] = '\0';
6112 + // ast_log(LOG_NOTICE, "i = %d\n", i);
6113 + }
6114 + } else {
6115 + /* deny registration */
6116 + peer_name[0] = '\0';
6117 + }
6118 + }
6119 + }
6120 ast_copy_flags(p, peer, SIP_NAT);
6121 transmit_response(p, "100 Trying", req);
6122 - if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, 0, ignore))) {
6123 + if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer_name, peer->secret, peer->md5secret, SIP_REGISTER, uri, 0, ignore))) {
6124 sip_cancel_destroy(p);
6125 switch (parse_register_contact(p, peer, req)) {
6126 case PARSE_REGISTER_FAILED:
6127 @@ -6521,6 +6624,7 @@
6128 transmit_response_with_date(p, "200 OK", req);
6129 peer->lastmsgssent = -1;
6130 res = 0;
6131 + ast_copy_string(peer->reg_callid, callid, sizeof(peer->reg_callid));
6132 break;
6133 }
6134 }
6135 @@ -6866,6 +6970,11 @@
6136 /* XXX The refer_to could contain a call on an entirely different machine, requiring an
6137 INVITE with a replaces header -anthm XXX */
6138 /* The only way to find out is to use the dialplan - oej */
6139 + ast_copy_string(sip_pvt->refer_to, refer_to, sizeof(sip_pvt->refer_to));
6140 + ast_copy_string(sip_pvt->referred_by, referred_by, sizeof(sip_pvt->referred_by));
6141 + ast_copy_string(sip_pvt->refer_contact, h_contact, sizeof(sip_pvt->refer_contact));
6142 + ast_copy_string(sip_pvt->refer_replaces, replace_callid, sizeof(sip_pvt->referred_by));
6143 + return 2;
6144 }
6145 } else if (ast_exists_extension(NULL, transfercontext, refer_to, 1, NULL) || !strcmp(refer_to, ast_parking_ext())) {
6146 /* This is an unsupervised transfer (blind transfer) */
6147 @@ -7586,6 +7695,8 @@
6148 int peers_offline = 0;
6149 char *id;
6150 char idtext[256] = "";
6151 + char *tmp;
6152 + int i = 0;
6153
6154 if (s) { /* Manager - get ActionID */
6155 id = astman_get_header(m,"ActionID");
6156 @@ -7628,6 +7739,7 @@
6157 else
6158 ast_copy_string(name, iterator->name, sizeof(name));
6159
6160 + if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
6161 pstatus = peer_status(iterator, status, sizeof(status));
6162 if (pstatus)
6163 peers_online++;
6164 @@ -7644,14 +7756,24 @@
6165 }
6166 }
6167
6168 - snprintf(srch, sizeof(srch), FORMAT, name,
6169 + }
6170 + /* multiple registration, peer used ? */
6171 + if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
6172 + snprintf(srch, sizeof(srch), FORMAT, name,
6173 iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
6174 ast_test_flag(&iterator->flags_page2, SIP_PAGE2_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
6175 (ast_test_flag(iterator, SIP_NAT) & SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */
6176 iterator->ha ? " A " : " ", /* permit/deny */
6177 ntohs(iterator->addr.sin_port), status);
6178 + }
6179
6180 if (!s) {/* Normal CLI list */
6181 + if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
6182 + if (iterator->subpeer == 1) {
6183 + tmp = strchr(name, '@');
6184 + i = tmp - name;
6185 + name[i] = '\0';
6186 + }
6187 ast_cli(fd, FORMAT, name,
6188 iterator->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), iterator->addr.sin_addr) : "(Unspecified)",
6189 ast_test_flag(&iterator->flags_page2, SIP_PAGE2_DYNAMIC) ? " D " : " ", /* Dynamic or not? */
6190 @@ -7659,6 +7781,7 @@
6191 iterator->ha ? " A " : " ", /* permit/deny */
6192
6193 ntohs(iterator->addr.sin_port), status);
6194 + }
6195 } else { /* Manager format */
6196 /* The names here need to be the same as other channels */
6197 ast_cli(fd,
6198 @@ -7684,7 +7807,9 @@
6199
6200 ASTOBJ_UNLOCK(iterator);
6201
6202 - total_peers++;
6203 + if ((iterator->expire != -1) || (iterator->subpeer != 1)) {
6204 + total_peers++;
6205 + }
6206 } while(0) );
6207
6208 if (!s) {
6209 @@ -8719,6 +8844,7 @@
6210 char buf[1024];
6211 unsigned int event;
6212 char *c;
6213 + struct ast_call_feature *feature;
6214
6215 /* Need to check the media/type */
6216 if (!strcasecmp(get_header(req, "Content-Type"), "application/dtmf-relay") ||
6217 @@ -8782,6 +8908,19 @@
6218 ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE);
6219 transmit_response(p, "200 OK", req);
6220 return;
6221 + } else if ((c = get_header(req, "Record"))) {
6222 + feature = ast_find_builtin_feature("automon");
6223 + if (feature && (!ast_strlen_zero(feature->exten))) {
6224 + int i = 0;
6225 +// ast_log(LOG_NOTICE, "feature exten %s\n", feature->exten);
6226 + for (i=0; i<strlen(feature->exten); i++) {
6227 + struct ast_frame f = { AST_FRAME_DTMF, feature->exten[i] };
6228 + ast_queue_frame(p->owner, &f);
6229 + }
6230 + } else {
6231 + ast_log(LOG_NOTICE, "Feature \"One Touch Monitor\" not configured in features.conf.\n");
6232 + }
6233 + return;
6234 } else if ((c = get_header(req, "X-ClientCode"))) {
6235 /* Client code (from SNOM phone) */
6236 if (ast_test_flag(p, SIP_USECLIENTCODE)) {
6237 @@ -8881,12 +9020,63 @@
6238 return RESULT_SUCCESS;
6239 }
6240
6241 +
6242 +/*! \brief sip_notify: Send SIP notify to peer */
6243 +static int sip_send_notify(int fd, char *notify_type, char *peer)
6244 +{
6245 + struct ast_variable *varlist;
6246 + struct sip_pvt *p;
6247 + struct sip_request req;
6248 + struct ast_variable *var;
6249 +
6250 + varlist = ast_variable_browse(notify_types, notify_type);
6251 +
6252 + if (!varlist) {
6253 + if (fd > 0)
6254 + ast_cli(fd, "Unable to find notify type '%s'\n", notify_type);
6255 + return RESULT_FAILURE;
6256 + }
6257 +
6258 + p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
6259 + if (!p) {
6260 + ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
6261 + return RESULT_FAILURE;
6262 + }
6263 +
6264 + if (create_addr(p, peer)) {
6265 + /* Maybe they're not registered, etc. */
6266 + sip_destroy(p);
6267 + if (fd > 0)
6268 + ast_cli(fd, "Could not create address for '%s'\n", peer);
6269 + return RESULT_FAILURE;
6270 + }
6271 +
6272 + initreqprep(&req, p, SIP_NOTIFY);
6273 +
6274 + for (var = varlist; var; var = var->next)
6275 + add_header(&req, var->name, var->value);
6276 +
6277 + add_blank_header(&req);
6278 + /* Recalculate our side, and recalculate Call ID */
6279 + if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
6280 + memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
6281 + build_via(p, p->via, sizeof(p->via));
6282 + build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
6283 + if (fd > 0)
6284 + ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", notify_type, peer);
6285 + transmit_sip_request(p, &req);
6286 + sip_scheddestroy(p, 15000);
6287 +
6288 + return RESULT_SUCCESS;
6289 +}
6290 +
6291 /*! \brief sip_notify: Send SIP notify to peer */
6292 static int sip_notify(int fd, int argc, char *argv[])
6293 {
6294 struct ast_variable *varlist;
6295 int i;
6296 -
6297 + int res = RESULT_SUCCESS;
6298 +
6299 if (argc < 4)
6300 return RESULT_SHOWUSAGE;
6301
6302 @@ -8903,41 +9093,13 @@
6303 }
6304
6305 for (i = 3; i < argc; i++) {
6306 - struct sip_pvt *p;
6307 - struct sip_request req;
6308 - struct ast_variable *var;
6309 -
6310 - p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
6311 - if (!p) {
6312 - ast_log(LOG_WARNING, "Unable to build sip pvt data for notify\n");
6313 - return RESULT_FAILURE;
6314 - }
6315 -
6316 - if (create_addr(p, argv[i])) {
6317 - /* Maybe they're not registered, etc. */
6318 - sip_destroy(p);
6319 - ast_cli(fd, "Could not create address for '%s'\n", argv[i]);
6320 - continue;
6321 - }
6322 -
6323 - initreqprep(&req, p, SIP_NOTIFY);
6324 + if (sip_send_notify(fd, argv[2], argv[i]) == RESULT_FAILURE)
6325 + res = RESULT_FAILURE;
6326 + }
6327 + return res;
6328 +}
6329
6330 - for (var = varlist; var; var = var->next)
6331 - add_header(&req, var->name, var->value);
6332
6333 - add_blank_header(&req);
6334 - /* Recalculate our side, and recalculate Call ID */
6335 - if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
6336 - memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
6337 - build_via(p, p->via, sizeof(p->via));
6338 - build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
6339 - ast_cli(fd, "Sending NOTIFY of type '%s' to '%s'\n", argv[2], argv[i]);
6340 - transmit_sip_request(p, &req);
6341 - sip_scheddestroy(p, 15000);
6342 - }
6343 -
6344 - return RESULT_SUCCESS;
6345 -}
6346 /*! \brief sip_do_history: Enable SIP History logging (CLI) ---*/
6347 static int sip_do_history(int fd, int argc, char *argv[])
6348 {
6349 @@ -9598,7 +9760,7 @@
6350 if (!ignore && p->owner) {
6351 ast_queue_control(p->owner, AST_CONTROL_RINGING);
6352 if (p->owner->_state != AST_STATE_UP)
6353 - ast_setstate(p->owner, AST_STATE_RINGING);
6354 + ast_setstate_and_cid(p->owner, AST_STATE_RINGING, p->owner->cid.cid_num, p->owner->cid.cid_name);
6355 }
6356 if (find_sdp(req)) {
6357 process_sdp(p, req);
6358 @@ -10423,9 +10585,18 @@
6359 /* This is a call to ourself. Send ourselves an error code and stop
6360 processing immediately, as SIP really has no good mechanism for
6361 being able to call yourself */
6362 - transmit_response(p, "482 Loop Detected", req);
6363 - /* We do NOT destroy p here, so that our response will be accepted */
6364 - return 0;
6365 +/* char tmp[256] = "", *uri;
6366 + if (req->rlPart2)
6367 + ast_copy_string(tmp, req->rlPart2, sizeof(tmp));
6368 + uri = get_in_brackets(tmp);
6369 + if (strcmp(p->uri, uri)) {
6370 + ast_log(LOG_NOTICE, "SPIRAL DETECTED p->uri: %s uri: %s\n", p->uri, uri);
6371 + } else {
6372 + ast_log(LOG_NOTICE, "LOOP DETECTED p->uri: %s uri: %s\n", p->uri, uri);*/
6373 + transmit_response(p, "482 Loop Detected", req);
6374 + /* We do NOT destroy p here, so that our response will be accepted */
6375 + return 0;
6376 +/* }*/
6377 }
6378 if (!ignore) {
6379 /* Use this as the basis */
6380 @@ -10657,6 +10828,7 @@
6381 struct ast_channel *c=NULL;
6382 int res;
6383 struct ast_channel *transfer_to;
6384 + struct sip_pvt *rp; /* replace call */
6385
6386 if (option_debug > 2)
6387 ast_log(LOG_DEBUG, "SIP call transfer received for call %s (REFER)!\n", p->callid);
6388 @@ -10665,9 +10837,73 @@
6389 res = get_refer_info(p, req);
6390 if (res < 0)
6391 transmit_response(p, "603 Declined", req);
6392 - else if (res > 0)
6393 + else if (res == 1)
6394 transmit_response(p, "484 Address Incomplete", req);
6395 - else {
6396 + else if (res == 2) {
6397 + transmit_response(p, "202 Accepted", req);
6398 + rp = sip_alloc(NULL, NULL, 0, SIP_INVITE);
6399 + if (!rp) {
6400 + return -1;
6401 + }
6402 + rp->capability = global_capability;
6403 +
6404 + build_route(rp, req, 0);
6405 + if (option_verbose > 3)
6406 + ast_log(LOG_NOTICE, "got REFER for callid %s TO %s CONTACT %s replacing callid %s (tohost %s, p->route %s, rp->route %s)\n", p->callid, p->refer_to, p->refer_contact, p->refer_replaces, p->tohost, p->route->hop, rp->route->hop);
6407 + if (create_addr(rp, p->tohost)) {
6408 + sip_destroy(rp);
6409 + return -1;
6410 + }
6411 +
6412 + if (ast_sip_ouraddrfor(&rp->sa.sin_addr,&rp->ourip)) {
6413 + memcpy(&rp->ourip, &__ourip, sizeof(rp->ourip));
6414 + }
6415 + build_via(rp, rp->via, sizeof(rp->via));
6416 + build_callid(rp->callid, sizeof(rp->callid) - 1, rp->ourip, rp->fromdomain);
6417 +
6418 + ast_log(LOG_NOTICE, "1\n");
6419 + rp->prefcodec = p->prefcodec;
6420 + rp->jointcapability = rp->capability;
6421 + rp->rtp = p->rtp;
6422 + p->rtp = NULL;
6423 + if (!ast_strlen_zero(p->refer_to)) {
6424 + ast_copy_string(rp->username, p->refer_to, sizeof(rp->username));
6425 + rp->fullcontact[0] = '\0';
6426 + }
6427 + if (!ast_strlen_zero(p->refer_replaces)) {
6428 + ast_copy_string(rp->refer_replaces, p->refer_replaces, sizeof(rp->refer_replaces));
6429 + }
6430 + ast_log(LOG_NOTICE, "2\n");
6431 + ast_set_flag(rp, SIP_OUTGOING);
6432 +
6433 + ast_log(LOG_NOTICE, "3\n");
6434 +
6435 + if (p->owner) {
6436 + c = p->owner;
6437 +// ast_copy_string(rp->cid_num, c->cid.cid_num, sizeof(rp->cid_num));
6438 +// ast_copy_string(rp->cid_name, c->cid.cid_name, sizeof(rp->cid_name));
6439 + ast_log(LOG_NOTICE, "4\n");
6440 + c->tech_pvt = rp;
6441 + rp->owner = c;
6442 + ast_log(LOG_NOTICE, "5\n");
6443 + ast_mutex_unlock(&c->lock);
6444 + }
6445 + p->owner = NULL;
6446 + ast_log(LOG_NOTICE, "6\n");
6447 +
6448 + transmit_invite(rp, SIP_INVITE, 1, 2);
6449 + if (rp->maxtime) {
6450 + /* Initialize auto-congest time */
6451 + rp->initid = ast_sched_add(sched, rp->maxtime * 4, auto_congest, rp);
6452 + }
6453 +
6454 + transmit_notify_with_sipfrag(p, seqno);
6455 +
6456 + /* Always increment on a BYE */
6457 + transmit_request_with_auth(p, SIP_BYE, 0, 1, 1);
6458 + ast_set_flag(p, SIP_ALREADYGONE);
6459 + return 0;
6460 + } else { /* res == 0 */
6461 int nobye = 0;
6462 if (!ignore) {
6463 if (p->refer_call) {
6464 @@ -10995,7 +11231,7 @@
6465 struct sip_pvt *p_old;
6466
6467 transmit_response(p, "200 OK", req);
6468 - transmit_state_notify(p, firststate, 1, 1); /* Send first notification */
6469 + transmit_state_notify(p, firststate, 1, 1, NULL, NULL); /* Send first notification */
6470 append_history(p, "Subscribestatus", ast_extension_state2str(firststate));
6471
6472 /* remove any old subscription from this peer for the same exten/context,
6473 @@ -11189,6 +11425,8 @@
6474 res = handle_request_options(p, req, debug);
6475 break;
6476 case SIP_INVITE:
6477 + /* XXX quick fix for xfers */
6478 + ast_copy_string(p->tohost, ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), sizeof(p->tohost));
6479 res = handle_request_invite(p, req, debug, ignore, seqno, sin, recount, e);
6480 break;
6481 case SIP_REFER:
6482 @@ -11309,7 +11547,7 @@
6483 /* Process request, with netlock held */
6484 retrylock:
6485 ast_mutex_lock(&netlock);
6486 - p = find_call(&req, &sin, req.method);
6487 + p = find_call(&req, &sin, req.method, 0);
6488 if (p) {
6489 /* Go ahead and lock the owner if it has one -- we may need it */
6490 if (p->owner && ast_mutex_trylock(&p->owner->lock)) {
6491 @@ -11636,6 +11874,52 @@
6492 return 0;
6493 }
6494
6495 +static char mandescr_sip_notify[] =
6496 +"Description: Send a NOTIFY message to one or more SIP peers.\n"
6497 +"Variables: \n"
6498 +" Peer: <name> The peer name you want to send a NOTIFY to.\n"
6499 +" Type: <name> The notify type (see sip_notify.conf).\n"
6500 +" ActionID: <id> Optional action ID for this AMI transaction.\n";
6501 +
6502 +/*! \brief manager_sip_notify: Send a notify (see sip_notify.conf) to a peer ---*/
6503 +static int manager_sip_notify(struct mansession *s, struct message *m)
6504 +{
6505 + char *id = astman_get_header(m,"ActionID");
6506 + char *peer;
6507 + char *notify_type;
6508 + int res = 0;
6509 +
6510 + peer = astman_get_header(m,"Peer");
6511 + if (ast_strlen_zero(peer)) {
6512 + astman_send_error(s, m, "Peer: <name> missing.\n");
6513 + return 0;
6514 + }
6515 + notify_type = astman_get_header(m,"Type");
6516 + if (ast_strlen_zero(notify_type)) {
6517 + astman_send_error(s, m, "Type: <name> missing.\n");
6518 + return 0;
6519 + }
6520 +
6521 + res = sip_send_notify(-1, notify_type, peer);
6522 + if (res != RESULT_SUCCESS) {
6523 + ast_cli(s->fd, "Response: SIPNotify Failure\r\n"
6524 + "Peer: %s\r\n"
6525 + "Type: %s\r\n"
6526 + "ActionID: %s\r\n"
6527 + "\r\n",
6528 + peer, notify_type, id);
6529 + } else {
6530 + ast_cli(s->fd, "Response: SIPNotify Success\r\n"
6531 + "Peer: %s\r\n"
6532 + "Type: %s\r\n"
6533 + "ActionID: %s\r\n"
6534 + "\r\n",
6535 + peer, notify_type, id);
6536 + }
6537 + return res;
6538 +}
6539 +
6540 +
6541 /*! \brief sip_devicestate: Part of PBX channel interface ---*/
6542
6543 /* Return values:---
6544 @@ -12173,6 +12457,7 @@
6545
6546 peer->expire = -1;
6547 peer->pokeexpire = -1;
6548 + peer->max_regs = 1;
6549 ast_copy_string(peer->name, name, sizeof(peer->name));
6550 ast_copy_flags(peer, &global_flags, SIP_FLAGS_TO_COPY);
6551 strcpy(peer->context, default_context);
6552 @@ -12218,7 +12503,9 @@
6553
6554 if (peer) {
6555 /* Already in the list, remove it and it will be added back (or FREE'd) */
6556 - found++;
6557 + if (peer->max_regs == 1) {
6558 + found++;
6559 + }
6560 } else {
6561 peer = malloc(sizeof(*peer));
6562 if (peer) {
6563 @@ -12230,6 +12517,7 @@
6564 ASTOBJ_INIT(peer);
6565 peer->expire = -1;
6566 peer->pokeexpire = -1;
6567 + peer->max_regs = 1;
6568 } else {
6569 ast_log(LOG_WARNING, "Can't allocate SIP peer memory\n");
6570 }
6571 @@ -12375,6 +12663,10 @@
6572 peer->call_limit = atoi(v->value);
6573 if (peer->call_limit < 0)
6574 peer->call_limit = 0;
6575 + } else if (!strcasecmp(v->name, "registrations")) {
6576 + peer->max_regs = atoi(v->value);
6577 + if (peer->max_regs < 0)
6578 + peer->max_regs = 0;
6579 } else if (!strcasecmp(v->name, "amaflags")) {
6580 format = ast_cdr_amaflags2int(v->value);
6581 if (format < 0) {
6582 @@ -12770,8 +13062,24 @@
6583 if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
6584 peer = build_peer(cat, ast_variable_browse(cfg, cat), 0);
6585 if (peer) {
6586 - ASTOBJ_CONTAINER_LINK(&peerl,peer);
6587 - ASTOBJ_UNREF(peer, sip_destroy_peer);
6588 + if (peer->max_regs > 1) {
6589 + int i = 0;
6590 + int clones = peer->max_regs - 1;
6591 + struct sip_peer *clone = NULL;
6592 + char clone_name[sizeof(clone->name)];
6593 + /* clone clone clone */
6594 + for (i=0;i<clones;i++) {
6595 + snprintf(clone_name, sizeof(clone_name), "%s@%d", cat, i);
6596 + clone = build_peer(clone_name, ast_variable_browse(cfg, cat), 0);
6597 + if (clone) {
6598 + clone->subpeer = 1;
6599 + ASTOBJ_CONTAINER_LINK(&peerl,clone);
6600 + ASTOBJ_UNREF(clone, sip_destroy_peer);
6601 + }
6602 + }
6603 + }
6604 + ASTOBJ_CONTAINER_LINK(&peerl,peer);
6605 + ASTOBJ_UNREF(peer, sip_destroy_peer);
6606 }
6607 } else if (strcasecmp(utype, "user")) {
6608 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf");
6609 @@ -13361,6 +13669,8 @@
6610 "List SIP peers (text format)", mandescr_show_peers);
6611 ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM, manager_sip_show_peer,
6612 "Show SIP peer (text format)", mandescr_show_peer);
6613 + ast_manager_register2("SIPNotify", EVENT_FLAG_SYSTEM, manager_sip_notify,
6614 + "Send NOTIFY to peer", mandescr_sip_notify);
6615
6616 sip_poke_all_peers();
6617 sip_send_all_registers();
6618 @@ -13391,6 +13701,7 @@
6619
6620 ast_rtp_proto_unregister(&sip_rtp);
6621
6622 + ast_manager_unregister("SIPNotify");
6623 ast_manager_unregister("SIPpeers");
6624 ast_manager_unregister("SIPshowpeer");
6625
6626 diff -urN asterisk-1.2.10.orig/channels/chan_zap.c asterisk-1.2.10/channels/chan_zap.c
6627 --- asterisk-1.2.10.orig/channels/chan_zap.c 2006-07-12 15:54:10.000000000 +0200
6628 +++ asterisk-1.2.10/channels/chan_zap.c 2006-08-09 16:15:04.000000000 +0200
6629 @@ -11,6 +11,10 @@
6630 * the project provides a web site, mailing lists and IRC
6631 * channels for your use.
6632 *
6633 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
6634 + * Klaus-Peter Junghanns <kpj@junghanns.net>
6635 + *
6636 + *
6637 * This program is free software, distributed under the terms of
6638 * the GNU General Public License Version 2. See the LICENSE file
6639 * at the top of the source tree.
6640 @@ -65,6 +69,9 @@
6641 #ifdef ZAPATA_R2
6642 #include <libmfcr2.h>
6643 #endif
6644 +#ifdef ZAPATA_GSM
6645 +#include <libgsmat.h>
6646 +#endif
6647
6648 #include "asterisk.h"
6649
6650 @@ -96,6 +103,7 @@
6651 #include "asterisk/term.h"
6652 #include "asterisk/utils.h"
6653 #include "asterisk/transcap.h"
6654 +#include "asterisk/devicestate.h"
6655
6656 #ifndef ZT_SIG_EM_E1
6657 #error "Your zaptel is too old. please cvs update"
6658 @@ -173,6 +181,7 @@
6659 #define SIG_FXOGS ZT_SIG_FXOGS
6660 #define SIG_FXOKS ZT_SIG_FXOKS
6661 #define SIG_PRI ZT_SIG_CLEAR
6662 +#define SIG_GSM (0x100000 | ZT_SIG_CLEAR)
6663 #define SIG_R2 ZT_SIG_CAS
6664 #define SIG_SF ZT_SIG_SF
6665 #define SIG_SFWINK (0x0100000 | ZT_SIG_SF)
6666 @@ -183,7 +192,7 @@
6667 #define SIG_GR303FXOKS (0x0100000 | ZT_SIG_FXOKS)
6668 #define SIG_GR303FXSKS (0x0100000 | ZT_SIG_FXSKS)
6669
6670 -#define NUM_SPANS 32
6671 +#define NUM_SPANS 128 /*!<"32 spans", muahahaha, us alaws like to have some more... */
6672 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
6673 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
6674
6675 @@ -201,6 +210,11 @@
6676 static char defaultcic[64] = "";
6677 static char defaultozz[64] = "";
6678
6679 +static char nocid[256] = "No CID available";
6680 +static char withheldcid[256] = "CID withheld";
6681 +static char gsm_modem_pin[20];
6682 +static char gsm_modem_exten[AST_MAX_EXTENSION];
6683 +
6684 static char language[MAX_LANGUAGE] = "";
6685 static char musicclass[MAX_MUSICCLASS] = "";
6686 static char progzone[10]= "";
6687 @@ -287,6 +301,7 @@
6688 static int cur_priexclusive = 0;
6689
6690 static int priindication_oob = 0;
6691 +static int pritransfer = 0;
6692
6693 #ifdef ZAPATA_PRI
6694 static int minunused = 2;
6695 @@ -294,6 +309,7 @@
6696 static char idleext[AST_MAX_EXTENSION];
6697 static char idledial[AST_MAX_EXTENSION];
6698 static int overlapdial = 0;
6699 +static int usercid = 0;
6700 static int facilityenable = 0;
6701 static char internationalprefix[10] = "";
6702 static char nationalprefix[10] = "";
6703 @@ -305,8 +321,6 @@
6704 #ifdef PRI_GETSET_TIMERS
6705 static int pritimers[PRI_MAX_TIMERS];
6706 #endif
6707 -static int pridebugfd = -1;
6708 -static char pridebugfilename[1024]="";
6709 #endif
6710
6711 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
6712 @@ -327,10 +341,6 @@
6713
6714 static int ifcount = 0;
6715
6716 -#ifdef ZAPATA_PRI
6717 -AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
6718 -#endif
6719 -
6720 /*! \brief Whether we answer on a Polarity Switch event */
6721 static int answeronpolarityswitch = 0;
6722
6723 @@ -389,6 +399,18 @@
6724
6725 struct zt_pvt;
6726
6727 +#ifdef ZAPATA_GSM
6728 +struct zt_gsm {
6729 + pthread_t master;
6730 + ast_mutex_t lock; /* Mutex */
6731 + int fd;
6732 + int span;
6733 + struct gsm_modul *modul;
6734 + char pin[256];
6735 + char exten[AST_MAX_EXTENSION]; /* Where to idle extra calls */
6736 + struct zt_pvt *pvt;
6737 +};
6738 +#endif
6739
6740 #ifdef ZAPATA_R2
6741 static int r2prot = -1;
6742 @@ -403,6 +425,28 @@
6743 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
6744 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
6745
6746 +struct zt_suspended_call {
6747 + ast_mutex_t lock; /* Mutex */
6748 + char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
6749 + char callid[10]; /* the callID provided by the user */
6750 + int parked_at; /* extension in the call parking context */
6751 + struct zt_suspended_call *next;
6752 +};
6753 +
6754 +struct zt_holded_call {
6755 + ast_mutex_t lock; /* Mutex */
6756 + char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
6757 + char uniqueid[AST_MAX_EXTENSION]; /* unique id of the onhold channel */
6758 + int tei;
6759 + int cref;
6760 + int alreadyhungup;
6761 + struct ast_channel *channel;
6762 + struct ast_channel *bridge;
6763 + q931_call *call; /* this also covers tei mumbojumbo */
6764 + struct zt_holded_call *next;
6765 +};
6766 +
6767 +
6768 struct zt_pri {
6769 pthread_t master; /*!< Thread of master */
6770 ast_mutex_t lock; /*!< Mutex */
6771 @@ -416,6 +460,8 @@
6772 int nsf; /*!< Network-Specific Facilities */
6773 int dialplan; /*!< Dialing plan */
6774 int localdialplan; /*!< Local dialing plan */
6775 + char nocid[256];
6776 + char withheldcid[256];
6777 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
6778 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
6779 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
6780 @@ -435,6 +481,7 @@
6781 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
6782 int offset;
6783 int span;
6784 + int usercid; /* trust user provided callerid (callerani) ?? */
6785 int resetting;
6786 int resetpos;
6787 time_t lastreset; /*!< time when unused channels were last reset */
6788 @@ -442,6 +489,9 @@
6789 struct zt_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
6790 struct zt_pvt *crvs; /*!< Member CRV structs */
6791 struct zt_pvt *crvend; /*!< Pointer to end of CRV structs */
6792 + struct zt_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
6793 + struct zt_holded_call *holded_calls; /* Calls on hold */
6794 + int debugfd;
6795 };
6796
6797
6798 @@ -561,6 +611,8 @@
6799 unsigned int echocanbridged:1;
6800 unsigned int echocanon:1;
6801 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
6802 + /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
6803 + on a zap channel with EC to be off no matter what happens. */
6804 unsigned int firstradio:1;
6805 unsigned int hanguponpolarityswitch:1;
6806 unsigned int hardwaredtmf:1;
6807 @@ -573,7 +625,8 @@
6808 unsigned int overlapdial:1;
6809 unsigned int permcallwaiting:1;
6810 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
6811 - unsigned int priindication_oob:1;
6812 + unsigned int priindication_oob:2;
6813 + unsigned int pritransfer:2;
6814 unsigned int priexclusive:1;
6815 unsigned int pulse:1;
6816 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
6817 @@ -612,6 +665,7 @@
6818 #endif
6819 char cid_num[AST_MAX_EXTENSION];
6820 int cid_ton; /*!< Type Of Number (TON) */
6821 + int cid_pres; /*!< Calling Presentation */
6822 char cid_name[AST_MAX_EXTENSION];
6823 char lastcid_num[AST_MAX_EXTENSION];
6824 char lastcid_name[AST_MAX_EXTENSION];
6825 @@ -672,10 +726,15 @@
6826 int polarityonanswerdelay;
6827 struct timeval polaritydelaytv;
6828 int sendcalleridafter;
6829 +#ifdef ZAPATA_GSM
6830 + struct zt_gsm gsm;
6831 +#endif
6832 #ifdef ZAPATA_PRI
6833 struct zt_pri *pri;
6834 struct zt_pvt *bearer;
6835 struct zt_pvt *realcall;
6836 + int tei; /* channel in use by this tei */
6837 + q931_call *holdedcall;
6838 q931_call *call;
6839 int prioffset;
6840 int logicalspan;
6841 @@ -701,11 +760,14 @@
6842 static int zt_indicate(struct ast_channel *chan, int condition);
6843 static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
6844 static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen);
6845 +static int zt_devicestate(void *data);
6846 +static void disable_dtmf_detect(struct zt_pvt *p);
6847 +static void enable_dtmf_detect(struct zt_pvt *p);
6848
6849 static const struct ast_channel_tech zap_tech = {
6850 .type = type,
6851 .description = tdesc,
6852 - .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW,
6853 + .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
6854 .requester = zt_request,
6855 .send_digit = zt_digit,
6856 .send_text = zt_sendtext,
6857 @@ -719,6 +781,7 @@
6858 .indicate = zt_indicate,
6859 .fixup = zt_fixup,
6860 .setoption = zt_setoption,
6861 + .devicestate = zt_devicestate
6862 };
6863
6864 #ifdef ZAPATA_PRI
6865 @@ -730,6 +793,13 @@
6866 struct zt_pvt *round_robin[32];
6867
6868 #ifdef ZAPATA_PRI
6869 +struct app_tmp {
6870 + char app[256];
6871 + char data[256];
6872 + struct ast_channel *chan;
6873 + pthread_t t;
6874 +};
6875 +
6876 static inline int pri_grab(struct zt_pvt *pvt, struct zt_pri *pri)
6877 {
6878 int res;
6879 @@ -779,6 +849,112 @@
6880 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
6881 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __ZT_SIG_FXO) */)
6882
6883 +static int zt_devicestate(void *data)
6884 +{
6885 + int groupmatch = 0;
6886 + int channelmatch = 0;
6887 + struct zt_pvt *p;
6888 + char *dest=NULL;
6889 + int x,d;
6890 + char *s;
6891 + char opt=0;
6892 + int res, y=0;
6893 + struct zt_pvt *exit, *start, *end;
6894 + ast_mutex_t *lock;
6895 +
6896 +// ast_log(LOG_NOTICE, "data = %s\n", (char *)data);
6897 + return AST_DEVICE_UNKNOWN;
6898 +
6899 + /* Assume we're locking the iflock */
6900 + lock = &iflock;
6901 + start = iflist;
6902 + end = ifend;
6903 +
6904 + if (data) {
6905 + dest = ast_strdupa((char *)data);
6906 + } else {
6907 + ast_log(LOG_WARNING, "Channel requested with no data\n");
6908 + return AST_DEVICE_INVALID;
6909 + }
6910 + if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
6911 + /* Retrieve the group number */
6912 + char *stringp=NULL;
6913 + stringp=dest + 1;
6914 + s = strsep(&stringp, "/");
6915 + if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
6916 + ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
6917 + return AST_DEVICE_INVALID;
6918 + }
6919 + groupmatch = 1 << x;
6920 + } else {
6921 + char *stringp=NULL;
6922 + stringp=dest;
6923 + s = strsep(&stringp, "/");
6924 + p = iflist;
6925 + if (!strcasecmp(s, "pseudo")) {
6926 + /* Special case for pseudo */
6927 + x = CHAN_PSEUDO;
6928 + channelmatch = x;
6929 + /* bail out */
6930 + return AST_DEVICE_INVALID;
6931 + }
6932 +
6933 + else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
6934 + ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
6935 + return AST_DEVICE_INVALID;
6936 + } else {
6937 + channelmatch = x;
6938 + ast_log(LOG_NOTICE, "channelmatch = %d\n", channelmatch);
6939 + }
6940 + }
6941 + /* Search for an unowned channel */
6942 + if (ast_mutex_lock(lock)) {
6943 + ast_log(LOG_ERROR, "Unable to lock interface list???\n");
6944 + return AST_DEVICE_INVALID;
6945 + }
6946 + p = iflist;
6947 + exit = iflist;
6948 + res = AST_DEVICE_INVALID; /* start pessimistic */
6949 + while(p) {
6950 + if (p) {
6951 + ast_mutex_lock(&p->lock);
6952 + if ((groupmatch && ((p->group & groupmatch) != 0)) || (channelmatch && (p->channel == channelmatch))) {
6953 +#ifdef ZAPATA_PRI
6954 + if (p->pri) {
6955 + for(d=0;d<NUM_DCHANS;d++) {
6956 + if (p->pri->dchanavail[d] & DCHAN_UP) {
6957 + res = AST_DEVICE_UNKNOWN;
6958 + }
6959 + }
6960 + }
6961 +#endif
6962 + if ((!ast_strlen_zero(p->cid_num) && (strncasecmp(p->cid_num, dest, strlen(p->cid_num)))) || (!ast_strlen_zero(p->dnid) && (strncasecmp(p->dnid, dest, strlen(p->dnid))))) {
6963 + res = AST_DEVICE_UNKNOWN;
6964 + if (p->owner) {
6965 + if ((p->owner->_state == AST_STATE_RINGING) && (p->outgoing)) {
6966 + res = AST_DEVICE_RINGING;
6967 + }
6968 + if (((p->owner->_state == AST_STATE_RINGING) && (!p->outgoing)) || (p->owner->_state == AST_STATE_UP) || (p->owner->_state == AST_STATE_DIALING) || (p->owner->_state == AST_STATE_RESERVED) || (p->owner->_state == AST_STATE_RING)){
6969 + res = AST_DEVICE_INUSE;
6970 + }
6971 + }
6972 + if ((res == AST_DEVICE_INUSE) || (res == AST_DEVICE_RINGING)) {
6973 + /* stop searching now, one non-idle channel is sufficient */
6974 + ast_mutex_unlock(&p->lock);
6975 + break;
6976 + }
6977 + }
6978 + }
6979 + ast_mutex_unlock(&p->lock);
6980 + }
6981 + p = p->next;
6982 + }
6983 + ast_mutex_unlock(lock);
6984 +
6985 + return res;
6986 +
6987 +}
6988 +
6989 static int zt_get_index(struct ast_channel *ast, struct zt_pvt *p, int nullok)
6990 {
6991 int res;
6992 @@ -1181,6 +1357,8 @@
6993 return "GR-303 Signalling with FXOKS";
6994 case SIG_GR303FXSKS:
6995 return "GR-303 Signalling with FXSKS";
6996 + case SIG_GSM:
6997 + return "GSM Signalling";
6998 case 0:
6999 return "Pseudo Signalling";
7000 default:
7001 @@ -1381,12 +1559,16 @@
7002 int res;
7003 if (!p)
7004 return;
7005 + if (p->faxhandled) {
7006 + ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
7007 + return;
7008 + }
7009 if (p->echocanon) {
7010 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
7011 return;
7012 }
7013 if (p->digital) {
7014 - ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
7015 + ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
7016 return;
7017 }
7018 if (p->echocancel) {
7019 @@ -1412,7 +1594,7 @@
7020 {
7021 int x;
7022 int res;
7023 - if (p && p->echocancel && p->echotraining) {
7024 + if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
7025 x = p->echotraining;
7026 res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
7027 if (res)
7028 @@ -1592,7 +1774,7 @@
7029 {
7030 int x, y, res;
7031 x = muted;
7032 - if (p->sig == SIG_PRI) {
7033 + if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
7034 y = 1;
7035 res = ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &y);
7036 if (res)
7037 @@ -1774,7 +1956,12 @@
7038 ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
7039 p->outgoing = 1;
7040
7041 - set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
7042 + if (IS_DIGITAL(ast->transfercapability)) {
7043 + set_actual_gain(p->subs[SUB_REAL].zfd, 0, 0, 0, p->law);
7044 + } else {
7045 + set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
7046 + }
7047 +
7048
7049 switch(p->sig) {
7050 case SIG_FXOLS:
7051 @@ -1998,6 +2185,26 @@
7052 case SIG_PRI:
7053 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
7054 p->dialdest[0] = '\0';
7055 + disable_dtmf_detect(p);
7056 + break;
7057 + case SIG_GSM:
7058 +#ifdef ZAPATA_GSM
7059 + if (p->gsm.modul) {
7060 + c = strchr(dest, '/');
7061 + if (c)
7062 + c++;
7063 + else
7064 + c = dest;
7065 + ast_mutex_lock(&p->gsm.lock);
7066 + if (gsm_dial(p->gsm.modul, p->use_callingpres ? ast->cid.cid_pres : 0, c)) {
7067 + ast_log(LOG_WARNING, "dialing failed on channel %d\n", p->channel);
7068 + ast_mutex_unlock(&p->gsm.lock);
7069 + ast_mutex_unlock(&p->lock);
7070 + return -1;
7071 + }
7072 + ast_mutex_unlock(&p->gsm.lock);
7073 + }
7074 +#endif
7075 break;
7076 default:
7077 ast_log(LOG_DEBUG, "not yet implemented\n");
7078 @@ -2016,6 +2223,12 @@
7079 int ldp_strip;
7080 int exclusive;
7081
7082 + if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
7083 + // pass NO audio when ringing an isdn phone
7084 + p->dialing = 1;
7085 + // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
7086 + }
7087 +
7088 c = strchr(dest, '/');
7089 if (c)
7090 c++;
7091 @@ -2033,6 +2246,7 @@
7092 ast_mutex_unlock(&p->lock);
7093 return -1;
7094 }
7095 + strncpy(p->dnid, (c + p->stripmsd), sizeof(p->dnid)-1);
7096 if (p->sig != SIG_FXSKS) {
7097 p->dop.op = ZT_DIAL_OP_REPLACE;
7098 s = strchr(c + p->stripmsd, 'w');
7099 @@ -2056,6 +2270,8 @@
7100 pri_rel(p->pri);
7101 ast_mutex_unlock(&p->lock);
7102 return -1;
7103 + } else {
7104 + // ast_log(LOG_NOTICE, "call %d\n", p->call);
7105 }
7106 if (!(sr = pri_sr_new())) {
7107 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
7108 @@ -2085,7 +2301,7 @@
7109 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
7110 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
7111 (p->digital ? -1 :
7112 - ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
7113 + ((p->law == ZT_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
7114 if (p->pri->facilityenable)
7115 pri_facility_enable(p->pri->pri);
7116
7117 @@ -2286,8 +2502,10 @@
7118 }
7119 if (newslot < 0) {
7120 newslot = 0;
7121 - ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
7122 + if (pri->nodetype != BRI_CPE_PTMP) {
7123 + ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
7124 pri->dchannels[newslot]);
7125 + }
7126 }
7127 if (old && (oldslot != newslot))
7128 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
7129 @@ -2343,8 +2561,7 @@
7130
7131 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
7132 p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
7133 - p->ignoredtmf = 0;
7134 -
7135 +
7136 if (index > -1) {
7137 /* Real channel, do some fixup */
7138 p->subs[index].owner = NULL;
7139 @@ -2441,6 +2658,7 @@
7140
7141
7142 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
7143 + int outgoing = p->outgoing;
7144 p->owner = NULL;
7145 p->ringt = 0;
7146 p->distinctivering = 0;
7147 @@ -2477,19 +2695,61 @@
7148 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
7149 if (!pri_grab(p, p->pri)) {
7150 if (p->alreadyhungup) {
7151 +/* char *aoc = pbx_builtin_getvar_helper(ast,"AOCEUNITS");
7152 + int iaoc = aoc ? atoi(aoc) : -1;
7153 + char *aocpm = pbx_builtin_getvar_helper(ast,"AOCEUNITSPERMIN");
7154 + int iaocpm = aocpm ? atoi(aocpm) : -1;
7155 +
7156 + if (iaocpm > -1) {
7157 + if (ast->cdr) {
7158 + long bill_sec = ast->cdr->billsec;
7159 + long bill_min = 0;
7160 + if (bill_sec > 0) {
7161 + bill_min = bill_sec / 60;
7162 + if (bill_min < 1) bill_min = 1;
7163 + }
7164 + iaoc = bill_min * iaocpm;
7165 + } else {
7166 + ast_log(LOG_NOTICE, "no cdr \n");
7167 + }
7168 + } else {
7169 + ast_log(LOG_NOTICE, "iaocpm %d \n", iaocpm);
7170 + }
7171 +*/
7172 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
7173
7174 #ifdef SUPPORT_USERUSER
7175 pri_call_set_useruser(p->call, useruser);
7176 #endif
7177
7178 - pri_hangup(p->pri->pri, p->call, -1);
7179 + pri_hangup(p->pri->pri, p->call, -1, -1);
7180 p->call = NULL;
7181 if (p->bearer)
7182 p->bearer->call = NULL;
7183 } else {
7184 char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
7185 int icause = ast->hangupcause ? ast->hangupcause : -1;
7186 +/* char *aoc = pbx_builtin_getvar_helper(ast,"AOCEUNITS");
7187 + int iaoc = aoc ? atoi(aoc) : -1;
7188 + char *aocpm = pbx_builtin_getvar_helper(ast,"AOCEUNITSPERMIN");
7189 + int iaocpm = aocpm ? atoi(aocpm) : -1;
7190 +
7191 + if (iaocpm > -1) {
7192 + if (ast->cdr) {
7193 + long bill_sec = ast->cdr->billsec;
7194 + long bill_min = 0;
7195 + if (bill_sec > 0) {
7196 + bill_min = bill_sec / 60;
7197 + if (bill_min < 1) bill_min = 1;
7198 + }
7199 + iaoc = bill_min * iaocpm;
7200 + } else {
7201 + ast_log(LOG_NOTICE, "no cdr \n");
7202 + }
7203 + } else {
7204 + ast_log(LOG_NOTICE, "iaocpm %d \n", iaocpm);
7205 + }
7206 +*/
7207 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
7208
7209 #ifdef SUPPORT_USERUSER
7210 @@ -2503,7 +2763,28 @@
7211 if (atoi(cause))
7212 icause = atoi(cause);
7213 }
7214 - pri_hangup(p->pri->pri, p->call, icause);
7215 +
7216 + pri_hangup(p->pri->pri, p->call, icause, -1);
7217 +
7218 + /* if we send a release complete we wont ge no hangup event, so clear the call here */
7219 + if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
7220 + if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING)) {
7221 + p->call = NULL;
7222 + } else {
7223 + ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
7224 + icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
7225 + }
7226 + }
7227 +
7228 + if (p->pri->nodetype == BRI_NETWORK_PTMP) {
7229 + if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
7230 + if (outgoing) {
7231 + p->call = NULL;
7232 + }
7233 + }
7234 + }
7235 +
7236 +
7237 }
7238 if (res < 0)
7239 ast_log(LOG_WARNING, "pri_disconnect failed\n");
7240 @@ -2531,7 +2812,13 @@
7241
7242 }
7243 #endif
7244 - if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_R2))
7245 +#ifdef ZAPATA_GSM
7246 + if (p->gsm.modul) {
7247 + if (!p->alreadyhungup)
7248 + gsm_hangup(p->gsm.modul);
7249 + }
7250 +#endif
7251 + if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_R2) && (p->sig != SIG_GSM))
7252 res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_ONHOOK);
7253 if (res < 0) {
7254 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
7255 @@ -2700,10 +2987,14 @@
7256 p->proceeding = 1;
7257 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
7258 pri_rel(p->pri);
7259 + /* stop ignoring inband dtmf */
7260 + enable_dtmf_detect(p);
7261 } else {
7262 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
7263 res= -1;
7264 }
7265 + /* the audio path is complete now, train the echo canceler */
7266 + zt_train_ec(p);
7267 break;
7268 #endif
7269 #ifdef ZAPATA_R2
7270 @@ -2713,6 +3004,13 @@
7271 ast_log(LOG_WARNING, "R2 Answer call failed :( on %s\n", ast->name);
7272 break;
7273 #endif
7274 +#ifdef ZAPATA_GSM
7275 + case SIG_GSM:
7276 + if (p->gsm.modul) {
7277 + gsm_answer(p->gsm.modul);
7278 + }
7279 + break;
7280 +#endif
7281 case 0:
7282 ast_mutex_unlock(&p->lock);
7283 return 0;
7284 @@ -3273,6 +3571,15 @@
7285 {
7286 struct zt_pvt *p = newchan->tech_pvt;
7287 int x;
7288 + if (newchan && newchan->tech_pvt) {
7289 + p = newchan->tech_pvt;
7290 + }
7291 + if (!p) {
7292 + if (newchan) {
7293 + ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
7294 + }
7295 + return 0;
7296 + }
7297 ast_mutex_lock(&p->lock);
7298 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
7299 if (p->owner == oldchan) {
7300 @@ -3633,7 +3940,7 @@
7301 if (p->call) {
7302 if (p->pri && p->pri->pri) {
7303 if (!pri_grab(p, p->pri)) {
7304 - pri_hangup(p->pri->pri, p->call, -1);
7305 + pri_hangup(p->pri->pri, p->call, -1, -1);
7306 pri_destroycall(p->pri->pri, p->call);
7307 p->call = NULL;
7308 pri_rel(p->pri);
7309 @@ -4596,7 +4903,7 @@
7310 p->subs[index].f.data = NULL;
7311 p->subs[index].f.datalen= 0;
7312 }
7313 - if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
7314 + if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
7315 /* Perform busy detection. etc on the zap line */
7316 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
7317 if (f) {
7318 @@ -4608,8 +4915,9 @@
7319 }
7320 } else if (f->frametype == AST_FRAME_DTMF) {
7321 #ifdef ZAPATA_PRI
7322 - if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
7323 - /* Don't accept in-band DTMF when in overlap dial mode */
7324 + if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
7325 + /* Don't accept in-band DTMF when in overlap dial mode
7326 + or when in non-overlap overlapdialing mode ... */
7327 f->frametype = AST_FRAME_NULL;
7328 f->subclass = 0;
7329 }
7330 @@ -4657,8 +4965,10 @@
7331 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
7332 if (ast_async_goto(ast, target_context, "fax", 1))
7333 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
7334 - } else
7335 - ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
7336 + } else {
7337 + if (option_verbose > 2)
7338 + ast_verbose(VERBOSE_PREFIX_3 "Fax detected, but no fax extension\n");
7339 + }
7340 } else
7341 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
7342 } else
7343 @@ -4744,7 +5054,9 @@
7344 #endif
7345 /* Write a frame of (presumably voice) data */
7346 if (frame->frametype != AST_FRAME_VOICE) {
7347 - if (frame->frametype != AST_FRAME_IMAGE)
7348 + if (frame->frametype == AST_FRAME_TEXT) {
7349 + ast_log(LOG_NOTICE, "text\n");
7350 + } else if (frame->frametype != AST_FRAME_IMAGE)
7351 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
7352 return 0;
7353 }
7354 @@ -4815,7 +5127,7 @@
7355 switch(condition) {
7356 case AST_CONTROL_BUSY:
7357 #ifdef ZAPATA_PRI
7358 - if (p->priindication_oob && p->sig == SIG_PRI) {
7359 + if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
7360 chan->hangupcause = AST_CAUSE_USER_BUSY;
7361 chan->_softhangup |= AST_SOFTHANGUP_DEV;
7362 res = 0;
7363 @@ -4897,7 +5209,7 @@
7364 case AST_CONTROL_CONGESTION:
7365 chan->hangupcause = AST_CAUSE_CONGESTION;
7366 #ifdef ZAPATA_PRI
7367 - if (p->priindication_oob && p->sig == SIG_PRI) {
7368 + if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
7369 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
7370 chan->_softhangup |= AST_SOFTHANGUP_DEV;
7371 res = 0;
7372 @@ -5082,8 +5394,12 @@
7373 if (state == AST_STATE_RING)
7374 tmp->rings = 1;
7375 tmp->tech_pvt = i;
7376 - if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
7377 - /* Only FXO signalled stuff can be picked up */
7378 +#ifdef ZAPATA_PRI
7379 + if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
7380 +#else
7381 + if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
7382 +#endif
7383 + /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
7384 tmp->callgroup = i->callgroup;
7385 tmp->pickupgroup = i->pickupgroup;
7386 }
7387 @@ -5213,6 +5529,7 @@
7388 int len = 0;
7389 int res;
7390 int index;
7391 + int network;
7392 if (option_verbose > 2)
7393 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
7394 index = zt_get_index(chan, p, 1);
7395 @@ -5231,10 +5548,17 @@
7396 len = strlen(exten);
7397 res = 0;
7398 while((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
7399 - if (len && !ast_ignore_pattern(chan->context, exten))
7400 + if (len && !ast_ignore_pattern(chan->context, exten)) {
7401 tone_zone_play_tone(p->subs[index].zfd, -1);
7402 - else
7403 - tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
7404 + } else {
7405 + network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
7406 + if (network) {
7407 + tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);
7408 + } else {
7409 + /* cpe be quiet */
7410 + tone_zone_play_tone(p->subs[index].zfd, -1);
7411 + }
7412 + }
7413 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
7414 timeout = matchdigittimeout;
7415 else
7416 @@ -6327,18 +6651,44 @@
7417 break;
7418 case ZT_EVENT_NOALARM:
7419 i->inalarm = 0;
7420 +#ifdef ZAPATA_PRI
7421 + if (i->pri) {
7422 + if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE_PTMP)) {
7423 + /* dont annoy BRI TE mode users with layer2layer alarms */
7424 + } else {
7425 + ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
7426 + manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
7427 + "Channel: %d\r\n", i->channel);
7428 + }
7429 + }
7430 +#else
7431 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
7432 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
7433 "Channel: %d\r\n", i->channel);
7434 +#endif
7435 break;
7436 case ZT_EVENT_ALARM:
7437 i->inalarm = 1;
7438 res = get_alarms(i);
7439 +#ifdef ZAPATA_PRI
7440 + if (i->pri) {
7441 + if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE_PTMP)) {
7442 + /* dont annoy BRI TE mode users with layer2layer alarms */
7443 + } else {
7444 + ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
7445 + manager_event(EVENT_FLAG_SYSTEM, "Alarm",
7446 + "Alarm: %s\r\n"
7447 + "Channel: %d\r\n",
7448 + alarm2str(res), i->channel);
7449 + }
7450 + }
7451 +#else
7452 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
7453 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
7454 "Alarm: %s\r\n"
7455 "Channel: %d\r\n",
7456 alarm2str(res), i->channel);
7457 +#endif
7458 /* fall thru intentionally */
7459 case ZT_EVENT_ONHOOK:
7460 if (i->radio) break;
7461 @@ -6378,8 +6728,10 @@
7462 zt_set_hook(i->subs[SUB_REAL].zfd, ZT_ONHOOK);
7463 break;
7464 case SIG_PRI:
7465 - zt_disable_ec(i);
7466 - res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7467 + if (event != ZT_EVENT_ALARM) {
7468 + zt_disable_ec(i);
7469 + res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7470 + }
7471 break;
7472 default:
7473 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
7474 @@ -6702,6 +7054,8 @@
7475 } else {
7476 if (si->totalchans == 31) { /* if it's an E1 */
7477 pris[*span].dchannels[0] = 16 + offset;
7478 + } else if (si->totalchans == 3) { /* if it's an S0 ZAPBRI */
7479 + pris[*span].dchannels[0] = 3 + offset;
7480 } else {
7481 pris[*span].dchannels[0] = 24 + offset;
7482 }
7483 @@ -6789,6 +7143,10 @@
7484
7485 #endif
7486
7487 +#ifdef ZAPATA_GSM
7488 +static void *gsm_dchannel(void *vgsm);
7489 +#endif
7490 +
7491 static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_pri *pri, int reloading)
7492 {
7493 /* Make a zt_pvt structure for this interface (or CRV if "pri" is specified) */
7494 @@ -6947,6 +7305,11 @@
7495 destroy_zt_pvt(&tmp);
7496 return NULL;
7497 }
7498 + if ((pris[span].localdialplan) && (pris[span].localdialplan != localdialplan)) {
7499 + ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
7500 + destroy_zt_pvt(&tmp);
7501 + return NULL;
7502 + }
7503 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, idledial)) {
7504 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, idledial);
7505 destroy_zt_pvt(&tmp);
7506 @@ -6974,6 +7337,17 @@
7507 return NULL;
7508 }
7509 pris[span].nodetype = pritype;
7510 +// XXX
7511 + if (pritype == BRI_NETWORK_PTMP) {
7512 + pris[span].dchanavail[0] = DCHAN_AVAILABLE;
7513 + pri_find_dchan(&pris[span]);
7514 + }
7515 +// XXX tuev
7516 +
7517 +// if ((pritype == BRI_CPE) || (pritype == BRI_CPE_PTMP)) {
7518 +// pris[span].dchanavail[0] = DCHAN_AVAILABLE;
7519 +// pri_find_dchan(&pris[span]);
7520 +// }
7521 pris[span].switchtype = myswitchtype;
7522 pris[span].nsf = nsf;
7523 pris[span].dialplan = dialplan;
7524 @@ -6982,9 +7356,14 @@
7525 pris[span].minunused = minunused;
7526 pris[span].minidle = minidle;
7527 pris[span].overlapdial = overlapdial;
7528 + pris[span].usercid = usercid;
7529 + pris[span].suspended_calls = NULL;
7530 + pris[span].holded_calls = NULL;
7531 pris[span].facilityenable = facilityenable;
7532 ast_copy_string(pris[span].idledial, idledial, sizeof(pris[span].idledial));
7533 ast_copy_string(pris[span].idleext, idleext, sizeof(pris[span].idleext));
7534 + ast_copy_string(pris[span].nocid, nocid, sizeof(pris[span].nocid) - 1);
7535 + ast_copy_string(pris[span].withheldcid, withheldcid, sizeof(pris[span].withheldcid) - 1);
7536 ast_copy_string(pris[span].internationalprefix, internationalprefix, sizeof(pris[span].internationalprefix));
7537 ast_copy_string(pris[span].nationalprefix, nationalprefix, sizeof(pris[span].nationalprefix));
7538 ast_copy_string(pris[span].localprefix, localprefix, sizeof(pris[span].localprefix));
7539 @@ -7005,6 +7384,36 @@
7540 tmp->prioffset = 0;
7541 }
7542 #endif
7543 +#ifdef ZAPATA_GSM
7544 + if (signalling == SIG_GSM) {
7545 + struct zt_bufferinfo bi;
7546 + ast_mutex_init(&tmp->gsm.lock);
7547 + strncpy(tmp->gsm.pin, gsm_modem_pin, sizeof(tmp->gsm.pin) - 1);
7548 + strncpy(tmp->gsm.exten, gsm_modem_exten, sizeof(tmp->gsm.exten) - 1);
7549 + snprintf(fn, sizeof(fn), "%d", channel + 1);
7550 + /* Open non-blocking */
7551 + tmp->gsm.fd = zt_open(fn);
7552 + bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
7553 + bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
7554 + bi.numbufs = 16;
7555 + bi.bufsize = 1024;
7556 + if (ioctl(tmp->gsm.fd, ZT_SET_BUFINFO, &bi)) {
7557 + ast_log(LOG_ERROR, "Unable to set buffer info on channel '%s': %s\n", fn, strerror(errno));
7558 + return NULL;
7559 + }
7560 + tmp->gsm.pvt = tmp;
7561 + tmp->gsm.span = tmp->span;
7562 + tmp->gsm.modul = gsm_new(tmp->gsm.fd, 0, tmp->gsm.pin, tmp->span, tmp->channel);
7563 + if (ioctl(tmp->subs[SUB_REAL].zfd, ZT_AUDIOMODE, tmp->channel)) {
7564 + ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d: %s\n", tmp->channel, strerror(errno));
7565 + destroy_zt_pvt(&tmp);
7566 + return NULL;
7567 + }
7568 + if (ast_pthread_create(&tmp->gsm.master, NULL, gsm_dchannel, &tmp->gsm)) {
7569 + zt_close(tmp->gsm.fd);
7570 + }
7571 + }
7572 +#endif
7573 #ifdef ZAPATA_R2
7574 if (signalling == SIG_R2) {
7575 if (r2prot < 0) {
7576 @@ -7138,6 +7547,7 @@
7577 tmp->restrictcid = restrictcid;
7578 tmp->use_callingpres = use_callingpres;
7579 tmp->priindication_oob = priindication_oob;
7580 + tmp->pritransfer = pritransfer;
7581 tmp->priexclusive = cur_priexclusive;
7582 if (tmp->usedistinctiveringdetection) {
7583 if (!tmp->use_callerid) {
7584 @@ -7411,7 +7821,7 @@
7585 break;
7586 if (!backwards && (x >= pri->numchans))
7587 break;
7588 - if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
7589 + if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
7590 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
7591 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
7592 return x;
7593 @@ -7458,7 +7868,7 @@
7594 end = ifend;
7595 /* We do signed linear */
7596 oldformat = format;
7597 - format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW);
7598 + format &= (AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW);
7599 if (!format) {
7600 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
7601 return NULL;
7602 @@ -7618,6 +8028,11 @@
7603 p->digital = 1;
7604 if (tmp)
7605 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
7606 + } else if (opt == 'm') {
7607 + /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
7608 + p->faxhandled = 1;
7609 + if (tmp)
7610 + tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
7611 } else {
7612 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
7613 }
7614 @@ -7651,12 +8066,174 @@
7615 *cause = AST_CAUSE_BUSY;
7616 } else if (groupmatched) {
7617 *cause = AST_CAUSE_CONGESTION;
7618 + } else {
7619 + *cause = AST_CAUSE_CONGESTION;
7620 }
7621 }
7622
7623 return tmp;
7624 }
7625
7626 +#ifdef ZAPATA_GSM
7627 +static void handle_gsm_event(struct zt_gsm *gsm, gsm_event *e)
7628 +{
7629 + struct ast_channel *c = NULL;
7630 + int law = ZT_LAW_ALAW;
7631 + int res = 0;
7632 +
7633 + switch(e->e) {
7634 + case GSM_EVENT_DCHAN_UP:
7635 + if (option_verbose > 2)
7636 + ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d registered to network!\n", gsm->span);
7637 + break;
7638 + case GSM_EVENT_DCHAN_DOWN:
7639 + if (option_verbose > 2)
7640 + ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d unregistered from network!\n", gsm->span);
7641 + break;
7642 + case GSM_EVENT_RING:
7643 + ast_mutex_lock(&gsm->pvt->lock);
7644 + if (!ast_strlen_zero(e->ring.callingnum)) {
7645 + strncpy(gsm->pvt->cid_num, e->ring.callingnum, sizeof(gsm->pvt->cid_num) - 1);
7646 + } else {
7647 + strncpy(gsm->pvt->cid_name, withheldcid, sizeof(gsm->pvt->cid_name));
7648 + }
7649 + if (!ast_strlen_zero(gsm->exten)) {
7650 + strncpy(gsm->pvt->exten, gsm->exten, sizeof(gsm->pvt->exten) - 1);
7651 + } else {
7652 + gsm->pvt->exten[0] = 's';
7653 + gsm->pvt->exten[1] = '\0';
7654 + }
7655 + c = zt_new(gsm->pvt, AST_STATE_RING, 1, SUB_REAL, ZT_LAW_ALAW, AST_TRANS_CAP_SPEECH);
7656 + if (c) {
7657 + if (option_verbose > 2)
7658 + ast_verbose(VERBOSE_PREFIX_3 "Ring on channel %d (from %s to %s)\n", e->ring.channel, e->ring.callingnum, gsm->exten);
7659 + gsm->pvt->owner = c;
7660 + if (ioctl(gsm->pvt->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
7661 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", gsm->pvt->channel, law);
7662 + res = zt_setlaw(gsm->pvt->subs[SUB_REAL].zfd, law);
7663 + res = set_actual_gain(gsm->pvt->subs[SUB_REAL].zfd, 0, gsm->pvt->rxgain, gsm->pvt->txgain, law);
7664 + if (res < 0) {
7665 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", gsm->pvt->channel);
7666 +// } else {
7667 +// ast_log(LOG_NOTICE, "tx gain %f rx gain %f law %d pvt->law %d\n", gsm->pvt->txgain, gsm->pvt->rxgain, law, gsm->pvt->law);
7668 + }
7669 + }
7670 + ast_mutex_unlock(&gsm->pvt->lock);
7671 + break;
7672 + case GSM_EVENT_HANGUP:
7673 + ast_verbose(VERBOSE_PREFIX_3 "Got hang up on channel %d\n", e->hangup.channel);
7674 + ast_mutex_lock(&gsm->pvt->lock);
7675 + gsm->pvt->alreadyhungup = 1;
7676 + if (gsm->pvt->owner) {
7677 + gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
7678 + }
7679 + ast_mutex_unlock(&gsm->pvt->lock);
7680 + break;
7681 + case GSM_EVENT_ALERTING:
7682 + ast_mutex_lock(&gsm->pvt->lock);
7683 + gsm->pvt->subs[SUB_REAL].needringing =1;
7684 + ast_mutex_unlock(&gsm->pvt->lock);
7685 + break;
7686 + case GSM_EVENT_ANSWER:
7687 + ast_mutex_lock(&gsm->pvt->lock);
7688 + gsm->pvt->dialing = 0;
7689 + gsm->pvt->subs[SUB_REAL].needanswer =1;
7690 + gsm->pvt->ignoredtmf = 0;
7691 + ast_mutex_unlock(&gsm->pvt->lock);
7692 + break;
7693 + case GSM_EVENT_PIN_REQUIRED:
7694 + gsm_send_pin(gsm->modul, gsm->pin);
7695 + break;
7696 + case GSM_EVENT_SM_RECEIVED:
7697 + ast_verbose(VERBOSE_PREFIX_3 "SMS received on span %d. PDU: %s\n", gsm->span, e->sm_received.pdu);
7698 + break;
7699 + default:
7700 + ast_log(LOG_WARNING,"!! Unknown GSM event %d !!\n", e->e);
7701 + }
7702 +}
7703 +
7704 +static void *gsm_dchannel(void *vgsm)
7705 +{
7706 + struct zt_gsm *gsm = vgsm;
7707 + gsm_event *e;
7708 + struct timeval tv = {0,0}, *next;
7709 + fd_set rfds, efds;
7710 + int res,x;
7711 +
7712 + if (!gsm) return NULL;
7713 +
7714 + if (!gsm->modul) {
7715 + fprintf(stderr, "No gsm_mod\n");
7716 + return NULL;
7717 + }
7718 + gsm_set_debug(gsm->modul, GSM_DEBUG_NONE);
7719 + for (;;) {
7720 +
7721 + /* Run the D-Channel */
7722 + FD_ZERO(&rfds);
7723 + FD_ZERO(&efds);
7724 + FD_SET(gsm->fd, &rfds);
7725 + FD_SET(gsm->fd, &efds);
7726 +
7727 + if ((next = gsm_schedule_next(gsm->modul))) {
7728 + gettimeofday(&tv, NULL);
7729 + tv.tv_sec = next->tv_sec - tv.tv_sec;
7730 + tv.tv_usec = next->tv_usec - tv.tv_usec;
7731 + if (tv.tv_usec < 0) {
7732 + tv.tv_usec += 1000000;
7733 + tv.tv_sec -= 1;
7734 + }
7735 + if (tv.tv_sec < 0) {
7736 + tv.tv_sec = 0;
7737 + tv.tv_usec = 0;
7738 + }
7739 + }
7740 + res = select(gsm->fd + 1, &rfds, NULL, &efds, next ? &tv : NULL);
7741 + e = NULL;
7742 +
7743 + ast_mutex_lock(&gsm->lock);
7744 + if (!res) {
7745 + e = gsm_schedule_run(gsm->modul);
7746 + } else if (res > 0) {
7747 + e = gsm_check_event(gsm->modul, 1);
7748 + } else if (errno == ELAST) {
7749 + res = ioctl(gsm->fd, ZT_GETEVENT, &x);
7750 + printf("Got Zaptel event: %d\n", x);
7751 + } else if (errno != EINTR)
7752 + fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
7753 +
7754 + if (!e) {
7755 + e = gsm_check_event(gsm->modul, 0);
7756 + }
7757 +
7758 + if (e) {
7759 + handle_gsm_event(gsm, e);
7760 + }
7761 + ast_mutex_unlock(&gsm->lock);
7762 +
7763 + res = ioctl(gsm->fd, ZT_GETEVENT, &x);
7764 +
7765 + if (!res && x) {
7766 + switch (x) {
7767 + case ZT_EVENT_NOALARM:
7768 + ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", gsm->span);
7769 + usleep(1000);
7770 + gsm_restart(gsm->modul);
7771 + break;
7772 + case ZT_EVENT_ALARM:
7773 + ast_log(LOG_NOTICE, "Alarm detected on span %d\n", gsm->span);
7774 + break;
7775 + default:
7776 + fprintf(stderr, "Got event on GSM interface: %d\n", x);
7777 + }
7778 + }
7779 +
7780 +
7781 + }
7782 + return NULL;
7783 +}
7784 +
7785 +#endif
7786
7787 #ifdef ZAPATA_PRI
7788 static struct zt_pvt *pri_find_crv(struct zt_pri *pri, int crv)
7789 @@ -7671,6 +8248,57 @@
7790 return NULL;
7791 }
7792
7793 +static int pri_find_tei(struct zt_pri *pri, q931_call *c, int tei)
7794 +{
7795 + int x=0;
7796 + for (x=0;x<pri->numchans;x++) {
7797 + if (!pri->pvts[x]) continue;
7798 + if ((pri->pvts[x]->tei == tei) && (pri->pvts[x]-> call != c)) {
7799 + return x;
7800 + }
7801 + }
7802 + return -1;
7803 +}
7804 +
7805 +static struct zt_holded_call *pri_get_callonhold(struct zt_pri *pri, int cref, int tei) {
7806 + struct zt_holded_call *zhc = pri->holded_calls;
7807 + struct zt_holded_call *zhctemp = NULL;
7808 +
7809 + while (zhc) {
7810 + if ((zhc->tei == tei) && ((zhc->cref == cref) || (cref == -1))) {
7811 + return zhc;
7812 + }
7813 + zhctemp = zhc;
7814 + if (zhc) zhc = zhc->next;
7815 + }
7816 + return NULL;
7817 +}
7818 +
7819 +static int pri_destroy_callonhold(struct zt_pri *pri, struct zt_holded_call *onhold) {
7820 + struct zt_holded_call *zhc = pri->holded_calls;
7821 + struct zt_holded_call *zhctemp = NULL;
7822 +
7823 + while (zhc) {
7824 + if (zhc == onhold) {
7825 + if (zhctemp) {
7826 + zhctemp->next = zhc->next;
7827 + zhc = zhctemp;
7828 + } else {
7829 + pri->holded_calls = zhc->next;
7830 + zhc = pri->holded_calls;
7831 + zhctemp = NULL;
7832 + }
7833 + }
7834 + zhctemp = zhc;
7835 + if (zhc) zhc = zhc->next;
7836 + }
7837 + if (onhold) {
7838 + free(onhold);
7839 + onhold = NULL;
7840 + return 1;
7841 + }
7842 + return 0;
7843 +}
7844
7845 static int pri_find_principle(struct zt_pri *pri, int channel)
7846 {
7847 @@ -7703,7 +8331,9 @@
7848 static int pri_fixup_principle(struct zt_pri *pri, int principle, q931_call *c)
7849 {
7850 int x;
7851 + int res = 0;
7852 struct zt_pvt *crv;
7853 + char tmpname[256];
7854 if (!c) {
7855 if (principle < 0)
7856 return -1;
7857 @@ -7717,6 +8347,7 @@
7858 /* First, check for other bearers */
7859 for (x=0;x<pri->numchans;x++) {
7860 if (!pri->pvts[x]) continue;
7861 +// ast_log(LOG_NOTICE, "principle %d channel %d call %d channel[x]->call %d\n",principle, x, c, pri->pvts[x]->call);
7862 if (pri->pvts[x]->call == c) {
7863 /* Found our call */
7864 if (principle != x) {
7865 @@ -7730,19 +8361,56 @@
7866 }
7867 /* Fix it all up now */
7868 pri->pvts[principle]->owner = pri->pvts[x]->owner;
7869 + pri->pvts[principle]->outgoing = pri->pvts[x]->outgoing;
7870 if (pri->pvts[principle]->owner) {
7871 snprintf(pri->pvts[principle]->owner->name, sizeof(pri->pvts[principle]->owner->name),
7872 "Zap/%d:%d-%d", pri->trunkgroup, pri->pvts[principle]->channel, 1);
7873 pri->pvts[principle]->owner->tech_pvt = pri->pvts[principle];
7874 pri->pvts[principle]->owner->fds[0] = pri->pvts[principle]->subs[SUB_REAL].zfd;
7875 pri->pvts[principle]->subs[SUB_REAL].owner = pri->pvts[x]->subs[SUB_REAL].owner;
7876 - } else
7877 + } else {
7878 ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", pri->pvts[x]->channel, pri->pvts[principle]->channel);
7879 + }
7880 pri->pvts[principle]->call = pri->pvts[x]->call;
7881 + pri->pvts[principle]->dsp = pri->pvts[x]->dsp;
7882 + pri->pvts[principle]->alreadyhungup = pri->pvts[x]->alreadyhungup;
7883 + pri->pvts[principle]->digital = pri->pvts[x]->digital;
7884 + pri->pvts[principle]->faxhandled = pri->pvts[x]->faxhandled;
7885 +
7886 + if ((pri->nodetype == BRI_CPE_PTMP) || (pri->nodetype == BRI_CPE)) {
7887 + /* this might also apply for other pri types! */
7888 + pri->pvts[principle]->law = pri->pvts[x]->law;
7889 + if (ioctl(pri->pvts[principle]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &pri->pvts[principle]->law) == -1)
7890 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvts[principle]->channel, pri->pvts[principle]->law);
7891 + res = zt_setlaw(pri->pvts[principle]->subs[SUB_REAL].zfd, pri->pvts[principle]->law);
7892 + if (res < 0)
7893 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[principle]->channel);
7894 + if (!pri->pvts[principle]->digital) {
7895 + res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, pri->pvts[principle]->rxgain, pri->pvts[principle]->txgain, pri->pvts[principle]->law);
7896 + } else {
7897 + res = set_actual_gain(pri->pvts[principle]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[principle]->law);
7898 + }
7899 + if (res < 0)
7900 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[principle]->channel);
7901 + zt_confmute(pri->pvts[x], 0);
7902 + update_conf(pri->pvts[x]);
7903 + reset_conf(pri->pvts[x]);
7904 + restore_gains(pri->pvts[x]);
7905 + zt_disable_ec(pri->pvts[x]);
7906 + zt_setlinear(pri->pvts[x]->subs[SUB_REAL].zfd, 0);
7907 + }
7908 +
7909 + if (pri->pvts[principle]->owner) {
7910 + snprintf(tmpname, sizeof(tmpname), "Zap/%d-1", pri->pvts[principle]->channel);
7911 + ast_change_name(pri->pvts[principle]->owner, tmpname);
7912 + }
7913 +
7914 +
7915 /* Free up the old channel, now not in use */
7916 pri->pvts[x]->subs[SUB_REAL].owner = NULL;
7917 pri->pvts[x]->owner = NULL;
7918 pri->pvts[x]->call = NULL;
7919 + pri->pvts[x]->dsp = NULL;
7920 }
7921 return principle;
7922 }
7923 @@ -7771,7 +8439,9 @@
7924 }
7925 crv = crv->next;
7926 }
7927 - ast_log(LOG_WARNING, "Call specified, but not found?\n");
7928 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
7929 + ast_log(LOG_WARNING, "Call specified, but not found?\n");
7930 + }
7931 return -1;
7932 }
7933
7934 @@ -7830,86 +8500,33 @@
7935 #ifndef PRI_RESTART
7936 #error "Upgrade your libpri"
7937 #endif
7938 -static void zt_pri_message(struct pri *pri, char *s)
7939 +static void zt_pri_message(char *s, int span)
7940 {
7941 - int x, y;
7942 - int dchan = -1, span = -1;
7943 - int dchancount = 0;
7944 -
7945 - if (pri) {
7946 - for (x = 0; x < NUM_SPANS; x++) {
7947 - for (y = 0; y < NUM_DCHANS; y++) {
7948 - if (pris[x].dchans[y])
7949 - dchancount++;
7950 -
7951 - if (pris[x].dchans[y] == pri)
7952 - dchan = y;
7953 - }
7954 - if (dchan >= 0) {
7955 - span = x;
7956 - break;
7957 - }
7958 - dchancount = 0;
7959 - }
7960 - if ((dchan >= 0) && (span >= 0)) {
7961 - if (dchancount > 1)
7962 - ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
7963 - else
7964 - ast_verbose("%s", s);
7965 - } else
7966 - ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
7967 - } else
7968 - ast_verbose("%s", s);
7969 -
7970 - ast_mutex_lock(&pridebugfdlock);
7971 -
7972 - if (pridebugfd >= 0)
7973 - write(pridebugfd, s, strlen(s));
7974 -
7975 - ast_mutex_unlock(&pridebugfdlock);
7976 + ast_verbose("%d %s", span, s);
7977 }
7978
7979 -static void zt_pri_error(struct pri *pri, char *s)
7980 +static void zt_pri_error(char *s, int span)
7981 {
7982 - int x, y;
7983 - int dchan = -1, span = -1;
7984 - int dchancount = 0;
7985 + ast_log(LOG_WARNING, "%d %s", span, s);
7986 +}
7987
7988 - if (pri) {
7989 - for (x = 0; x < NUM_SPANS; x++) {
7990 - for (y = 0; y < NUM_DCHANS; y++) {
7991 - if (pris[x].dchans[y])
7992 - dchancount++;
7993 -
7994 - if (pris[x].dchans[y] == pri)
7995 - dchan = y;
7996 - }
7997 - if (dchan >= 0) {
7998 - span = x;
7999 - break;
8000 - }
8001 - dchancount = 0;
8002 - }
8003 - if ((dchan >= 0) && (span >= 0)) {
8004 - if (dchancount > 1)
8005 - ast_log(LOG_WARNING, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
8006 - else
8007 - ast_verbose("%s", s);
8008 - } else
8009 - ast_verbose("PRI debug error: could not find pri associated it with debug message output\n");
8010 - } else
8011 - ast_log(LOG_WARNING, "%s", s);
8012 -
8013 - ast_mutex_lock(&pridebugfdlock);
8014 -
8015 - if (pridebugfd >= 0)
8016 - write(pridebugfd, s, strlen(s));
8017 +#ifdef ZAPATA_GSM
8018 +static void zt_gsm_message(char *s, int channel)
8019 +{
8020 + ast_verbose("GSM %d: %s", channel, s);
8021 +}
8022
8023 - ast_mutex_unlock(&pridebugfdlock);
8024 +static void zt_gsm_error(char *s, int channel)
8025 +{
8026 + ast_log(LOG_WARNING, "GSM %d: %s", channel, s);
8027 }
8028 +#endif
8029
8030 static int pri_check_restart(struct zt_pri *pri)
8031 {
8032 + if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
8033 + return 0;
8034 + }
8035 do {
8036 pri->resetpos++;
8037 } while((pri->resetpos < pri->numchans) &&
8038 @@ -7992,6 +8609,32 @@
8039 }
8040 }
8041
8042 +static void pri_make_callerid(struct zt_pri *pri, char *callerid, int callerid_len, char *callingnum, int callingnum_len, int callingplan, int callingpres, int stripmsd) {
8043 + if (callingnum && (callingnum_len > stripmsd)) {
8044 + callingnum += stripmsd;
8045 + }
8046 + switch (callingplan) {
8047 + case PRI_INTERNATIONAL_ISDN:
8048 + snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
8049 + break;
8050 + case PRI_NATIONAL_ISDN:
8051 + snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
8052 + break;
8053 + case PRI_LOCAL_ISDN:
8054 + snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
8055 + break;
8056 + case PRI_PRIVATE:
8057 + snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
8058 + break;
8059 + case PRI_UNKNOWN:
8060 + snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
8061 + break;
8062 + default:
8063 + snprintf(callerid, callerid_len, "%s", callingnum);
8064 + break;
8065 + }
8066 +}
8067 +
8068 static void *pri_dchannel(void *vpri)
8069 {
8070 struct zt_pri *pri = vpri;
8071 @@ -8172,15 +8815,44 @@
8072 /* Check for an event */
8073 x = 0;
8074 res = ioctl(pri->fds[which], ZT_GETEVENT, &x);
8075 - if (x)
8076 + if ((pri->nodetype != BRI_CPE) && (pri->nodetype != BRI_CPE_PTMP)) {
8077 + /* dont annoy BRI TE mode users with layer2layer alarms */
8078 + if (x)
8079 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
8080 + }
8081 /* Keep track of alarm state */
8082 if (x == ZT_EVENT_ALARM) {
8083 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
8084 pri_find_dchan(pri);
8085 + if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
8086 + if (pri->pri) {
8087 + for (i=0; i<pri->numchans; i++) {
8088 + struct zt_pvt *p = pri->pvts[i];
8089 + if (p) {
8090 + if (p->call) {
8091 + if (p->pri && p->pri->pri) {
8092 + pri_destroycall(p->pri->pri, p->call);
8093 + p->call = NULL;
8094 + p->tei = -1;
8095 + } else
8096 + ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8097 + }
8098 + if (p->owner)
8099 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8100 + p->inalarm = 1;
8101 + }
8102 + }
8103 + pri_shutdown(pri->pri);
8104 + }
8105 + }
8106 } else if (x == ZT_EVENT_NOALARM) {
8107 - pri->dchanavail[which] |= DCHAN_NOTINALARM;
8108 - pri_restart(pri->dchans[which]);
8109 + if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
8110 + pri->dchanavail[which] |= DCHAN_NOTINALARM;
8111 + // pri->dchanavail[which] |= DCHAN_UP;
8112 + } else {
8113 + pri->dchanavail[which] |= DCHAN_NOTINALARM;
8114 + pri_restart(pri->dchans[which]);
8115 + }
8116 }
8117
8118 if (option_debug)
8119 @@ -8192,8 +8864,7 @@
8120 break;
8121 }
8122 } else if (errno != EINTR)
8123 - ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
8124 -
8125 + ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
8126 if (e) {
8127 if (pri->debug)
8128 pri_dump_event(pri->dchans[which], e);
8129 @@ -8201,32 +8872,102 @@
8130 pri->dchanavail[which] |= DCHAN_UP;
8131 switch(e->e) {
8132 case PRI_EVENT_DCHAN_UP:
8133 - if (option_verbose > 1)
8134 - ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8135 - pri->dchanavail[which] |= DCHAN_UP;
8136 - if (!pri->pri) pri_find_dchan(pri);
8137 -
8138 - /* Note presense of D-channel */
8139 - time(&pri->lastreset);
8140 -
8141 - /* Restart in 5 seconds */
8142 - if (pri->resetinterval > -1) {
8143 - pri->lastreset -= pri->resetinterval;
8144 - pri->lastreset += 5;
8145 - }
8146 - pri->resetting = 0;
8147 - /* Take the channels from inalarm condition */
8148 - for (i=0; i<pri->numchans; i++)
8149 - if (pri->pvts[i]) {
8150 - pri->pvts[i]->inalarm = 0;
8151 - }
8152 + if (pri->nodetype == BRI_NETWORK_PTMP) {
8153 + if (option_verbose > 3)
8154 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
8155 + pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
8156 + pri_find_dchan(pri);
8157 +
8158 + /* Note presense of D-channel */
8159 + time(&pri->lastreset);
8160 +
8161 + pri->resetting = 0;
8162 + /* Take the channels from inalarm condition */
8163 + for (i=0; i<pri->numchans; i++)
8164 + if (pri->pvts[i]) {
8165 + pri->pvts[i]->inalarm = 0;
8166 + }
8167 + } else {
8168 + if (pri->nodetype == BRI_CPE_PTMP) {
8169 + if (option_verbose > 3)
8170 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8171 + } else {
8172 + if (option_verbose > 1)
8173 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8174 + }
8175 + pri->dchanavail[which] |= (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP);
8176 + pri_find_dchan(pri);
8177 +
8178 + /* Note presense of D-channel */
8179 + time(&pri->lastreset);
8180 +
8181 + /* Restart in 5 seconds */
8182 + pri->lastreset -= pri->resetinterval;
8183 + pri->lastreset += 5;
8184 + pri->resetting = 0;
8185 + /* Take the channels from inalarm condition */
8186 + for (i=0; i<pri->numchans; i++) {
8187 + struct zt_pvt *p = pri->pvts[i];
8188 + if (p) {
8189 + p->inalarm = 0;
8190 + /* hang up calls that are not bridged yet, dont touch bridged calls */
8191 + if (p->call) {
8192 + if (p->pri && p->pri->pri) {
8193 + if (p->owner) {
8194 + if (p->owner->_state != AST_STATE_UP) {
8195 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8196 + pri_destroycall(p->pri->pri, p->call);
8197 + p->call = NULL;
8198 + }
8199 + } else {
8200 + pri_destroycall(p->pri->pri, p->call);
8201 + p->call = NULL;
8202 + }
8203 + }
8204 + }
8205 + }
8206 + }
8207 + }
8208 break;
8209 case PRI_EVENT_DCHAN_DOWN:
8210 - if (option_verbose > 1)
8211 - ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8212 - pri->dchanavail[which] &= ~DCHAN_UP;
8213 - pri_find_dchan(pri);
8214 - if (!pri_is_up(pri)) {
8215 + if (pri->nodetype == BRI_NETWORK_PTMP) {
8216 + if (option_verbose > 3)
8217 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
8218 + // PTMP BRIs have N dchans, handled by libpri
8219 + if (e->gen.tei == 0) break;
8220 + /* Hangup active channels */
8221 + for (i=0; i<pri->numchans; i++) {
8222 + struct zt_pvt *p = pri->pvts[i];
8223 + if (p) {
8224 + // ast_log(LOG_NOTICE, "chan %d tei %d\n",i,p->tei);
8225 + if (p->tei == e->gen.tei) {
8226 + if (p->call) {
8227 + if (p->pri && p->pri->pri) {
8228 + // pri_hangup(p->pri->pri, p->call, -1);
8229 + pri_destroycall(p->pri->pri, p->call);
8230 + p->tei = -1;
8231 + p->call = NULL;
8232 + } else
8233 + ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8234 + }
8235 + if (p->owner)
8236 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8237 + p->inalarm = 1;
8238 + p->tei = -1;
8239 + }
8240 + }
8241 + }
8242 + } else {
8243 + if (pri->nodetype == BRI_CPE_PTMP) {
8244 + if (option_verbose > 3)
8245 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8246 + } else {
8247 + if (option_verbose > 1)
8248 + ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8249 + }
8250 + pri->dchanavail[which] &= ~DCHAN_UP;
8251 + pri_find_dchan(pri);
8252 + if (!pri_is_up(pri)) {
8253 pri->resetting = 0;
8254 /* Hangup active channels and put them in alarm mode */
8255 for (i=0; i<pri->numchans; i++) {
8256 @@ -8234,19 +8975,29 @@
8257 if (p) {
8258 if (p->call) {
8259 if (p->pri && p->pri->pri) {
8260 - pri_hangup(p->pri->pri, p->call, -1);
8261 - pri_destroycall(p->pri->pri, p->call);
8262 - p->call = NULL;
8263 + if (p->owner) {
8264 + if (p->owner->_state != AST_STATE_UP) {
8265 + // pri_hangup(p->pri->pri, p->call, -1);
8266 + pri_destroycall(p->pri->pri, p->call);
8267 + p->call = NULL;
8268 + p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8269 + p->inalarm = 1;
8270 + }
8271 + } else {
8272 + pri_destroycall(p->pri->pri, p->call);
8273 + p->call = NULL;
8274 + p->inalarm = 1;
8275 + }
8276 } else
8277 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8278 }
8279 if (p->realcall) {
8280 - pri_hangup_all(p->realcall, pri);
8281 - } else if (p->owner)
8282 - p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8283 - p->inalarm = 1;
8284 + pri_hangup_all(p->realcall, pri);
8285 + p->inalarm = 1;
8286 + }
8287 }
8288 }
8289 + }
8290 }
8291 break;
8292 case PRI_EVENT_RESTART:
8293 @@ -8281,8 +9032,8 @@
8294 pri_destroycall(pri->pri, pri->pvts[x]->call);
8295 pri->pvts[x]->call = NULL;
8296 }
8297 - if (pri->pvts[chanpos]->realcall)
8298 - pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8299 + if (pri->pvts[x]->realcall)
8300 + pri_hangup_all(pri->pvts[x]->realcall, pri);
8301 else if (pri->pvts[x]->owner)
8302 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8303 ast_mutex_unlock(&pri->pvts[x]->lock);
8304 @@ -8316,7 +9067,6 @@
8305 }
8306 }
8307 break;
8308 -
8309 case PRI_EVENT_INFO_RECEIVED:
8310 chanpos = pri_find_principle(pri, e->ring.channel);
8311 if (chanpos < 0) {
8312 @@ -8325,9 +9075,11 @@
8313 } else {
8314 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
8315 if (chanpos > -1) {
8316 +// ast_log(LOG_NOTICE, "INFO received on channel %d/%d span %d\n",
8317 +// PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8318 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8319 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8320 - if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
8321 + if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
8322 /* how to do that */
8323 int digitlen = strlen(e->ring.callednum);
8324 char digit;
8325 @@ -8339,6 +9091,14 @@
8326 zap_queue_frame(pri->pvts[chanpos], &f, pri);
8327 }
8328 }
8329 + if (!pri->overlapdial) {
8330 + strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8331 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
8332 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
8333 + } else {
8334 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
8335 + }
8336 + }
8337 }
8338 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8339 }
8340 @@ -8346,39 +9106,58 @@
8341 break;
8342 case PRI_EVENT_RING:
8343 crv = NULL;
8344 - if (e->ring.channel == -1)
8345 + if (e->ring.channel == -1) {
8346 + /* if no channel specified find one empty */
8347 chanpos = pri_find_empty_chan(pri, 1);
8348 - else
8349 + } else {
8350 chanpos = pri_find_principle(pri, e->ring.channel);
8351 - /* if no channel specified find one empty */
8352 + }
8353 if (chanpos < 0) {
8354 - ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
8355 - PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8356 + /* no channel specified and no free channel. this is a callwating SETUP */
8357 + if (e->ring.channel == -1) {
8358 + if (option_verbose > 2)
8359 + ast_verbose(VERBOSE_PREFIX_3 "Ignoring callwaiting SETUP on channel %d/%d span %d %d\n", PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span, e->ring.channel);
8360 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY, -1);
8361 + break;
8362 + }
8363 } else {
8364 + /* ok, we got a b channel for this call, lock it */
8365 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8366 if (pri->pvts[chanpos]->owner) {
8367 - if (pri->pvts[chanpos]->call == e->ring.call) {
8368 - ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8369 - PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8370 - break;
8371 - } else {
8372 - ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
8373 + /* safety check, for messed up retransmissions? */
8374 + if (pri->pvts[chanpos]->call == e->ring.call) {
8375 + ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8376 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8377 - if (pri->pvts[chanpos]->realcall)
8378 - pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8379 - else
8380 - pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8381 - ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8382 - chanpos = -1;
8383 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8384 + chanpos = -1;
8385 + break;
8386 + } else {
8387 + ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
8388 + PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8389 + if (pri->pvts[chanpos]->realcall) {
8390 + pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8391 + } else {
8392 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8393 + /* XXX destroy the call here, so we can accept the retransmission as a new call */
8394 + pri_destroycall(pri->pri, e->ring.call);
8395 }
8396 - }
8397 - if (chanpos > -1)
8398 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8399 + chanpos = -1;
8400 + break;
8401 + }
8402 + }
8403 + if (chanpos > -1) {
8404 + /* everything is ok with the b channel */
8405 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8406 + }
8407 }
8408 - if ((chanpos < 0) && (e->ring.flexible))
8409 - chanpos = pri_find_empty_chan(pri, 1);
8410 + /* actually, we already got a valid channel by now */
8411 if (chanpos > -1) {
8412 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8413 + /* dont detect dtmfs before the signalling is done */
8414 + disable_dtmf_detect(pri->pvts[chanpos]);
8415 + /* this channel is owned by this TEI */
8416 + pri->pvts[chanpos]->tei = e->ring.tei;
8417 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
8418 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8419 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
8420 @@ -8392,13 +9171,14 @@
8421 ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
8422 } else
8423 ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
8424 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
8425 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE, -1);
8426 if (crv)
8427 ast_mutex_unlock(&crv->lock);
8428 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8429 break;
8430 }
8431 }
8432 + /* assign call to b channel */
8433 pri->pvts[chanpos]->call = e->ring.call;
8434 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
8435 if (pri->pvts[chanpos]->use_callerid) {
8436 @@ -8423,29 +9203,78 @@
8437 }
8438 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
8439 e->ring.redirectingnum, e->ring.callingplanrdnis);
8440 + /* get callingpres */
8441 + pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
8442 + switch (e->ring.callingpres) {
8443 + case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
8444 + case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
8445 + case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
8446 + case PRES_PROHIB_NETWORK_NUMBER:
8447 + strncpy(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
8448 + break;
8449 + case PRES_NUMBER_NOT_AVAILABLE:
8450 + strncpy(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
8451 + break;
8452 + }
8453 /* If immediate=yes go to s|1 */
8454 if (pri->pvts[chanpos]->immediate) {
8455 if (option_verbose > 2)
8456 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
8457 pri->pvts[chanpos]->exten[0] = 's';
8458 pri->pvts[chanpos]->exten[1] = '\0';
8459 - }
8460 - /* Get called number */
8461 - else if (!ast_strlen_zero(e->ring.callednum)) {
8462 - ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8463 - ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8464 - } else
8465 - pri->pvts[chanpos]->exten[0] = '\0';
8466 - /* Set DNID on all incoming calls -- even immediate */
8467 - if (!ast_strlen_zero(e->ring.callednum))
8468 - ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8469 - /* No number yet, but received "sending complete"? */
8470 - if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
8471 + } else if (ast_strlen_zero(e->ring.callednum)) {
8472 + /* called party number is empty */
8473 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
8474 + if (!pri->overlapdial) {
8475 + // be able to set digittimeout for BRI phones
8476 + pri->pvts[chanpos]->exten[0] = 's';
8477 + pri->pvts[chanpos]->exten[1] = '\0';
8478 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
8479 + } else {
8480 + pri->pvts[chanpos]->exten[0] = '\0';
8481 + }
8482 + } else {
8483 + if (pri->nodetype == BRI_CPE) {
8484 + /* fix for .at p2p bri lines */
8485 + pri->pvts[chanpos]->exten[0] = 's';
8486 + pri->pvts[chanpos]->exten[1] = '\0';
8487 + } else {
8488 + pri->pvts[chanpos]->exten[0] = '\0';
8489 + }
8490 + }
8491 + /* No number yet, but received "sending complete"? */
8492 + if (e->ring.complete) {
8493 if (option_verbose > 2)
8494 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
8495 pri->pvts[chanpos]->exten[0] = 's';
8496 pri->pvts[chanpos]->exten[1] = '\0';
8497 - }
8498 + }
8499 + } else {
8500 + /* Get called number */
8501 + pri_make_callerid(pri, pri->pvts[chanpos]->dnid, sizeof(pri->pvts[chanpos]->dnid), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
8502 + pri_make_callerid(pri, pri->pvts[chanpos]->exten, sizeof(pri->pvts[chanpos]->exten), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
8503 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
8504 + /* if we get the next digit we should stop the dialtone */
8505 + if (!pri->overlapdial) {
8506 + // with overlapdial=no the exten is always prefixed by "s"
8507 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
8508 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
8509 + } else {
8510 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
8511 + }
8512 + } else {
8513 + if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
8514 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, -1);
8515 + } else {
8516 + tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
8517 + }
8518 + }
8519 + }
8520 + }
8521 + /* Part 3: create channel, setup audio... */
8522 + /* Set DNID on all incoming calls -- even immediate */
8523 + if (!ast_strlen_zero(e->ring.callednum))
8524 + strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
8525 /* Make sure extension exists (or in overlap dial mode, can exist) */
8526 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
8527 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8528 @@ -8464,22 +9293,38 @@
8529 res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
8530 if (res < 0)
8531 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
8532 - res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8533 + if (IS_DIGITAL(e->ring.ctype)) {
8534 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
8535 + } else {
8536 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8537 + }
8538 if (res < 0)
8539 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
8540 - if (e->ring.complete || !pri->overlapdial)
8541 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8542 + if (e->ring.complete || !pri->overlapdial) {
8543 /* Just announce proceeding */
8544 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
8545 - else {
8546 + // pri->pvts[chanpos]->ignoredtmf = 0;
8547 + } else {
8548 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
8549 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8550 else
8551 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8552 + }
8553 + } else {
8554 + /* BRI_NETWORK | BRI_NETWORK_PTMP */
8555 + if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
8556 + /* send a SETUP_ACKNOWLEDGE */
8557 + pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8558 + } else {
8559 + /* send an ALERTING ??? wtf */
8560 + // pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8561 + pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
8562 + }
8563 }
8564 - /* Get the use_callingpres state */
8565 - pri->pvts[chanpos]->callingpres = e->ring.callingpres;
8566 -
8567 - /* Start PBX */
8568 +
8569 + /* overlapdial = yes and the extension can be valid */
8570 +
8571 if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8572 /* Release the PRI lock while we create the channel */
8573 ast_mutex_unlock(&pri->lock);
8574 @@ -8487,14 +9332,31 @@
8575 /* Set bearer and such */
8576 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
8577 c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8578 + if (c && (e->ring.lowlayercompat[0] > 0)) {
8579 + memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
8580 + }
8581 pri->pvts[chanpos]->owner = &inuse;
8582 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
8583 } else {
8584 c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8585 + if (c && (e->ring.lowlayercompat[0] > 0)) {
8586 + memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
8587 + }
8588 + zt_enable_ec(pri->pvts[chanpos]);
8589 }
8590 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
8591 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
8592 }
8593 + if (!ast_strlen_zero(e->ring.callingnum)) {
8594 + char tmpstr[256];
8595 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
8596 + pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
8597 + }
8598 + if (!ast_strlen_zero(e->ring.callingani)) {
8599 + char tmpstr[256];
8600 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
8601 + pbx_builtin_setvar_helper(c, "PRI_USER_CID", tmpstr);
8602 + }
8603 if(e->ring.ani2 >= 0) {
8604 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
8605 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
8606 @@ -8514,8 +9376,8 @@
8607 ast_mutex_lock(&pri->lock);
8608 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
8609 if (option_verbose > 2)
8610 - ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
8611 - plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>",
8612 + ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
8613 + pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>",
8614 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8615 } else {
8616 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8617 @@ -8523,14 +9385,18 @@
8618 if (c)
8619 ast_hangup(c);
8620 else {
8621 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8622 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
8623 pri->pvts[chanpos]->call = NULL;
8624 }
8625 }
8626 } else {
8627 + /* overlapdial = no */
8628 ast_mutex_unlock(&pri->lock);
8629 /* Release PRI lock while we create the channel */
8630 c = zt_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
8631 + if (c && (e->ring.lowlayercompat[0] > 0)) {
8632 + memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
8633 + }
8634 ast_mutex_lock(&pri->lock);
8635 if (c) {
8636 char calledtonstr[10];
8637 @@ -8551,23 +9417,40 @@
8638 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8639 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8640 if (option_verbose > 2)
8641 - ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
8642 - plancallingnum, pri->pvts[chanpos]->exten,
8643 + ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
8644 + pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten,
8645 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8646 zt_enable_ec(pri->pvts[chanpos]);
8647 + if(!ast_strlen_zero(e->ring.callingsubaddr)) {
8648 + pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
8649 + }
8650 + if (!ast_strlen_zero(e->ring.callingnum)) {
8651 + char tmpstr[256];
8652 + pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
8653 + pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
8654 + }
8655 + if (!ast_strlen_zero(e->ring.callingani)) {
8656 + char tmpstr[256];
8657 + pri_make_callerid(pri, tmpstr,sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
8658 + pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
8659 + }
8660 + if (!ast_strlen_zero(e->ring.useruserinfo)) {
8661 + pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
8662 + }
8663 } else {
8664 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8665 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8666 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8667 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION, -1);
8668 pri->pvts[chanpos]->call = NULL;
8669 }
8670 }
8671 } else {
8672 + /* invalid extension */
8673 if (option_verbose > 2)
8674 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
8675 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
8676 pri->pvts[chanpos]->prioffset, pri->span);
8677 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
8678 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED, -1);
8679 pri->pvts[chanpos]->call = NULL;
8680 pri->pvts[chanpos]->exten[0] = '\0';
8681 }
8682 @@ -8575,7 +9458,7 @@
8683 ast_mutex_unlock(&crv->lock);
8684 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8685 } else
8686 - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
8687 + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL, -1);
8688 break;
8689 case PRI_EVENT_RINGING:
8690 chanpos = pri_find_principle(pri, e->ringing.channel);
8691 @@ -8593,7 +9476,7 @@
8692 } else {
8693 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8694 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
8695 - zt_enable_ec(pri->pvts[chanpos]);
8696 + // XXX zt_enable_ec(pri->pvts[chanpos]);
8697 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
8698 pri->pvts[chanpos]->alerting = 1;
8699 } else
8700 @@ -8622,9 +9505,16 @@
8701 }
8702 break;
8703 case PRI_EVENT_PROGRESS:
8704 - /* Get chan value if e->e is not PRI_EVNT_RINGING */
8705 + /* Get chan value if e->e is not PRI_EVENT_RINGING */
8706 chanpos = pri_find_principle(pri, e->proceeding.channel);
8707 if (chanpos > -1) {
8708 + if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
8709 + /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
8710 + if (pri->pvts[chanpos]->owner) {
8711 + pri->pvts[chanpos]->owner->hangupcause = AST_CAUSE_USER_BUSY;
8712 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8713 + }
8714 + } else {
8715 #ifdef PRI_PROGRESS_MASK
8716 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
8717 #else
8718 @@ -8671,6 +9561,12 @@
8719 case PRI_EVENT_PROCEEDING:
8720 chanpos = pri_find_principle(pri, e->proceeding.channel);
8721 if (chanpos > -1) {
8722 + chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
8723 + if (chanpos < 0) {
8724 + ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n",
8725 + PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
8726 + chanpos = -1;
8727 + } else {
8728 if (!pri->pvts[chanpos]->proceeding) {
8729 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
8730
8731 @@ -8721,6 +9617,295 @@
8732 }
8733 }
8734 break;
8735 + case PRI_EVENT_SUSPEND_REQ:
8736 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8737 + pri_suspend_reject(pri->pri, e->suspend_req.call, "");
8738 + break;
8739 + }
8740 + chanpos = pri_find_principle(pri, e->suspend_req.channel);
8741 + if (chanpos < 0) {
8742 + ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
8743 + chanpos = -1;
8744 + }
8745 +
8746 + if (chanpos > -1) {
8747 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
8748 + if (pri->pvts[chanpos]->owner) {
8749 + if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
8750 + struct zt_suspended_call *zpc;
8751 + char tmpstr[256];
8752 + zpc = malloc(sizeof(struct zt_suspended_call));
8753 + if (!zpc) {
8754 + ast_log(LOG_ERROR, "unable to malloc zt_suspended_call\n");
8755 + break;
8756 + }
8757 + strncpy(zpc->msn, pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
8758 + strncpy(zpc->callid, e->suspend_req.callid, sizeof(zpc->callid));
8759 + ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
8760 + zpc->next = pri->suspended_calls;
8761 + pri->suspended_calls = zpc;
8762 + snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
8763 + pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
8764 + pri->pvts[chanpos]->call = NULL;
8765 + pri->pvts[chanpos]->tei = -1;
8766 + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8767 + } else {
8768 + pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
8769 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8770 + break;
8771 + }
8772 + } else {
8773 + pri_suspend_reject(pri->pri, e->suspend_req.call, "");
8774 + }
8775 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8776 + }
8777 + break;
8778 + case PRI_EVENT_RESUME_REQ:
8779 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8780 + break;
8781 + }
8782 + chanpos = pri_find_empty_chan(pri, 1);
8783 + if (chanpos < 0) {
8784 + pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
8785 + ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
8786 + chanpos = -1;
8787 + } else if (!pri->pvts[chanpos]) {
8788 + pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
8789 + chanpos = -1;
8790 + }
8791 +
8792 + if (chanpos > -1) {
8793 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
8794 + if (!pri->pvts[chanpos]->owner) {
8795 + struct zt_suspended_call *zpc, *zpcl;
8796 + int unparked=0;
8797 + char extenstr[255], temp[255];
8798 + zpc = NULL;
8799 + zpcl = pri->suspended_calls;
8800 + while (zpcl) {
8801 + // ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
8802 + if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
8803 + int law;
8804 + // found a parked call
8805 + snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
8806 + strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
8807 + // strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
8808 + pri->pvts[chanpos]->call = e->resume_req.call;
8809 + law = 1;
8810 + if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
8811 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
8812 + // uhh ohh...what shall we do without the bearer cap???
8813 + law = ZT_LAW_ALAW;
8814 + res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
8815 + if (res < 0)
8816 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8817 + if (!pri->pvts[chanpos]->digital) {
8818 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8819 + } else {
8820 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, 0, 0, pri->pvts[chanpos]->law);
8821 + }
8822 + if (res < 0)
8823 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8824 + /* Start PBX */
8825 + c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
8826 + if (c) {
8827 + pri->pvts[chanpos]->owner = c;
8828 + pri->pvts[chanpos]->call = e->resume_req.call;
8829 + zt_enable_ec(pri->pvts[chanpos]);
8830 + zt_train_ec(pri->pvts[chanpos]);
8831 + } else {
8832 + ast_log(LOG_ERROR, "unable to start pbx\n");
8833 + }
8834 +
8835 + if (zpc) {
8836 + zpc->next = zpcl->next;
8837 + free(zpcl);
8838 + zpcl = zpc->next;
8839 + } else {
8840 + // remove head
8841 + pri->suspended_calls = zpcl->next;
8842 + free(zpcl);
8843 + zpcl = pri->suspended_calls;
8844 + zpc = NULL;
8845 + }
8846 + unparked = 1;
8847 + snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
8848 + pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
8849 + break;
8850 + }
8851 + zpc = zpcl;
8852 + if (zpcl) zpcl = zpcl->next;
8853 + }
8854 + if (!unparked)
8855 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
8856 + } else {
8857 + pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
8858 + }
8859 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8860 + }
8861 + break;
8862 + case PRI_EVENT_HOLD_REQ:
8863 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8864 + pri_hold_reject(pri->pri, e->hold_req.call);
8865 + break;
8866 + }
8867 + chanpos = pri_find_principle(pri, e->hold_req.channel);
8868 + if (chanpos < 0) {
8869 + ast_log(LOG_WARNING, "Hold requested on unconfigured channel %d span %d\n", chanpos, pri->span);
8870 + chanpos = -1;
8871 + }
8872 + if (chanpos > -1) {
8873 + // ast_log(LOG_NOTICE, "Hold request for channel number %d span %d\n", chanpos, pri->span);
8874 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
8875 + if (pri->pvts[chanpos]->owner) {
8876 + struct zt_pvt *p = pri->pvts[chanpos];
8877 + struct zt_holded_call *zhc;
8878 + int holdacked=0;
8879 +
8880 +// ast_log(LOG_NOTICE,"HOLD request from channel %s tei %d\n",p->owner->name, e->hold_req.tei);
8881 + if (ast_bridged_channel(p->owner)) {
8882 + zhc = malloc(sizeof(struct zt_holded_call));
8883 + if (!zhc) {
8884 + ast_log(LOG_ERROR, "unable to malloc zt_holded_call\n");
8885 + break;
8886 + }
8887 + memset(zhc, 0, sizeof(zhc));
8888 + strncpy(zhc->msn, pri->pvts[chanpos]->cid_num, sizeof(zhc->msn));
8889 + strncpy(zhc->uniqueid, ast_bridged_channel(p->owner)->uniqueid, sizeof(zhc->uniqueid));
8890 + zhc->tei = e->hold_req.tei;
8891 + zhc->cref = e->hold_req.cref;
8892 + zhc->call = e->hold_req.call;
8893 + zhc->channel = p->owner;
8894 + zhc->alreadyhungup = 0;
8895 + zhc->bridge = ast_bridged_channel(p->owner);
8896 + zhc->next = pri->holded_calls;
8897 + pri->holded_calls = zhc;
8898 +
8899 + /* put channel on hold */
8900 + ast_masq_hold_call(ast_bridged_channel(p->owner), p->owner);
8901 +
8902 + pri_hold_acknowledge(pri->pri, e->hold_req.call);
8903 + holdacked = 1;
8904 + p->call = NULL; // free the bchannel withouth destroying the call
8905 + p->tei = -1;
8906 + } else {
8907 + // cant hold a non-bridge,...yet
8908 +
8909 + // make a fake channel
8910 +
8911 + // masquerade
8912 +
8913 + // put on hold
8914 + pri_hold_reject(pri->pri, e->hold_req.call);
8915 + }
8916 + } else {
8917 + pri_hold_reject(pri->pri, e->hold_req.call);
8918 + }
8919 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8920 + } else {
8921 + pri_hold_reject(pri->pri, e->hold_req.call);
8922 + }
8923 + break;
8924 + case PRI_EVENT_RETRIEVE_REQ:
8925 + if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8926 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8927 + break;
8928 + }
8929 + chanpos = pri_find_empty_chan(pri, 1);
8930 + if (chanpos < 0) {
8931 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8932 + ast_log(LOG_WARNING, "Retrieve requested on odd channel number %d span %d\n", chanpos, pri->span);
8933 + chanpos = -1;
8934 + break;
8935 + } else if (!pri->pvts[chanpos]) {
8936 + ast_log(LOG_WARNING, "Retrieve requested on unconfigured channel number %d span %d\n", chanpos, pri->span);
8937 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8938 + chanpos = -1;
8939 + break;
8940 + }
8941 + if (chanpos > -1) {
8942 + struct zt_holded_call *onhold = NULL;
8943 + int retrieved = 0;
8944 + int res = -1;
8945 + struct app_tmp *tmp;
8946 + pthread_attr_t attr;
8947 + int law;
8948 +
8949 + onhold = pri_get_callonhold(pri, e->retrieve_req.cref, e->retrieve_req.tei);
8950 +
8951 + if (!onhold) {
8952 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
8953 + break;
8954 + }
8955 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
8956 + // found a parked call
8957 + law = 1;
8958 + if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1)
8959 + ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
8960 + // uhh ohh...what shall we do without the bearer cap???
8961 + law = ZT_LAW_ALAW;
8962 + res = zt_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
8963 + if (res < 0)
8964 + ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8965 + res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8966 + if (res < 0)
8967 + ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
8968 + /* Start PBX */
8969 + c = zt_new(pri->pvts[chanpos], AST_STATE_UP, 0, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
8970 + if (c) {
8971 + pri->pvts[chanpos]->owner = c;
8972 + pri->pvts[chanpos]->outgoing = 1; /* for not sending proceedings... */
8973 + pri->pvts[chanpos]->call = e->retrieve_req.call;
8974 + pri->pvts[chanpos]->tei = e->retrieve_req.tei;
8975 + zt_enable_ec(pri->pvts[chanpos]);
8976 + zt_train_ec(pri->pvts[chanpos]);
8977 + } else {
8978 + ast_log(LOG_ERROR, "unable to start pbx\n");
8979 + }
8980 +
8981 + retrieved = 1;
8982 + // ast_log(LOG_NOTICE, "sending RETRIEVE ACK on channel %d, span %d for tei %d cref %d\n",chanpos,pri->span, e->retrieve_req.tei, e->retrieve_req.cref);
8983 + pri_retrieve_acknowledge(pri->pri, e->retrieve_req.call, chanpos + 1);
8984 +
8985 + // the magic begins here: ....
8986 + tmp = malloc(sizeof(struct app_tmp));
8987 + if (tmp) {
8988 + memset(tmp, 0, sizeof(struct app_tmp));
8989 + strncpy(tmp->app, "holdedcall", sizeof(tmp->app) - 1);
8990 + strncpy(tmp->data, onhold->uniqueid, sizeof(tmp->data) - 1);
8991 + tmp->chan = c;
8992 + }
8993 + pri_destroy_callonhold(pri, onhold);
8994 + onhold = NULL;
8995 +
8996 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8997 + pthread_attr_init(&attr);
8998 + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
8999 + if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
9000 + ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", c->name, strerror(errno));
9001 + free(tmp);
9002 + ast_hangup(c);
9003 + retrieved = 0;
9004 + }
9005 +
9006 + if (!retrieved) {
9007 + pri_retrieve_reject(pri->pri, e->retrieve_req.call);
9008 + }
9009 + }
9010 + break;
9011 + case PRI_EVENT_DISPLAY_RECEIVED:
9012 + ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
9013 + chanpos = pri_find_principle(pri, e->display.channel);
9014 + if (chanpos < 0) {
9015 + ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
9016 + chanpos = -1;
9017 + }
9018 + if (chanpos > -1) {
9019 + if (pri->pvts[chanpos]->owner) {
9020 + // ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
9021 + }
9022 + }
9023 + break;
9024 case PRI_EVENT_ANSWER:
9025 chanpos = pri_find_principle(pri, e->answer.channel);
9026 if (chanpos < 0) {
9027 @@ -8736,6 +9921,7 @@
9028 chanpos = -1;
9029 } else {
9030 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9031 + pri->pvts[chanpos]->tei = e->answer.tei;
9032 /* Now we can do call progress detection */
9033
9034 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9035 @@ -8765,11 +9951,16 @@
9036 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
9037 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9038 } else if (pri->pvts[chanpos]->confirmanswer) {
9039 - ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
9040 + ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
9041 + enable_dtmf_detect(pri->pvts[chanpos]);
9042 } else {
9043 + pri->pvts[chanpos]->dialing = 0;
9044 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
9045 /* Enable echo cancellation if it's not on already */
9046 zt_enable_ec(pri->pvts[chanpos]);
9047 + zt_train_ec(pri->pvts[chanpos]);
9048 + /* stop ignoring inband dtmf */
9049 + enable_dtmf_detect(pri->pvts[chanpos]);
9050 }
9051
9052 #ifdef SUPPORT_USERUSER
9053 @@ -8818,23 +10009,32 @@
9054 }
9055 }
9056 if (option_verbose > 2)
9057 - ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n",
9058 - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9059 + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
9060 + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
9061 } else {
9062 - pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9063 + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
9064 pri->pvts[chanpos]->call = NULL;
9065 + pri->pvts[chanpos]->tei = -1;
9066 }
9067 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9068 - if (option_verbose > 2)
9069 + if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
9070 + if (option_verbose > 2)
9071 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9072 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9073 - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9074 - pri->pvts[chanpos]->resetting = 1;
9075 + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9076 + pri->pvts[chanpos]->resetting = 1;
9077 + }
9078 }
9079 - if (e->hangup.aoc_units > -1)
9080 + if (e->hangup.aoc_units > -1) {
9081 + if (pri->pvts[chanpos]->owner) {
9082 + char tmpstr[256];
9083 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
9084 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
9085 + }
9086 if (option_verbose > 2)
9087 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9088 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9089 + }
9090
9091 #ifdef SUPPORT_USERUSER
9092 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9093 @@ -8844,8 +10044,20 @@
9094
9095 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9096 } else {
9097 - ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
9098 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9099 + struct zt_holded_call *onhold = NULL;
9100 + /* check calls on hold */
9101 + onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
9102 +
9103 + if (onhold) {
9104 + // ast_log(LOG_NOTICE, "hangup, found cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
9105 + pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
9106 + pri_destroy_callonhold(pri, onhold);
9107 + onhold = NULL;
9108 + } else {
9109 + ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
9110 + ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
9111 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9112 + }
9113 }
9114 }
9115 break;
9116 @@ -8855,17 +10067,25 @@
9117 case PRI_EVENT_HANGUP_REQ:
9118 chanpos = pri_find_principle(pri, e->hangup.channel);
9119 if (chanpos < 0) {
9120 - ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9121 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9122 + if (pri->nodetype == BRI_NETWORK_PTMP) {
9123 + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
9124 + } else {
9125 + ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9126 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9127 + }
9128 chanpos = -1;
9129 }
9130 - if (chanpos > -1) {
9131 + /* dont hang up if we want to hear inband call progress */
9132 + if ((chanpos > -1) && ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing))){
9133 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9134 if (chanpos > -1) {
9135 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9136 if (pri->pvts[chanpos]->realcall)
9137 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9138 else if (pri->pvts[chanpos]->owner) {
9139 + char tmpstr[256];
9140 + snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
9141 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
9142 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9143 switch(e->hangup.cause) {
9144 case PRI_CAUSE_USER_BUSY:
9145 @@ -8884,20 +10104,87 @@
9146 }
9147 if (option_verbose > 2)
9148 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9149 - if (e->hangup.aoc_units > -1)
9150 - if (option_verbose > 2)
9151 - ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9152 - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9153 + if (e->hangup.aoc_units > -1) {
9154 + if (pri->pvts[chanpos]->owner) {
9155 + char tmpstr[256];
9156 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
9157 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
9158 + }
9159 + if (option_verbose > 2)
9160 + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9161 + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9162 + }
9163 + if (pri->nodetype == BRI_NETWORK_PTMP) {
9164 + // check for bri transfers, not everybody uses ECT...
9165 + if (pri->pvts[chanpos]->owner) {
9166 + // find on hold call
9167 + struct zt_holded_call *onhold = NULL;
9168 + struct ast_channel *transferee = NULL;
9169 + int transfer_ok = 0;
9170 +
9171 + onhold = pri_get_callonhold(pri, -1, e->hangup.tei);
9172 +
9173 + if (onhold) {
9174 + if (pri->pvts[chanpos]->pritransfer == 2) {
9175 + if (((pri->pvts[chanpos]->owner->_state != AST_STATE_RING) && (pri->pvts[chanpos]->owner->_state != AST_STATE_RESERVED)) || ((!ast_strlen_zero(pri->pvts[chanpos]->exten)) && (strncasecmp(pri->pvts[chanpos]->exten, "s", sizeof(pri->pvts[chanpos]->exten))))) {
9176 + transferee = ast_get_holded_call(onhold->uniqueid);
9177 +
9178 + if (transferee) {
9179 + if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
9180 + ast_indicate(transferee, AST_CONTROL_RINGING);
9181 + }
9182 +
9183 + pri->pvts[chanpos]->owner->_softhangup &= ~AST_SOFTHANGUP_DEV;
9184 +
9185 + ast_mutex_unlock(&transferee->lock);
9186 + if (ast_channel_masquerade(pri->pvts[chanpos]->owner, transferee)) {
9187 + ast_log(LOG_WARNING, "unable to masquerade\n");
9188 + } else {
9189 + /* beware of zombies!!! */
9190 + ast_set_flag(transferee, AST_FLAG_ZOMBIE);
9191 + pri->pvts[chanpos]->owner = NULL;
9192 + pri->pvts[chanpos]->tei = -1;
9193 + transfer_ok = 1;
9194 + }
9195 + }
9196 + }
9197 + } else if (pri->pvts[chanpos]->pritransfer == 0) {
9198 + ast_log(LOG_NOTICE, "killing channel %s \n", onhold->uniqueid);
9199 + ast_retrieve_call_to_death(onhold->uniqueid);
9200 + transfer_ok = 1;
9201 + } else if (pri->pvts[chanpos]->pritransfer == 1) {
9202 + /* we use ECT transfers, so just ignore this */
9203 + transfer_ok = 0;
9204 + }
9205 +
9206 + if (transfer_ok) {
9207 + onhold->alreadyhungup = 1;
9208 + pri_hangup(pri->pri, onhold->call, e->hangup.cause, -1);
9209 + onhold = NULL;
9210 + }
9211 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9212 + break;
9213 + } else {
9214 + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
9215 + pri->pvts[chanpos]->call = NULL;
9216 + pri->pvts[chanpos]->tei = -1;
9217 + }
9218 + }
9219 + }
9220 } else {
9221 - pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9222 + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause, -1);
9223 pri->pvts[chanpos]->call = NULL;
9224 + pri->pvts[chanpos]->tei = -1;
9225 }
9226 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9227 - if (option_verbose > 2)
9228 - ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
9229 - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9230 - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9231 - pri->pvts[chanpos]->resetting = 1;
9232 + if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
9233 + if (option_verbose > 2)
9234 + ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
9235 + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9236 + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9237 + pri->pvts[chanpos]->resetting = 1;
9238 + }
9239 +
9240 }
9241
9242 #ifdef SUPPORT_USERUSER
9243 @@ -8908,9 +10195,37 @@
9244
9245 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9246 } else {
9247 - ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9248 + if (pri->nodetype != BRI_NETWORK_PTMP) {
9249 + ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9250 + } else {
9251 + // check holded_calls!!!
9252 + struct zt_holded_call *onhold = NULL;
9253 +
9254 + onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
9255 +
9256 + if (onhold) {
9257 + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause, -1);
9258 + ast_retrieve_call_to_death(onhold->uniqueid);
9259 + pri_destroy_callonhold(pri, onhold);
9260 + onhold = NULL;
9261 + } else {
9262 + ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9263 + }
9264 + }
9265 }
9266 }
9267 + if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
9268 + if (e->hangup.aoc_units > -1) {
9269 + char tmpstr[256];
9270 + snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
9271 + pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "AOCEUNITS", tmpstr);
9272 + if (option_verbose > 2)
9273 + ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9274 + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9275 + }
9276 + pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9277 + ast_channel_setwhentohangup(pri->pvts[chanpos]->owner, 5);
9278 + }
9279 break;
9280 case PRI_EVENT_HANGUP_ACK:
9281 chanpos = pri_find_principle(pri, e->hangup.channel);
9282 @@ -8924,6 +10239,7 @@
9283 if (chanpos > -1) {
9284 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9285 pri->pvts[chanpos]->call = NULL;
9286 + pri->pvts[chanpos]->tei = -1;
9287 pri->pvts[chanpos]->resetting = 0;
9288 if (pri->pvts[chanpos]->owner) {
9289 if (option_verbose > 2)
9290 @@ -8937,7 +10253,9 @@
9291 #endif
9292
9293 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9294 + }
9295 }
9296 + }
9297 }
9298 break;
9299 case PRI_EVENT_CONFIG_ERR:
9300 @@ -9029,10 +10347,22 @@
9301 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9302 switch(e->notify.info) {
9303 case PRI_NOTIFY_REMOTE_HOLD:
9304 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
9305 + ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
9306 + ast_moh_start(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL);
9307 + } else {
9308 + ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
9309 + }
9310 f.subclass = AST_CONTROL_HOLD;
9311 zap_queue_frame(pri->pvts[chanpos], &f, pri);
9312 break;
9313 case PRI_NOTIFY_REMOTE_RETRIEVAL:
9314 + if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
9315 + ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
9316 + ast_moh_stop(ast_bridged_channel(pri->pvts[chanpos]->owner));
9317 + } else {
9318 + ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
9319 + }
9320 f.subclass = AST_CONTROL_UNHOLD;
9321 zap_queue_frame(pri->pvts[chanpos], &f, pri);
9322 break;
9323 @@ -9040,6 +10370,77 @@
9324 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9325 }
9326 break;
9327 + case PRI_EVENT_FACILITY:
9328 + if (e->facility.operation == 0x06) {
9329 + struct ast_channel *chan = NULL;
9330 + struct zt_holded_call *onhold = NULL;
9331 + if (option_verbose > 2) {
9332 + ast_verbose(VERBOSE_PREFIX_3 "ECT requested by TEI %d for cref %d\n", e->facility.tei, e->facility.cref);
9333 + }
9334 + /* search for cref/tei in held calls */
9335 + onhold = pri_get_callonhold(pri, e->facility.cref, e->facility.tei);
9336 + if (onhold) {
9337 + chan = ast_get_holded_call(onhold->uniqueid);
9338 + onhold->alreadyhungup = 1;
9339 + onhold = NULL;
9340 + if (!chan) {
9341 + /* hang up */
9342 + pri_hangup(pri->pri, e->facility.call, 16, -1);
9343 + break;
9344 + }
9345 + } else {
9346 + /* unknown cref/tei */
9347 + ast_log(LOG_WARNING, "did not find call on hold for cref %d tei %d\n", e->facility.tei, e->facility.cref);
9348 + /* hang up */
9349 + pri_hangup(pri->pri, e->facility.call, 16, -1);
9350 + break;
9351 + }
9352 +
9353 + /* find an active call for the same tei */
9354 + chanpos = pri_find_tei(pri, e->facility.call, e->facility.tei);
9355 + if (chanpos < 0) {
9356 + /* did not find active call, hangup call on hold */
9357 + if (chan) {
9358 + ast_hangup(chan);
9359 + chan = NULL;
9360 + }
9361 + } else {
9362 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
9363 + /* transfer */
9364 + if (pri->pvts[chanpos]->owner) {
9365 + if (option_verbose > 3) {
9366 + ast_verbose(VERBOSE_PREFIX_3 "ECT: found %s on channel %d for tei %d\n", pri->pvts[chanpos]->owner->name ,chanpos, e->facility.tei);
9367 + }
9368 + /* pass callprogress if the channel is not up yet */
9369 + if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
9370 + ast_indicate(chan, AST_CONTROL_RINGING);
9371 + }
9372 + /* unlock the channel we removed from hold */
9373 + ast_mutex_unlock(&chan->lock);
9374 + if (ast_channel_masquerade(pri->pvts[chanpos]->owner, chan)) {
9375 + ast_log(LOG_WARNING, "unable to masquerade\n");
9376 + } else {
9377 + /* beware of zombies !!! */
9378 + ast_set_flag(chan, AST_FLAG_ZOMBIE);
9379 + // chan->zombie = 1;
9380 + }
9381 + }
9382 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9383 + }
9384 + /* disconnect */
9385 + pri_hangup(pri->pri, e->facility.call, 16, -1);
9386 + } else if (e->facility.operation == 0x0D) {
9387 + ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
9388 + ast_mutex_lock(&pri->pvts[chanpos]->lock);
9389 + /* transfer */
9390 + if (pri->pvts[chanpos]->owner) {
9391 + snprintf(pri->pvts[chanpos]->owner->call_forward, sizeof(pri->pvts[chanpos]->owner->call_forward), "Local/%s@%s", e->facility.forwardnum, pri->pvts[chanpos]->owner->context);
9392 + }
9393 + ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9394 + } else {
9395 + ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
9396 + }
9397 + break;
9398 default:
9399 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
9400 }
9401 @@ -9101,7 +10502,7 @@
9402 pri->fds[i] = -1;
9403 return -1;
9404 }
9405 - pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
9406 + pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
9407 /* Force overlap dial if we're doing GR-303! */
9408 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
9409 pri->overlapdial = 1;
9410 @@ -9170,39 +10571,77 @@
9411
9412 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
9413 {
9414 - int myfd;
9415 + int myfd, x, d;
9416 + int span;
9417 +
9418 + if (argc < 6)
9419 + return RESULT_SHOWUSAGE;
9420
9421 if (!strncasecmp(argv[1], "set", 3)) {
9422 - if (argc < 5)
9423 + if (argc < 7)
9424 return RESULT_SHOWUSAGE;
9425
9426 - if (ast_strlen_zero(argv[4]))
9427 + if (!argv[4] || ast_strlen_zero(argv[4]))
9428 return RESULT_SHOWUSAGE;
9429
9430 + if (!argv[5])
9431 + return RESULT_SHOWUSAGE;
9432 +
9433 + if (!argv[6] || ast_strlen_zero(argv[6]))
9434 + return RESULT_SHOWUSAGE;
9435 +
9436 + span = atoi(argv[6]);
9437 + if ((span < 1) && (span > NUM_SPANS)) {
9438 + return RESULT_SUCCESS;
9439 + }
9440 +
9441 +
9442 myfd = open(argv[4], O_CREAT|O_WRONLY);
9443 if (myfd < 0) {
9444 - ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9445 - return RESULT_SUCCESS;
9446 + ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9447 + return RESULT_SUCCESS;
9448 }
9449 -
9450 - ast_mutex_lock(&pridebugfdlock);
9451 -
9452 - if (pridebugfd >= 0)
9453 - close(pridebugfd);
9454 -
9455 - pridebugfd = myfd;
9456 - ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
9457 -
9458 - ast_mutex_unlock(&pridebugfdlock);
9459 -
9460 - ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
9461 + for (x=0; x < NUM_SPANS; x++) {
9462 + ast_mutex_lock(&pris[x].lock);
9463 +
9464 + if (pris[x].span == span) {
9465 + if (pris[x].debugfd >= 0)
9466 + close(pris[x].debugfd);
9467 + pris[x].debugfd = myfd;
9468 + for (d=0; d < NUM_DCHANS; d++) {
9469 + if (pris[x].dchans[d])
9470 + pri_set_debug_fd(pris[x].dchans[d], myfd);
9471 + }
9472 + }
9473 + ast_mutex_unlock(&pris[x].lock);
9474 + }
9475 +
9476 + ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
9477 } else {
9478 + if (!argv[5] || ast_strlen_zero(argv[5]))
9479 + return RESULT_SHOWUSAGE;
9480 /* Assume it is unset */
9481 - ast_mutex_lock(&pridebugfdlock);
9482 - close(pridebugfd);
9483 - pridebugfd = -1;
9484 - ast_cli(fd, "PRI debug output to file disabled\n");
9485 - ast_mutex_unlock(&pridebugfdlock);
9486 + span = atoi(argv[5]);
9487 + if ((span < 1) && (span > NUM_SPANS)) {
9488 + return RESULT_SUCCESS;
9489 + }
9490 +
9491 + for (x=0; x < NUM_SPANS; x++) {
9492 + ast_mutex_lock(&pris[x].lock);
9493 +
9494 + if (pris[x].span == span) {
9495 + if (pris[x].debugfd >= 0)
9496 + close(pris[x].debugfd);
9497 + pris[x].debugfd = -1;
9498 + for (d=0; d < NUM_DCHANS; d++) {
9499 + if (pris[x].dchans[d])
9500 + pri_set_debug_fd(pris[x].dchans[d], -1);
9501 + }
9502 + }
9503 + ast_mutex_unlock(&pris[x].lock);
9504 + }
9505 +
9506 + ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
9507 }
9508
9509 return RESULT_SUCCESS;
9510 @@ -9234,6 +10673,7 @@
9511
9512
9513
9514 +
9515 static int handle_pri_no_debug(int fd, int argc, char *argv[])
9516 {
9517 int span;
9518 @@ -9340,36 +10780,6 @@
9519 return RESULT_SUCCESS;
9520 }
9521
9522 -static int handle_pri_show_debug(int fd, int argc, char *argv[])
9523 -{
9524 - int x;
9525 - int span;
9526 - int count=0;
9527 - int debug=0;
9528 -
9529 - for(span=0;span<NUM_SPANS;span++) {
9530 - if (pris[span].pri) {
9531 - for(x=0;x<NUM_DCHANS;x++) {
9532 - debug=0;
9533 - if (pris[span].dchans[x]) {
9534 - debug = pri_get_debug(pris[span].dchans[x]);
9535 - ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
9536 - count++;
9537 - }
9538 - }
9539 - }
9540 -
9541 - }
9542 - ast_mutex_lock(&pridebugfdlock);
9543 - if (pridebugfd >= 0)
9544 - ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
9545 - ast_mutex_unlock(&pridebugfdlock);
9546 -
9547 - if (!count)
9548 - ast_cli(fd, "No debug set or no PRI running\n");
9549 - return RESULT_SUCCESS;
9550 -}
9551 -
9552 static char pri_debug_help[] =
9553 "Usage: pri debug span <span>\n"
9554 " Enables debugging on a given PRI span\n";
9555 @@ -9386,6 +10796,18 @@
9556 "Usage: pri show span <span>\n"
9557 " Displays PRI Information\n";
9558
9559 +static char bri_debug_help[] =
9560 + "Usage: bri debug span <span>\n"
9561 + " Enables debugging on a given BRI span\n";
9562 +
9563 +static char bri_no_debug_help[] =
9564 + "Usage: bri no debug span <span>\n"
9565 + " Disables debugging on a given BRI span\n";
9566 +
9567 +static char bri_really_debug_help[] =
9568 + "Usage: bri intensive debug span <span>\n"
9569 + " Enables debugging down to the Q.921 level\n";
9570 +
9571 static struct ast_cli_entry zap_pri_cli[] = {
9572 { { "pri", "debug", "span", NULL }, handle_pri_debug,
9573 "Enables PRI debugging on a span", pri_debug_help, complete_span_4 },
9574 @@ -9393,19 +10815,282 @@
9575 "Disables PRI debugging on a span", pri_no_debug_help, complete_span_5 },
9576 { { "pri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
9577 "Enables REALLY INTENSE PRI debugging", pri_really_debug_help, complete_span_5 },
9578 + { { "bri", "debug", "span", NULL }, handle_pri_debug,
9579 + "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
9580 + { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
9581 + "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
9582 + { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
9583 + "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
9584 { { "pri", "show", "span", NULL }, handle_pri_show_span,
9585 "Displays PRI Information", pri_show_span_help, complete_span_4 },
9586 - { { "pri", "show", "debug", NULL }, handle_pri_show_debug,
9587 - "Displays current PRI debug settings" },
9588 { { "pri", "set", "debug", "file", NULL }, handle_pri_set_debug_file,
9589 "Sends PRI debug output to the specified file" },
9590 - { { "pri", "unset", "debug", "file", NULL }, handle_pri_set_debug_file,
9591 + { { "pri", "unset", "debug", "file", "span", NULL }, handle_pri_set_debug_file,
9592 "Ends PRI debug output to file" },
9593 };
9594
9595 +static char *zapCD_tdesc = "Call Deflection";
9596 +static char *zapCD_app = "zapCD";
9597 +static char *zapCD_synopsis = "Call Deflection";
9598 +
9599 +static int app_zapCD(struct ast_channel *chan, void *data)
9600 +{
9601 + struct zt_pvt *p = chan->tech_pvt;
9602 +
9603 + if(!data) {
9604 + ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
9605 + return -1;
9606 + }
9607 + return pri_deflect(p->pri->pri, p->call, data);
9608 +}
9609 +
9610 +static char *zapInband_tdesc = "Inband Call Progress (pre-answer)";
9611 +static char *zapInband_app = "zapInband";
9612 +static char *zapInband_synopsis = "Inband Call Progress";
9613 +
9614 +static int app_zapInband(struct ast_channel *chan, void *data)
9615 +{
9616 + struct zt_pvt *p = chan->tech_pvt;
9617 +
9618 + return pri_acknowledge(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1);
9619 +}
9620 #endif /* ZAPATA_PRI */
9621
9622
9623 +#ifdef ZAPATA_GSM
9624 +static int handle_gsm_debug_helper(int fd, int channel, int debug)
9625 +{
9626 +/* gsm debug channel <channel> */
9627 + struct zt_pvt *pvt = NULL;
9628 + if (channel < 1) {
9629 + ast_cli(fd, "Invalid channel %d. Should be a number.\n", channel);
9630 + return RESULT_SUCCESS;
9631 + }
9632 + pvt = iflist;
9633 + while (pvt) {
9634 + if (pvt->channel == channel) {
9635 + ast_mutex_lock(&pvt->lock);
9636 + gsm_set_debug(pvt->gsm.modul, debug);
9637 + ast_mutex_unlock(&pvt->lock);
9638 + ast_cli(fd, "%s debugging on channel %d\n", debug ? "Enabled":"Disabled", channel);
9639 + return RESULT_SUCCESS;
9640 + }
9641 + pvt = pvt->next;
9642 + }
9643 +
9644 + ast_cli(fd, "No GSM running on channel %d\n", channel);
9645 + return RESULT_SUCCESS;
9646 +}
9647 +
9648 +
9649 +
9650 +static int handle_gsm_debug(int fd, int argc, char *argv[])
9651 +{
9652 +/* gsm debug channel <channel> */
9653 + int channel;
9654 + if (argc < 4) {
9655 + return RESULT_SHOWUSAGE;
9656 + }
9657 + channel = atoi(argv[3]);
9658 + return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_AT);
9659 +}
9660 +
9661 +static int handle_gsm_no_debug(int fd, int argc, char *argv[])
9662 +{
9663 +/* gsm no debug channel <channel> */
9664 + int channel;
9665 + if (argc < 5) {
9666 + return RESULT_SHOWUSAGE;
9667 + }
9668 + channel = atoi(argv[4]);
9669 + return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_NONE);
9670 +}
9671 +
9672 +static char gsm_debug_help[] =
9673 + "Usage: gsm debug channel <channel>\n"
9674 + " Enables debugging on a given GSM channel\n";
9675 +
9676 +static char gsm_no_debug_help[] =
9677 + "Usage: gsm no debug channel <channel>\n"
9678 + " Disables debugging on a given GSM channel\n";
9679 +
9680 +static struct ast_cli_entry zap_gsm_cli[] = {
9681 + { { "gsm", "debug", "channel", NULL }, handle_gsm_debug,
9682 + "Enables GSM debugging on a channel", gsm_debug_help },
9683 + { { "gsm", "no", "debug", "channel", NULL }, handle_gsm_no_debug,
9684 + "Disables GSM debugging on a channel", gsm_no_debug_help},
9685 +};
9686 +
9687 +
9688 +
9689 +static char gsm_send_pdu_help[] =
9690 + "Usage: gsm send pdu <channel> <length> <pdu>\n"
9691 + " Sends a PDU on a GSM channel\n";
9692 +
9693 +
9694 +static int handle_gsm_send_pdu(int fd, int argc, char *argv[])
9695 +{
9696 +/* gsm send sms <channel> <destination> <message> */
9697 + int channel;
9698 + int len;
9699 + struct zt_pvt *pvt = NULL;
9700 + if (argc < 6) {
9701 + return RESULT_SHOWUSAGE;
9702 + }
9703 + channel = atoi(argv[3]);
9704 + if (channel < 1) {
9705 + ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
9706 + return RESULT_SUCCESS;
9707 + }
9708 + len = atoi(argv[4]);
9709 + if (len < 1) {
9710 + ast_cli(fd, "Invalid length %s. Should be a number.\n", argv[4]);
9711 + return RESULT_SUCCESS;
9712 + }
9713 + pvt = iflist;
9714 + while (pvt) {
9715 + if (pvt->channel == channel) {
9716 + if (pvt->owner) {
9717 + ast_cli(fd, "Channel in use.\n");
9718 + return RESULT_FAILURE;
9719 + } else {
9720 + ast_mutex_lock(&pvt->lock);
9721 + gsm_sms_send_pdu(pvt->gsm.modul, argv[5], len);
9722 + ast_mutex_unlock(&pvt->lock);
9723 + return RESULT_SUCCESS;
9724 + }
9725 + }
9726 + pvt = pvt->next;
9727 + }
9728 +
9729 + return RESULT_SUCCESS;
9730 +}
9731 +
9732 +static struct ast_cli_entry gsm_send_pdu = {
9733 + { "gsm", "send", "pdu", NULL }, handle_gsm_send_pdu, "Sends a SM on a GSM channel", gsm_send_pdu_help, complete_span_4 };
9734 +
9735 +
9736 +static char gsm_send_sms_help[] =
9737 + "Usage: gsm send sms <channel> <destination> <message>\n"
9738 + " Sends a SM on a GSM channel\n";
9739 +
9740 +
9741 +static int handle_gsm_send_sms(int fd, int argc, char *argv[])
9742 +{
9743 +/* gsm send sms <channel> <destination> <message> */
9744 + int channel;
9745 + struct zt_pvt *pvt = NULL;
9746 + if (argc < 6) {
9747 + return RESULT_SHOWUSAGE;
9748 + }
9749 + channel = atoi(argv[3]);
9750 + if (channel < 1) {
9751 + ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
9752 + return RESULT_SUCCESS;
9753 + }
9754 + pvt = iflist;
9755 + while (pvt) {
9756 + if (pvt->channel == channel) {
9757 + if (pvt->owner) {
9758 + ast_cli(fd, "Channel in use.\n");
9759 + return RESULT_FAILURE;
9760 + } else {
9761 + ast_mutex_lock(&pvt->lock);
9762 + gsm_sms_send_text(pvt->gsm.modul, argv[4], argv[5]);
9763 + ast_mutex_unlock(&pvt->lock);
9764 + return RESULT_SUCCESS;
9765 + }
9766 + }
9767 + pvt = pvt->next;
9768 + }
9769 +
9770 + return RESULT_SUCCESS;
9771 +}
9772 +
9773 +static struct ast_cli_entry gsm_send_sms = {
9774 + { "gsm", "send", "sms", NULL }, handle_gsm_send_sms, "Sends a SM on a GSM channel", gsm_send_sms_help, complete_span_4 };
9775 +
9776 +static char gsm_show_status_help[] =
9777 + "Usage: gsm show status <channel>>\n"
9778 + " Displays status information about the GSM channel.\n";
9779 +
9780 +
9781 +static int handle_gsm_show_status(int fd, int argc, char *argv[])
9782 +{
9783 + int channel;
9784 + struct zt_pvt *pvt = NULL;
9785 + if (argc < 4) {
9786 + return RESULT_SHOWUSAGE;
9787 + }
9788 + channel = atoi(argv[3]);
9789 + if (channel < 1) {
9790 + ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
9791 + return RESULT_SUCCESS;
9792 + }
9793 + pvt = iflist;
9794 + while (pvt) {
9795 + if (pvt->channel == channel) {
9796 + if (pvt->owner) {
9797 + ast_cli(fd, "Channel in use.\n");
9798 + return RESULT_FAILURE;
9799 + } else {
9800 + ast_mutex_lock(&pvt->lock);
9801 + gsm_request_status(pvt->gsm.modul);
9802 + ast_mutex_unlock(&pvt->lock);
9803 + return RESULT_SUCCESS;
9804 + }
9805 + }
9806 + pvt = pvt->next;
9807 + }
9808 +
9809 + return RESULT_SUCCESS;
9810 +}
9811 +
9812 +static struct ast_cli_entry gsm_show_status = {
9813 + { "gsm", "show", "status", NULL }, handle_gsm_show_status, "Displays status information about the GSM channel.", gsm_show_status_help, complete_span_4 };
9814 +
9815 +#endif /* ZAPATA_GSM */
9816 +
9817 +static int app_zapEC(struct ast_channel *chan, void *data)
9818 +{
9819 + int res=-1;
9820 + struct zt_pvt *p = NULL;
9821 +
9822 + if (!data) {
9823 + ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
9824 + }
9825 + if (chan && !strcasecmp("ZAP",chan->type)) {
9826 + p = chan->tech_pvt;
9827 + if (!p) return res;
9828 + if (!strcasecmp("on",(char *)data)) {
9829 + zt_enable_ec(p);
9830 + res = 0;
9831 + if (option_verbose > 3) {
9832 + ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
9833 + }
9834 + } else if (!strcasecmp("off",(char *)data)) {
9835 + zt_disable_ec(p);
9836 + res = 0;
9837 + if (option_verbose > 3) {
9838 + ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
9839 + }
9840 + } else {
9841 + ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
9842 + }
9843 + } else {
9844 + ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
9845 + res = 0;
9846 + }
9847 +
9848 + return res;
9849 +}
9850 +
9851 +static char *zapEC_tdesc = "Enable/disable Echo cancelation";
9852 +static char *zapEC_app = "zapEC";
9853 +static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
9854 +
9855 +
9856 +
9857 #ifdef ZAPATA_R2
9858 static int handle_r2_no_debug(int fd, int argc, char *argv[])
9859 {
9860 @@ -10017,6 +11702,14 @@
9861 pthread_cancel(pris[i].master);
9862 }
9863 ast_cli_unregister_multiple(zap_pri_cli, sizeof(zap_pri_cli) / sizeof(zap_pri_cli[0]));
9864 + ast_unregister_application(zapCD_app);
9865 + ast_unregister_application(zapInband_app);
9866 +#endif
9867 +#ifdef ZAPATA_GSM
9868 + ast_cli_unregister_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
9869 + ast_cli_unregister(&gsm_send_sms);
9870 + ast_cli_unregister(&gsm_send_pdu);
9871 + ast_cli_unregister(&gsm_show_status);
9872 #endif
9873 #ifdef ZAPATA_R2
9874 ast_cli_unregister_multiple(zap_r2_cli, sizeof(zap_r2_cli) / sizeof(zap_r2_cli[0]));
9875 @@ -10028,6 +11721,7 @@
9876 ast_manager_unregister( "ZapDNDoff" );
9877 ast_manager_unregister( "ZapDNDon" );
9878 ast_manager_unregister("ZapShowChannels");
9879 + ast_unregister_application(zapEC_app);
9880 ast_channel_unregister(&zap_tech);
9881 if (!ast_mutex_lock(&iflock)) {
9882 /* Hangup all interfaces if they have an owner */
9883 @@ -10386,8 +12080,8 @@
9884 }
9885 } else if (!strcasecmp(v->name, "echotraining")) {
9886 if (sscanf(v->value, "%d", &y) == 1) {
9887 - if ((y < 10) || (y > 4000)) {
9888 - ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 2000 ms at line %d\n", v->lineno);
9889 + if ((y < 10) || (y > 1000)) {
9890 + ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 1000 ms at line %d\n", v->lineno);
9891 } else {
9892 echotraining = y;
9893 }
9894 @@ -10573,12 +12267,33 @@
9895 cur_signalling = SIG_GR303FXSKS;
9896 cur_radio = 0;
9897 pritype = PRI_CPE;
9898 + } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
9899 + cur_radio = 0;
9900 + cur_signalling = SIG_PRI;
9901 + pritype = BRI_NETWORK_PTMP;
9902 + } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
9903 + cur_signalling = SIG_PRI;
9904 + cur_radio = 0;
9905 + pritype = BRI_CPE_PTMP;
9906 + } else if (!strcasecmp(v->value, "bri_net")) {
9907 + cur_radio = 0;
9908 + cur_signalling = SIG_PRI;
9909 + pritype = BRI_NETWORK;
9910 + } else if (!strcasecmp(v->value, "bri_cpe")) {
9911 + cur_signalling = SIG_PRI;
9912 + cur_radio = 0;
9913 + pritype = BRI_CPE;
9914 #endif
9915 #ifdef ZAPATA_R2
9916 } else if (!strcasecmp(v->value, "r2")) {
9917 cur_signalling = SIG_R2;
9918 cur_radio = 0;
9919 #endif
9920 +#ifdef ZAPATA_GSM
9921 + } else if (!strcasecmp(v->value, "gsm")) {
9922 + cur_signalling = SIG_GSM;
9923 + cur_radio = 0;
9924 +#endif
9925 } else {
9926 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
9927 }
9928 @@ -10661,8 +12376,20 @@
9929 priindication_oob = 1;
9930 else if (!strcasecmp(v->value, "inband"))
9931 priindication_oob = 0;
9932 + else if (!strcasecmp(v->value, "passthrough"))
9933 + priindication_oob = 2;
9934 + else
9935 + ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' , 'outofband' or 'passthrough' at line %d\n",
9936 + v->value, v->lineno);
9937 + } else if (!strcasecmp(v->name, "pritransfer")) {
9938 + if (!strcasecmp(v->value, "no"))
9939 + pritransfer = 0;
9940 + else if (!strcasecmp(v->value, "ect"))
9941 + pritransfer = 1;
9942 + else if (!strcasecmp(v->value, "hangup"))
9943 + pritransfer = 2;
9944 else
9945 - ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
9946 + ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
9947 v->value, v->lineno);
9948 } else if (!strcasecmp(v->name, "priexclusive")) {
9949 cur_priexclusive = ast_true(v->value);
9950 @@ -10676,6 +12403,14 @@
9951 ast_copy_string(privateprefix, v->value, sizeof(privateprefix));
9952 } else if (!strcasecmp(v->name, "unknownprefix")) {
9953 ast_copy_string(unknownprefix, v->value, sizeof(unknownprefix));
9954 + } else if (!strcasecmp(v->name, "nocid")) {
9955 + ast_copy_string(nocid, v->value, sizeof(nocid) - 1);
9956 + } else if (!strcasecmp(v->name, "withheldcid")) {
9957 + ast_copy_string(withheldcid, v->value, sizeof(withheldcid) - 1);
9958 + } else if (!strcasecmp(v->name, "pin")) {
9959 + ast_copy_string(gsm_modem_pin, v->value, sizeof(gsm_modem_pin) - 1);
9960 + } else if (!strcasecmp(v->name, "exten")) {
9961 + ast_copy_string(gsm_modem_exten, v->value, sizeof(gsm_modem_exten) - 1);
9962 } else if (!strcasecmp(v->name, "resetinterval")) {
9963 if (!strcasecmp(v->value, "never"))
9964 resetinterval = -1;
9965 @@ -10692,6 +12427,8 @@
9966 ast_copy_string(idleext, v->value, sizeof(idleext));
9967 } else if (!strcasecmp(v->name, "idledial")) {
9968 ast_copy_string(idledial, v->value, sizeof(idledial));
9969 + } else if (!strcasecmp(v->name, "pritrustusercid")) {
9970 + usercid = ast_true(v->value);
9971 } else if (!strcasecmp(v->name, "overlapdial")) {
9972 overlapdial = ast_true(v->value);
9973 } else if (!strcasecmp(v->name, "pritimer")) {
9974 @@ -10877,6 +12614,7 @@
9975 #ifdef ZAPATA_PRI
9976 if (!reload) {
9977 for (x=0;x<NUM_SPANS;x++) {
9978 + pris[x].debugfd = -1;
9979 if (pris[x].pvts[0]) {
9980 if (start_pri(pris + x)) {
9981 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
9982 @@ -10909,6 +12647,10 @@
9983 pri_set_error(zt_pri_error);
9984 pri_set_message(zt_pri_message);
9985 #endif
9986 +#ifdef ZAPATA_GSM
9987 + gsm_set_error(zt_gsm_error);
9988 + gsm_set_message(zt_gsm_message);
9989 +#endif
9990 res = setup_zap(0);
9991 /* Make sure we can register our Zap channel type */
9992 if(res) {
9993 @@ -10926,6 +12668,12 @@
9994 ast_cli_register_multiple(zap_r2_cli, sizeof(zap_r2_cli) / sizeof(zap_r2_cli[0]));
9995 #endif
9996 ast_cli_register_multiple(zap_cli, sizeof(zap_cli) / sizeof(zap_cli[0]));
9997 +#ifdef ZAPATA_GSM
9998 + ast_cli_register(&gsm_send_sms);
9999 + ast_cli_register(&gsm_send_pdu);
10000 + ast_cli_register(&gsm_show_status);
10001 + ast_cli_register_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
10002 +#endif
10003
10004 memset(round_robin, 0, sizeof(round_robin));
10005 ast_manager_register( "ZapTransfer", 0, action_transfer, "Transfer Zap Channel" );
10006 @@ -10934,11 +12682,47 @@
10007 ast_manager_register( "ZapDNDon", 0, action_zapdndon, "Toggle Zap channel Do Not Disturb status ON" );
10008 ast_manager_register( "ZapDNDoff", 0, action_zapdndoff, "Toggle Zap channel Do Not Disturb status OFF" );
10009 ast_manager_register("ZapShowChannels", 0, action_zapshowchannels, "Show status zapata channels");
10010 -
10011 + ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
10012 +#ifdef ZAPATA_PRI
10013 + ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
10014 + ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
10015 +#endif
10016 return res;
10017 }
10018
10019 +#ifdef ZAPATA_PRI
10020 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text);
10021 +
10022 +static int zt_pri_sendtext(struct ast_channel *c, const char *text) {
10023 + struct zt_pvt *p = c->tech_pvt;
10024 + if (!p) return -1;
10025 + if (!p->pri) return -1;
10026 + if (strlen(text)) {
10027 + if (p->pri) {
10028 + if (!pri_grab(p, p->pri)) {
10029 + // ast_log(LOG_NOTICE, "Sending Display IE '%s'\n", text);
10030 + pri_information_display(p->pri->pri,p->call,(char *)text);
10031 + pri_rel(p->pri);
10032 + } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
10033 + }
10034 + }
10035 + return 0;
10036 +}
10037 +
10038 +static int zt_sendtext(struct ast_channel *c, const char *text) {
10039 + struct zt_pvt *p = c->tech_pvt;
10040 + if (!p) return -1;
10041 + if (p->sig == SIG_PRI) {
10042 + return zt_pri_sendtext(c, text);
10043 + } else {
10044 + return zt_tdd_sendtext(c, text);
10045 + }
10046 +}
10047 +
10048 +static int zt_tdd_sendtext(struct ast_channel *c, const char *text)
10049 +#else
10050 static int zt_sendtext(struct ast_channel *c, const char *text)
10051 +#endif
10052 {
10053 #define END_SILENCE_LEN 400
10054 #define HEADER_MS 50
10055 @@ -10957,6 +12741,7 @@
10056 float scont = 0.0;
10057 int index;
10058
10059 +
10060 index = zt_get_index(c, p, 0);
10061 if (index < 0) {
10062 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
10063 diff -urN asterisk-1.2.10.orig/codecs/codec_ilbc.c asterisk-1.2.10/codecs/codec_ilbc.c
10064 --- asterisk-1.2.10.orig/codecs/codec_ilbc.c 2005-11-29 19:24:39.000000000 +0100
10065 +++ asterisk-1.2.10/codecs/codec_ilbc.c 2006-07-31 14:13:08.000000000 +0200
10066 @@ -49,7 +49,7 @@
10067 #include "slin_ilbc_ex.h"
10068 #include "ilbc_slin_ex.h"
10069
10070 -#define USE_ILBC_ENHANCER 0
10071 +#define USE_ILBC_ENHANCER 1
10072 #define ILBC_MS 30
10073 /* #define ILBC_MS 20 */
10074
10075 diff -urN asterisk-1.2.10.orig/configs/capi.conf.sample asterisk-1.2.10/configs/capi.conf.sample
10076 --- asterisk-1.2.10.orig/configs/capi.conf.sample 1970-01-01 01:00:00.000000000 +0100
10077 +++ asterisk-1.2.10/configs/capi.conf.sample 2006-07-31 14:13:08.000000000 +0200
10078 @@ -0,0 +1,44 @@
10079 +;
10080 +; CAPI config
10081 +;
10082 +;
10083 +[general]
10084 +nationalprefix=0
10085 +internationalprefix=00
10086 +rxgain=0.8
10087 +txgain=0.8
10088 +
10089 +[interfaces]
10090 +
10091 +; mode: ptmp (point-to-multipoint) or ptp (point-to-point)
10092 +isdnmode=ptmp
10093 +; allow incoming calls to this list of MSNs, * == any
10094 +incomingmsn=*
10095 +; capi controller number
10096 +controller=1
10097 +; dialout group
10098 +group=1
10099 +; enable/disable software dtmf detection, recommended for AVM cards
10100 +softdtmf=1
10101 +; accountcode to use in CDRs
10102 +accountcode=
10103 +; context for incoming calls
10104 +context=capi-in
10105 +; _VERY_PRIMITIVE_ echo suppression
10106 +;echosquelch=1
10107 +; EICON DIVA SERVER echo cancelation
10108 +;echocancel=yes
10109 +;echotail=64
10110 +; call group
10111 +;callgroup=1
10112 +; deflect incoming calls to 12345678 if all B channels are busy
10113 +;deflect=12345678
10114 +; number of concurrent calls on this controller (2 makes sense for single BRI)
10115 +devices => 2
10116 +
10117 +
10118 +;PointToPoint (55512-0)
10119 +;isdnmode=ptp
10120 +;msn=55512
10121 +;controller=2
10122 +;devices => 30
10123 diff -urN asterisk-1.2.10.orig/configs/modules.conf.sample asterisk-1.2.10/configs/modules.conf.sample
10124 --- asterisk-1.2.10.orig/configs/modules.conf.sample 2005-11-29 19:24:39.000000000 +0100
10125 +++ asterisk-1.2.10/configs/modules.conf.sample 2006-07-31 14:13:08.000000000 +0200
10126 @@ -51,3 +51,4 @@
10127 ; exported to modules loaded after them.
10128 ;
10129 [global]
10130 +chan_capi.so=yes
10131 diff -urN asterisk-1.2.10.orig/configs/watchdog.conf.sample asterisk-1.2.10/configs/watchdog.conf.sample
10132 --- asterisk-1.2.10.orig/configs/watchdog.conf.sample 1970-01-01 01:00:00.000000000 +0100
10133 +++ asterisk-1.2.10/configs/watchdog.conf.sample 2006-07-31 14:13:08.000000000 +0200
10134 @@ -0,0 +1,22 @@
10135 +;
10136 +; Configuration file for res_watchdog
10137 +;
10138 +; type = isdnguard | watchdog
10139 +; device = /dev/...
10140 +; interval = interval to trigger the watchdog in ms
10141 +
10142 +;[ISDNguard-direct]
10143 +;type = isdnguard
10144 +;device = /dev/ttyS0
10145 +;interval = 200
10146 +
10147 +;[ISDNguard-with-daemon]
10148 +;type = isdnguard
10149 +;device = /var/run/guard.ctl
10150 +;interval = 200
10151 +
10152 +;[kernel_watchdog]
10153 +;type = watchdog
10154 +;device = /dev/watchdog
10155 +;interval = 100
10156 +
10157 diff -urN asterisk-1.2.10.orig/configs/zapata.conf.sample asterisk-1.2.10/configs/zapata.conf.sample
10158 --- asterisk-1.2.10.orig/configs/zapata.conf.sample 2006-04-28 18:40:32.000000000 +0200
10159 +++ asterisk-1.2.10/configs/zapata.conf.sample 2006-07-31 14:13:08.000000000 +0200
10160 @@ -121,9 +121,20 @@
10161 ;
10162 ; outofband: Signal Busy/Congestion out of band with RELEASE/DISCONNECT
10163 ; inband: Signal Busy/Congestion using in-band tones
10164 +; passthrough: Listen to the telco
10165 ;
10166 ; priindication = outofband
10167 ;
10168 +; PRI/BRI transfers (HOLD -> SETUP -> ECT/Hangup)
10169 +;
10170 +; Configure how transfers are initiated. ECT should be preferred
10171 +;
10172 +; no: no transfers allowed (results in hangup)
10173 +; ect: use ECT (facility)
10174 +: hangup: transfer on hangup (if your phones dont support ECT)
10175 +;
10176 +; pritransfer = ect
10177 +;
10178 ; If you need to override the existing channels selection routine and force all
10179 ; PRI channels to be marked as exclusively selected, set this to yes.
10180 ; priexclusive = yes
10181 diff -urN asterisk-1.2.10.orig/db.c asterisk-1.2.10/db.c
10182 --- asterisk-1.2.10.orig/db.c 2006-01-09 19:09:53.000000000 +0100
10183 +++ asterisk-1.2.10/db.c 2006-07-31 14:13:08.000000000 +0200
10184 @@ -516,11 +516,18 @@
10185 struct ast_cli_entry cli_database_deltree =
10186 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
10187
10188 +static char mandescr_dbput[] =
10189 +"Description: Put a value into astdb\n"
10190 +"Variables: \n"
10191 +" Family: ...\n"
10192 +" Key: ...\n"
10193 +" Value: ...\n";
10194 +
10195 static int manager_dbput(struct mansession *s, struct message *m)
10196 {
10197 char *family = astman_get_header(m, "Family");
10198 char *key = astman_get_header(m, "Key");
10199 - char *val = astman_get_header(m, "Val");
10200 + char *val = astman_get_header(m, "Value");
10201 int res;
10202
10203 if (!strlen(family)) {
10204 @@ -545,6 +552,12 @@
10205 return 0;
10206 }
10207
10208 +static char mandescr_dbget[] =
10209 +"Description: Get a value from astdb\n"
10210 +"Variables: \n"
10211 +" Family: ...\n"
10212 +" Key: ...\n";
10213 +
10214 static int manager_dbget(struct mansession *s, struct message *m)
10215 {
10216 char *id = astman_get_header(m,"ActionID");
10217 @@ -574,7 +587,7 @@
10218 ast_cli(s->fd, "Event: DBGetResponse\r\n"
10219 "Family: %s\r\n"
10220 "Key: %s\r\n"
10221 - "Val: %s\r\n"
10222 + "Value: %s\r\n"
10223 "%s"
10224 "\r\n",
10225 family, key, tmp, idText);
10226 @@ -582,6 +595,39 @@
10227 return 0;
10228 }
10229
10230 +static char mandescr_dbdel[] =
10231 +"Description: remove value from astdb\n"
10232 +"Variables: \n"
10233 +" Family: ...\n"
10234 +" Key: ...\n";
10235 +
10236 +static int manager_dbdel(struct mansession *s, struct message *m)
10237 +{
10238 + char *family = astman_get_header(m, "Family");
10239 + char *key = astman_get_header(m, "Key");
10240 + char *id = astman_get_header(m,"ActionID");
10241 +
10242 + if (!strlen(family)) {
10243 + astman_send_error(s, m, "No family specified");
10244 + return 0;
10245 + }
10246 + if (!strlen(key)) {
10247 + astman_send_error(s, m, "No key specified");
10248 + return 0;
10249 + }
10250 +
10251 + if (ast_db_del(family, key)) {
10252 + ast_cli(s->fd, "Response: Failed\r\n");
10253 + } else {
10254 + ast_cli(s->fd, "Response: Success\r\n");
10255 + }
10256 + if (id && !ast_strlen_zero(id))
10257 + ast_cli(s->fd, "ActionID: %s\r\n",id);
10258 + ast_cli(s->fd, "\r\n");
10259 +
10260 + return 0;
10261 +}
10262 +
10263 int astdb_init(void)
10264 {
10265 dbinit();
10266 @@ -591,7 +637,8 @@
10267 ast_cli_register(&cli_database_put);
10268 ast_cli_register(&cli_database_del);
10269 ast_cli_register(&cli_database_deltree);
10270 - ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
10271 - ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
10272 + ast_manager_register("DBget", EVENT_FLAG_SYSTEM, manager_dbget, mandescr_dbget);
10273 + ast_manager_register("DBput", EVENT_FLAG_SYSTEM, manager_dbput, mandescr_dbput);
10274 + ast_manager_register("DBdel", EVENT_FLAG_SYSTEM, manager_dbdel, mandescr_dbdel);
10275 return 0;
10276 }
10277 diff -urN asterisk-1.2.10.orig/devicestate.c asterisk-1.2.10/devicestate.c
10278 --- asterisk-1.2.10.orig/devicestate.c 2006-02-10 21:38:59.000000000 +0100
10279 +++ asterisk-1.2.10/devicestate.c 2006-07-31 14:13:08.000000000 +0200
10280 @@ -62,6 +62,8 @@
10281
10282 struct state_change {
10283 AST_LIST_ENTRY(state_change) list;
10284 + char cid_num[AST_MAX_EXTENSION];
10285 + char cid_name[AST_MAX_EXTENSION];
10286 char device[1];
10287 };
10288
10289 @@ -177,7 +179,7 @@
10290 }
10291
10292 /*--- do_state_change: Notify callback watchers of change, and notify PBX core for hint updates */
10293 -static void do_state_change(const char *device)
10294 +static void do_state_change(const char *device, char *cid_num, char *cid_name)
10295 {
10296 int state;
10297 struct devstate_cb *devcb;
10298 @@ -188,13 +190,13 @@
10299
10300 AST_LIST_LOCK(&devstate_cbs);
10301 AST_LIST_TRAVERSE(&devstate_cbs, devcb, list)
10302 - devcb->callback(device, state, devcb->data);
10303 + devcb->callback(device, state, devcb->data, cid_num, cid_name);
10304 AST_LIST_UNLOCK(&devstate_cbs);
10305
10306 - ast_hint_state_changed(device);
10307 + ast_hint_state_changed(device, cid_num, cid_name);
10308 }
10309
10310 -static int __ast_device_state_changed_literal(char *buf)
10311 +static int __ast_device_state_changed_literal(char *buf, char *cid_num, char *cid_name)
10312 {
10313 char *device, *tmp;
10314 struct state_change *change = NULL;
10315 @@ -209,10 +211,16 @@
10316 if (!change) {
10317 /* we could not allocate a change struct, or */
10318 /* there is no background thread, so process the change now */
10319 - do_state_change(device);
10320 + do_state_change(device, cid_num, cid_name);
10321 } else {
10322 /* queue the change */
10323 strcpy(change->device, device);
10324 + if (cid_num && (!ast_strlen_zero(cid_num))) {
10325 + strncpy(change->cid_num, cid_num, sizeof(change->cid_num) - 1);
10326 + }
10327 + if (cid_name && (!ast_strlen_zero(cid_name))) {
10328 + strncpy(change->cid_name, cid_name, sizeof(change->cid_name) - 1);
10329 + }
10330 AST_LIST_LOCK(&state_changes);
10331 AST_LIST_INSERT_TAIL(&state_changes, change, list);
10332 if (AST_LIST_FIRST(&state_changes) == change)
10333 @@ -224,11 +232,17 @@
10334 return 1;
10335 }
10336
10337 -int ast_device_state_changed_literal(const char *dev)
10338 +int ast_device_state_changed_literal(const char *dev, const char *cid_num, const char *cid_name)
10339 {
10340 char *buf;
10341 + char *buf2 = NULL;
10342 + char *buf3 = NULL;
10343 buf = ast_strdupa(dev);
10344 - return __ast_device_state_changed_literal(buf);
10345 + if (cid_num)
10346 + buf2 = ast_strdupa(cid_num);
10347 + if (cid_name)
10348 + buf3 = ast_strdupa(cid_name);
10349 + return __ast_device_state_changed_literal(buf, buf2, buf3);
10350 }
10351
10352 /*--- ast_device_state_changed: Accept change notification, add it to change queue */
10353 @@ -240,7 +254,7 @@
10354 va_start(ap, fmt);
10355 vsnprintf(buf, sizeof(buf), fmt, ap);
10356 va_end(ap);
10357 - return __ast_device_state_changed_literal(buf);
10358 + return __ast_device_state_changed_literal(buf, NULL, NULL);
10359 }
10360
10361 /*--- do_devstate_changes: Go through the dev state change queue and update changes in the dev state thread */
10362 @@ -255,7 +269,7 @@
10363 if (cur) {
10364 /* we got an entry, so unlock the list while we process it */
10365 AST_LIST_UNLOCK(&state_changes);
10366 - do_state_change(cur->device);
10367 + do_state_change(cur->device, cur->cid_num, cur->cid_name);
10368 free(cur);
10369 AST_LIST_LOCK(&state_changes);
10370 } else {
10371 diff -urN asterisk-1.2.10.orig/doc/README.asterisk.conf asterisk-1.2.10/doc/README.asterisk.conf
10372 --- asterisk-1.2.10.orig/doc/README.asterisk.conf 2005-11-29 19:24:39.000000000 +0100
10373 +++ asterisk-1.2.10/doc/README.asterisk.conf 2006-07-31 14:13:08.000000000 +0200
10374 @@ -62,6 +62,7 @@
10375 maxcalls = 255 ; The maximum number of concurrent calls you want to allow
10376 execincludes = yes | no ; Allow #exec entries in configuration files
10377 dontwarn = yes | no ; Don't over-inform the Asterisk sysadm, he's a guru
10378 +uniquename = asterisk ; host name part to be included in the uniqueid
10379
10380 [files]
10381 ; Changing the following lines may compromise your security
10382 diff -urN asterisk-1.2.10.orig/editline/cygdef.h asterisk-1.2.10/editline/cygdef.h
10383 --- asterisk-1.2.10.orig/editline/cygdef.h 1970-01-01 01:00:00.000000000 +0100
10384 +++ asterisk-1.2.10/editline/cygdef.h 2006-07-31 14:13:08.000000000 +0200
10385 @@ -0,0 +1,11 @@
10386 +/* cygdef.h. Generated automatically by configure. */
10387 +#ifndef _CYGDEF_H_
10388 +#define _CYGDEF_H_ 1
10389 +#include <sys/ioctl.h>
10390 +#define __linux__ 1
10391 +
10392 +
10393 +typedef void (*sig_t)(int);
10394 +
10395 +
10396 +#endif /* _CYGDEF_H_ */
10397 diff -urN asterisk-1.2.10.orig/include/asterisk/agi.h asterisk-1.2.10/include/asterisk/agi.h
10398 --- asterisk-1.2.10.orig/include/asterisk/agi.h 2005-11-29 19:24:39.000000000 +0100
10399 +++ asterisk-1.2.10/include/asterisk/agi.h 2006-07-31 14:13:08.000000000 +0200
10400 @@ -29,7 +29,8 @@
10401
10402 typedef struct agi_state {
10403 int fd; /* FD for general output */
10404 - int audio; /* FD for audio output */
10405 + int audio_out; /* FD for audio output */
10406 + int audio_in; /* FD for audio output */
10407 int ctrl; /* FD for input control */
10408 } AGI;
10409
10410 diff -urN asterisk-1.2.10.orig/include/asterisk/chan_capi.h asterisk-1.2.10/include/asterisk/chan_capi.h
10411 --- asterisk-1.2.10.orig/include/asterisk/chan_capi.h 1970-01-01 01:00:00.000000000 +0100
10412 +++ asterisk-1.2.10/include/asterisk/chan_capi.h 2006-07-31 14:13:08.000000000 +0200
10413 @@ -0,0 +1,276 @@
10414 +/*
10415 + * (CAPI*)
10416 + *
10417 + * An implementation of Common ISDN API 2.0 for Asterisk
10418 + *
10419 + * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
10420 + *
10421 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
10422 + *
10423 + * This program is free software and may be modified and
10424 + * distributed under the terms of the GNU Public License.
10425 + */
10426 +
10427 +#ifndef _ASTERISK_CAPI_H
10428 +#define _ASTERISK_CAPI_H
10429 +
10430 +#define AST_CAPI_MAX_CONTROLLERS 16
10431 +#define AST_CAPI_MAX_DEVICES 30
10432 +#define AST_CAPI_MAX_BUF 160
10433 +
10434 +#define AST_CAPI_MAX_B3_BLOCKS 7
10435 +
10436 +/* was : 130 bytes Alaw = 16.25 ms audio not suitable for VoIP */
10437 +/* now : 160 bytes Alaw = 20 ms audio */
10438 +/* you can tune this to your need. higher value == more latency */
10439 +#define AST_CAPI_MAX_B3_BLOCK_SIZE 160
10440 +
10441 +#define AST_CAPI_BCHANS 120
10442 +#define ALL_SERVICES 0x1FFF03FF
10443 +
10444 +/* duration in ms for sending and detecting dtmfs */
10445 +#define AST_CAPI_DTMF_DURATION 0x40
10446 +
10447 +#define AST_CAPI_NATIONAL_PREF "0"
10448 +#define AST_CAPI_INTERNAT_PREF "00"
10449 +
10450 +#ifdef CAPI_ES
10451 +#define ECHO_TX_COUNT 5 // 5 x 20ms = 100ms
10452 +#define ECHO_EFFECTIVE_TX_COUNT 3 // 2 x 20ms = 40ms == 40-100ms ... ignore first 40ms
10453 +#define ECHO_TXRX_RATIO 2.3 // if( rx < (txavg/ECHO_TXRX_RATIO) ) rx=0;
10454 +#endif
10455 +
10456 +/*
10457 + * state combination for a normal incoming call:
10458 + * DIS -> ALERT -> CON -> BCON -> CON -> DIS
10459 + *
10460 + * outgoing call:
10461 + * DIS -> CONP -> BCONNECTED -> CON -> DIS
10462 + */
10463 +
10464 +#define CAPI_STATE_ALERTING 1
10465 +#define CAPI_STATE_CONNECTED 2
10466 +#define CAPI_STATE_BCONNECTED 3
10467 +
10468 +#define CAPI_STATE_DISCONNECTING 4
10469 +#define CAPI_STATE_DISCONNECTED 5
10470 +#define CAPI_STATE_REMOTE_HANGUP 6
10471 +
10472 +#define CAPI_STATE_CONNECTPENDING 7
10473 +#define CAPI_STATE_ONHOLD 8
10474 +#define CAPI_STATE_NETWORKHANGUP 9
10475 +#define CAPI_STATE_ANSWERING 10
10476 +#define CAPI_STATE_PUTTINGONHOLD 11
10477 +#define CAPI_STATE_RETRIEVING 12
10478 +
10479 +#define CAPI_STATE_DID 13
10480 +
10481 +#define AST_CAPI_B3_DONT 0
10482 +#define AST_CAPI_B3_ALWAYS 1
10483 +#define AST_CAPI_B3_ON_SUCCESS 2
10484 +
10485 +#ifdef CAPI_GAIN
10486 +struct ast_capi_gains {
10487 + unsigned char txgains[256];
10488 + unsigned char rxgains[256];
10489 +};
10490 +#endif
10491 +
10492 +#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
10493 +#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
10494 +#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
10495 +#define PRES_ALLOWED_NETWORK_NUMBER 0x03
10496 +#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
10497 +#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
10498 +#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
10499 +#define PRES_PROHIB_NETWORK_NUMBER 0x23
10500 +#define PRES_NUMBER_NOT_AVAILABLE 0x43
10501 +
10502 +
10503 +//! Private data for a capi device
10504 +struct ast_capi_pvt {
10505 + ast_mutex_t lock;
10506 + int fd;
10507 +
10508 + /*! Channel we belong to, possibly NULL */
10509 + struct ast_channel *owner;
10510 + /*! Frame */
10511 + struct ast_frame fr;
10512 +
10513 + char offset[AST_FRIENDLY_OFFSET];
10514 +
10515 + // capi message number
10516 + _cword MessageNumber;
10517 + int NCCI;
10518 + int PLCI;
10519 + /* on which controller we do live */
10520 + int controller;
10521 +
10522 + /* we could live on those */
10523 + unsigned long controllers;
10524 +
10525 + int datahandle;
10526 +
10527 + short buf[AST_CAPI_MAX_BUF];
10528 + int buflen;
10529 + /*! Immediate, or wait for an answer */
10530 + int mode;
10531 + /*! State of modem in miniature */
10532 + int state;
10533 + /*! Digits to strip on outgoing numbers */
10534 + int stripmsd;
10535 + /*! ringer timeout */
10536 + int ringt;
10537 + /*! actual time of last ring */
10538 + time_t lastring;
10539 + /*! dtmf receive state/data */
10540 + char dtmfrx;
10541 +
10542 + char context[AST_MAX_EXTENSION];
10543 + /*! Multiple Subscriber Number we listen to (, seperated list) */
10544 + char incomingmsn[AST_MAX_EXTENSION];
10545 + /*! Prefix to Build CID */
10546 + char prefix[AST_MAX_EXTENSION];
10547 + /*! Caller ID if available */
10548 + char cid[AST_MAX_EXTENSION];
10549 + /*! Dialed Number if available */
10550 + char dnid[AST_MAX_EXTENSION];
10551 +
10552 + char accountcode[20];
10553 +
10554 + unsigned int callgroup;
10555 + unsigned int group;
10556 +
10557 + /*! default language */
10558 + char language[MAX_LANGUAGE];
10559 + /*! Static response buffer */
10560 + char response[256];
10561 +
10562 + int calledPartyIsISDN;
10563 + // this is an outgoing channel
10564 + int outgoing;
10565 + // use CLIR
10566 + int CLIR;
10567 + // are we doing early B3 connect on this interface?
10568 + int earlyB3;
10569 + // should we do early B3 on this interface?
10570 + int doB3;
10571 + // store plci here for the call that is onhold
10572 + int onholdPLCI;
10573 + // do software dtmf detection
10574 + int doDTMF;
10575 + // CAPI echo cancellation
10576 + int doEC;
10577 + int ecOption;
10578 + int ecTail;
10579 + // isdnmode ptp or ptm
10580 + int isdnmode;
10581 +#ifdef CAPI_DEFLECT_ON_CIRCUITBUSY
10582 + // deflect on circuitbusy
10583 + char deflect2[AST_MAX_EXTENSION];
10584 +#endif
10585 +
10586 + // not all codecs supply frames in nice 320 byte chunks
10587 + struct ast_smoother *smoother;
10588 + // ok, we stop to be nice and give them the lowest possible latency 130 samples * 2 = 260 bytes */
10589 +#ifdef CAPI_SYNC
10590 + int B3in;
10591 + ast_mutex_t lockB3in;
10592 +#endif
10593 +
10594 + // do ECHO SURPRESSION
10595 + int doES;
10596 +#ifdef CAPI_ES
10597 + short txavg[ECHO_TX_COUNT];
10598 + float rxmin;
10599 + float txmin;
10600 +#endif
10601 +#ifdef CAPI_GAIN
10602 + struct ast_capi_gains g;
10603 +#endif
10604 + float txgain;
10605 + float rxgain;
10606 + struct ast_dsp *vad;
10607 +
10608 +
10609 + struct capi_pipe *mypipe;
10610 + /*! Next channel in list */
10611 + struct ast_capi_pvt *next;
10612 +};
10613 +
10614 +
10615 +struct ast_capi_profile {
10616 + unsigned short ncontrollers;
10617 + unsigned short nbchannels;
10618 + unsigned char globaloptions;
10619 + unsigned char globaloptions2;
10620 + unsigned char globaloptions3;
10621 + unsigned char globaloptions4;
10622 + unsigned int b1protocols;
10623 + unsigned int b2protocols;
10624 + unsigned int b3protocols;
10625 + unsigned int reserved3[6];
10626 + unsigned int manufacturer[5];
10627 +};
10628 +
10629 +struct capi_pipe {
10630 + // lock
10631 + ast_mutex_t lock;
10632 +
10633 + // fd for writing to the channel
10634 + int fd;
10635 +
10636 + // PLCI and NCCI of the B3 CON
10637 + int PLCI;
10638 + int NCCI;
10639 + // pointer to the interface
10640 + struct ast_capi_pvt *i;
10641 + // pointer to the channel
10642 + struct ast_channel *c;
10643 + // next pipe
10644 + struct capi_pipe *next;
10645 +};
10646 +
10647 +struct ast_capi_controller {
10648 + // which controller is this?
10649 + int controller;
10650 + // how many bchans?
10651 + int nbchannels;
10652 + // free bchans
10653 + int nfreebchannels;
10654 + // DID
10655 + int isdnmode;
10656 + // features:
10657 + int dtmf;
10658 + int echocancel;
10659 + int sservices; // supplementray services
10660 + // supported sservices:
10661 + int holdretrieve;
10662 + int terminalportability;
10663 + int ECT;
10664 + int threePTY;
10665 + int CF;
10666 + int CD;
10667 + int MCID;
10668 + int CCBS;
10669 + int MWI;
10670 + int CCNR;
10671 + int CONF;
10672 +};
10673 +
10674 +
10675 +// ETSI 300 102-1 information element identifiers
10676 +#define CAPI_ETSI_IE_CAUSE 0x08;
10677 +#define CAPI_ETSI_IE_PROGRESS_INDICATOR 0x1e;
10678 +#define CAPI_ETSI_IE_CALLED_PARTY_NUMBER 0x70;
10679 +
10680 +// ETIS 300 102-1 message types
10681 +#define CAPI_ETSI_ALERTING 0x01;
10682 +#define CAPI_ETSI_SETUP_ACKKNOWLEDGE 0x0d;
10683 +#define CAPI_ETSI_DISCONNECT 0x45;
10684 +
10685 +// ETSI 300 102-1 Numbering Plans
10686 +#define CAPI_ETSI_NPLAN_NATIONAL 0x20
10687 +#define CAPI_ETSI_NPLAN_INTERNAT 0x10
10688 +
10689 +#endif
10690 diff -urN asterisk-1.2.10.orig/include/asterisk/chan_capi_app.h asterisk-1.2.10/include/asterisk/chan_capi_app.h
10691 --- asterisk-1.2.10.orig/include/asterisk/chan_capi_app.h 1970-01-01 01:00:00.000000000 +0100
10692 +++ asterisk-1.2.10/include/asterisk/chan_capi_app.h 2006-07-31 14:13:08.000000000 +0200
10693 @@ -0,0 +1,30 @@
10694 +/*
10695 + * (CAPI*)
10696 + *
10697 + * An implementation of Common ISDN API 2.0 for Asterisk
10698 + *
10699 + * include file for helper applications
10700 + *
10701 + * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
10702 + *
10703 + * Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
10704 + *
10705 + * This program is free software and may be modified and
10706 + * distributed under the terms of the GNU Public License.
10707 + */
10708 +
10709 +#ifndef _ASTERISK_CAPI_IF_H
10710 +#define _ASTERISK_CAPI_IF_H
10711 +
10712 +// exported symbols from chan_capi
10713 +
10714 +// important things we need
10715 +extern unsigned ast_capi_ApplID;
10716 +extern unsigned ast_capi_MessageNumber;
10717 +extern int capidebug;
10718 +
10719 +extern int capi_call(struct ast_channel *c, char *idest, int timeout);
10720 +extern int capi_detect_dtmf(struct ast_channel *c, int flag);
10721 +extern MESSAGE_EXCHANGE_ERROR _capi_put_cmsg(_cmsg *CMSG);
10722 +
10723 +#endif
10724 diff -urN asterisk-1.2.10.orig/include/asterisk/channel.h asterisk-1.2.10/include/asterisk/channel.h
10725 --- asterisk-1.2.10.orig/include/asterisk/channel.h 2006-06-01 22:27:50.000000000 +0200
10726 +++ asterisk-1.2.10/include/asterisk/channel.h 2006-07-31 14:13:08.000000000 +0200
10727 @@ -86,6 +86,9 @@
10728 #ifndef _ASTERISK_CHANNEL_H
10729 #define _ASTERISK_CHANNEL_H
10730
10731 +/* Max length of the uniqueid */
10732 +#define AST_MAX_UNIQUEID 64
10733 +
10734 #include <unistd.h>
10735 #include <setjmp.h>
10736 #ifdef POLLCOMPAT
10737 @@ -381,7 +384,7 @@
10738 unsigned int fout;
10739
10740 /* Unique Channel Identifier */
10741 - char uniqueid[32];
10742 + char uniqueid[AST_MAX_UNIQUEID];
10743
10744 /* Why is the channel hanged up */
10745 int hangupcause;
10746 @@ -398,6 +401,12 @@
10747 /*! ISDN Transfer Capbility - AST_FLAG_DIGITAL is not enough */
10748 unsigned short transfercapability;
10749
10750 + /*! ISDN Low Layer Compatibility */
10751 + char lowlayercompat[16];
10752 +
10753 + /*! ISDN High Layer Compatibility */
10754 + char highlayercompat[4];
10755 +
10756 struct ast_frame *readq;
10757 int alertpipe[2];
10758 /*! Write translation path */
10759 @@ -534,6 +543,11 @@
10760 #define AST_STATE_MUTE (1 << 16)
10761 /*! @} */
10762
10763 +extern ast_mutex_t uniquelock;
10764 +
10765 +/*! \brief Change the state of a channel and the callerid of the calling channel*/
10766 +int ast_setstate_and_cid(struct ast_channel *chan, int state, char *cid_num, char *cid_name);
10767 +
10768 /*! \brief Change the state of a channel */
10769 int ast_setstate(struct ast_channel *chan, int state);
10770
10771 @@ -570,7 +584,7 @@
10772 * by the low level module
10773 * \return Returns an ast_channel on success, NULL on failure.
10774 */
10775 -struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
10776 +struct ast_channel *ast_request(const char *type, int format, void *data, int *status, char *uniqueid);
10777
10778 /*!
10779 * \brief Request a channel of a given type, with data as optional information used
10780 @@ -585,9 +599,9 @@
10781 * \return Returns an ast_channel on success or no answer, NULL on failure. Check the value of chan->_state
10782 * to know if the call was answered or not.
10783 */
10784 -struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname);
10785 +struct ast_channel *ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, char *uniqueid);
10786
10787 -struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, const char *cidnum, const char *cidname, struct outgoing_helper *oh);
10788 +struct ast_channel *__ast_request_and_dial(const char *type, int format, void *data, int timeout, int *reason, int callingpres, const char *cidnum, const char *cidname, struct outgoing_helper *oh, char *uniqueid);
10789
10790 /*!\brief Register a channel technology (a new channel driver)
10791 * Called by a channel module to register the kind of channels it supports.
10792 @@ -840,6 +854,10 @@
10793 /*--- ast_get_channel_by_exten_locked: Get channel by exten (and optionally context) and lock it */
10794 struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const char *context);
10795
10796 +/*! Get channel by uniqueid (locks channel) */
10797 +struct ast_channel *ast_get_channel_by_uniqueid_locked(const char *uniqueid);
10798 +
10799 +
10800 /*! Waits for a digit */
10801 /*!
10802 * \param c channel to wait for a digit on
10803 @@ -910,6 +928,9 @@
10804 p->owner pointer) that is affected by the change. The physical layer of the original
10805 channel is hung up. */
10806 int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone);
10807 +int ast_channel_masquerade_locked(struct ast_channel *original, struct ast_channel *clone);
10808 +
10809 +char *ast_alloc_uniqueid(void);
10810
10811 /*! Gives the string form of a given cause code */
10812 /*!
10813 diff -urN asterisk-1.2.10.orig/include/asterisk/devicestate.h asterisk-1.2.10/include/asterisk/devicestate.h
10814 --- asterisk-1.2.10.orig/include/asterisk/devicestate.h 2005-11-29 19:24:39.000000000 +0100
10815 +++ asterisk-1.2.10/include/asterisk/devicestate.h 2006-07-31 14:13:08.000000000 +0200
10816 @@ -42,7 +42,7 @@
10817 /*! Device is ringing */
10818 #define AST_DEVICE_RINGING 6
10819
10820 -typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
10821 +typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data, char *cid_num, char *cid_name);
10822
10823 /*! \brief Convert device state to text string for output
10824 * \param devstate Current device state
10825 @@ -84,7 +84,7 @@
10826 * callbacks for the changed extensions
10827 * Returns 0 on success, -1 on failure
10828 */
10829 -int ast_device_state_changed_literal(const char *device);
10830 +int ast_device_state_changed_literal(const char *device, const char *cid_num, const char *cid_name);
10831
10832 /*! \brief Registers a device state change callback
10833 * \param callback Callback
10834 diff -urN asterisk-1.2.10.orig/include/asterisk/features.h asterisk-1.2.10/include/asterisk/features.h
10835 --- asterisk-1.2.10.orig/include/asterisk/features.h 2005-11-29 19:24:39.000000000 +0100
10836 +++ asterisk-1.2.10/include/asterisk/features.h 2006-07-31 14:13:08.000000000 +0200
10837 @@ -45,6 +45,8 @@
10838 };
10839
10840
10841 +extern int ast_autoanswer_login(struct ast_channel *chan, void *data);
10842 +extern int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data);
10843
10844 /*! \brief Park a call and read back parked location
10845 * \param chan the channel to actually be parked
10846 @@ -68,11 +70,19 @@
10847 */
10848 extern int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout);
10849
10850 +extern int ast_hold_call(struct ast_channel *chan, struct ast_channel *host);
10851 +extern int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *host);
10852 +extern int ast_retrieve_call(struct ast_channel *chan, char *uniqueid);
10853 +extern int ast_retrieve_call_to_death(char *uniqueid);
10854 +extern struct ast_channel *ast_get_holded_call(char *uniqueid);
10855 +
10856 /*! \brief Determine system parking extension
10857 * Returns the call parking extension for drivers that provide special
10858 call parking help */
10859 extern char *ast_parking_ext(void);
10860
10861 +extern char *ast_parking_con(void);
10862 +
10863 /*! \brief Determine system call pickup extension */
10864 extern char *ast_pickup_ext(void);
10865
10866 @@ -92,4 +102,12 @@
10867 \param feature the ast_call_feature object which was registered before*/
10868 extern void ast_unregister_feature(struct ast_call_feature *feature);
10869
10870 +/*! \brief find a feature by name
10871 + \param name of the feature to be returned */
10872 +extern struct ast_call_feature *ast_find_feature(char *name);
10873 +
10874 +/*! \brief find a builtin feature by name
10875 + \param name of the feature to be returned */
10876 +extern struct ast_call_feature *ast_find_builtin_feature(char *name);
10877 +
10878 #endif /* _AST_FEATURES_H */
10879 diff -urN asterisk-1.2.10.orig/include/asterisk/manager.h asterisk-1.2.10/include/asterisk/manager.h
10880 --- asterisk-1.2.10.orig/include/asterisk/manager.h 2006-02-11 19:15:00.000000000 +0100
10881 +++ asterisk-1.2.10/include/asterisk/manager.h 2006-07-31 14:13:08.000000000 +0200
10882 @@ -54,6 +54,7 @@
10883 #define EVENT_FLAG_COMMAND (1 << 4) /* Ability to read/set commands */
10884 #define EVENT_FLAG_AGENT (1 << 5) /* Ability to read/set agent info */
10885 #define EVENT_FLAG_USER (1 << 6) /* Ability to read/set user info */
10886 +#define EVENT_FLAG_EXTENSIONSTATUS (1 << 7) /* ExtensionStatus events */
10887
10888 /* Export manager structures */
10889 #define AST_MAX_MANHEADERS 80
10890 diff -urN asterisk-1.2.10.orig/include/asterisk/monitor.h asterisk-1.2.10/include/asterisk/monitor.h
10891 --- asterisk-1.2.10.orig/include/asterisk/monitor.h 2005-11-29 19:24:39.000000000 +0100
10892 +++ asterisk-1.2.10/include/asterisk/monitor.h 2006-07-31 14:13:08.000000000 +0200
10893 @@ -35,6 +35,8 @@
10894 char write_filename[FILENAME_MAX];
10895 char filename_base[FILENAME_MAX];
10896 int filename_changed;
10897 + char target_url[FILENAME_MAX];
10898 + char target_script[FILENAME_MAX];
10899 char *format;
10900 int joinfiles;
10901 int (*stop)(struct ast_channel *chan, int need_lock);
10902 @@ -42,7 +44,7 @@
10903
10904 /* Start monitoring a channel */
10905 int ast_monitor_start(struct ast_channel *chan, const char *format_spec,
10906 - const char *fname_base, int need_lock );
10907 + const char *fname_base, const char *target_url, const char *target_script, int need_lock );
10908
10909 /* Stop monitoring a channel */
10910 int ast_monitor_stop(struct ast_channel *chan, int need_lock);
10911 diff -urN asterisk-1.2.10.orig/include/asterisk/pbx.h asterisk-1.2.10/include/asterisk/pbx.h
10912 --- asterisk-1.2.10.orig/include/asterisk/pbx.h 2006-03-29 21:11:18.000000000 +0200
10913 +++ asterisk-1.2.10/include/asterisk/pbx.h 2006-07-31 14:13:08.000000000 +0200
10914 @@ -57,7 +57,7 @@
10915 AST_EXTENSION_BUSY = 1 << 1,
10916 /*! All devices UNAVAILABLE/UNREGISTERED */
10917 AST_EXTENSION_UNAVAILABLE = 1 << 2,
10918 - /*! All devices RINGING */
10919 + /*! One or more devices RINGING */
10920 AST_EXTENSION_RINGING = 1 << 3,
10921 };
10922
10923 @@ -80,7 +80,7 @@
10924 struct ast_ignorepat;
10925 struct ast_sw;
10926
10927 -typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data);
10928 +typedef int (*ast_state_cb_type)(char *context, char* id, enum ast_extension_states state, void *data, char *cid_num, char *cid_name);
10929
10930 /*! Data structure associated with a custom function */
10931 struct ast_custom_function {
10932 @@ -156,6 +156,8 @@
10933 */
10934 extern struct ast_app *pbx_findapp(const char *app);
10935
10936 +void *ast_pbx_run_app(void *data);
10937 +
10938 /*! executes an application */
10939 /*!
10940 * \param c channel to execute on
10941 @@ -563,11 +565,11 @@
10942
10943 /* Synchronously or asynchronously make an outbound call and send it to a
10944 particular extension */
10945 -int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
10946 +int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
10947
10948 /* Synchronously or asynchronously make an outbound call and send it to a
10949 particular application with given extension */
10950 -int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel);
10951 +int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid);
10952
10953 /* Evaluate a condition for non-falseness and return a boolean */
10954 int pbx_checkcondition(char *condition);
10955 @@ -659,7 +661,7 @@
10956 */
10957 void ast_func_write(struct ast_channel *chan, const char *in, const char *value);
10958
10959 -void ast_hint_state_changed(const char *device);
10960 +void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name);
10961
10962 #if defined(__cplusplus) || defined(c_plusplus)
10963 }
10964 diff -urN asterisk-1.2.10.orig/include/asterisk/xlaw.h asterisk-1.2.10/include/asterisk/xlaw.h
10965 --- asterisk-1.2.10.orig/include/asterisk/xlaw.h 1970-01-01 01:00:00.000000000 +0100
10966 +++ asterisk-1.2.10/include/asterisk/xlaw.h 2006-07-31 14:13:08.000000000 +0200
10967 @@ -0,0 +1,1665 @@
10968 +#ifndef _ASTERISK_XLAW_H
10969 +#define _ASTERISK_XLAW_H
10970 +
10971 +#ifdef CAPI_ULAW
10972 +#define capiXLAW2INT(x) capiULAW2INT[x]
10973 +#define capiINT2XLAW(x) capiINT2ULAW[((unsigned short)x) >> 2]
10974 +#else
10975 +#define capiXLAW2INT(x) capiALAW2INT[x]
10976 +#define capiINT2XLAW(x) capiINT2ALAW[(x>>4)+4096]
10977 +#endif
10978 +
10979 +static unsigned char reversebits[256] =
10980 +{
10981 +0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
10982 +0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
10983 +0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
10984 +0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
10985 +0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
10986 +0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
10987 +0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
10988 +0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
10989 +0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
10990 +0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
10991 +0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
10992 +0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
10993 +0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
10994 +0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
10995 +0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
10996 +0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
10997 +0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
10998 +0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
10999 +0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
11000 +0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
11001 +0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
11002 +0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
11003 +0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
11004 +0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
11005 +0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
11006 +0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
11007 +0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
11008 +0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
11009 +0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
11010 +0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
11011 +0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
11012 +0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
11013 +};
11014 +
11015 +#ifdef CAPI_ULAW
11016 +static short capiULAW2INT[] =
11017 +{
11018 +0x8284, 0x7d7c, 0xf8a4, 0x075c, 0xe104, 0x1efc, 0xfe8c, 0x0174,
11019 +0xc184, 0x3e7c, 0xfc94, 0x036c, 0xf0c4, 0x0f3c, 0xff88, 0x0078,
11020 +0xa284, 0x5d7c, 0xfaa4, 0x055c, 0xe904, 0x16fc, 0xff0c, 0x00f4,
11021 +0xd184, 0x2e7c, 0xfd94, 0x026c, 0xf4c4, 0x0b3c, 0xffc8, 0x0038,
11022 +0x9284, 0x6d7c, 0xf9a4, 0x065c, 0xe504, 0x1afc, 0xfecc, 0x0134,
11023 +0xc984, 0x367c, 0xfd14, 0x02ec, 0xf2c4, 0x0d3c, 0xffa8, 0x0058,
11024 +0xb284, 0x4d7c, 0xfba4, 0x045c, 0xed04, 0x12fc, 0xff4c, 0x00b4,
11025 +0xd984, 0x267c, 0xfe14, 0x01ec, 0xf6c4, 0x093c, 0xffe8, 0x0018,
11026 +0x8a84, 0x757c, 0xf924, 0x06dc, 0xe304, 0x1cfc, 0xfeac, 0x0154,
11027 +0xc584, 0x3a7c, 0xfcd4, 0x032c, 0xf1c4, 0x0e3c, 0xff98, 0x0068,
11028 +0xaa84, 0x557c, 0xfb24, 0x04dc, 0xeb04, 0x14fc, 0xff2c, 0x00d4,
11029 +0xd584, 0x2a7c, 0xfdd4, 0x022c, 0xf5c4, 0x0a3c, 0xffd8, 0x0028,
11030 +0x9a84, 0x657c, 0xfa24, 0x05dc, 0xe704, 0x18fc, 0xfeec, 0x0114,
11031 +0xcd84, 0x327c, 0xfd54, 0x02ac, 0xf3c4, 0x0c3c, 0xffb8, 0x0048,
11032 +0xba84, 0x457c, 0xfc24, 0x03dc, 0xef04, 0x10fc, 0xff6c, 0x0094,
11033 +0xdd84, 0x227c, 0xfe54, 0x01ac, 0xf7c4, 0x083c, 0xfff8, 0x0008,
11034 +0x8684, 0x797c, 0xf8e4, 0x071c, 0xe204, 0x1dfc, 0xfe9c, 0x0164,
11035 +0xc384, 0x3c7c, 0xfcb4, 0x034c, 0xf144, 0x0ebc, 0xff90, 0x0070,
11036 +0xa684, 0x597c, 0xfae4, 0x051c, 0xea04, 0x15fc, 0xff1c, 0x00e4,
11037 +0xd384, 0x2c7c, 0xfdb4, 0x024c, 0xf544, 0x0abc, 0xffd0, 0x0030,
11038 +0x9684, 0x697c, 0xf9e4, 0x061c, 0xe604, 0x19fc, 0xfedc, 0x0124,
11039 +0xcb84, 0x347c, 0xfd34, 0x02cc, 0xf344, 0x0cbc, 0xffb0, 0x0050,
11040 +0xb684, 0x497c, 0xfbe4, 0x041c, 0xee04, 0x11fc, 0xff5c, 0x00a4,
11041 +0xdb84, 0x247c, 0xfe34, 0x01cc, 0xf744, 0x08bc, 0xfff0, 0x0010,
11042 +0x8e84, 0x717c, 0xf964, 0x069c, 0xe404, 0x1bfc, 0xfebc, 0x0144,
11043 +0xc784, 0x387c, 0xfcf4, 0x030c, 0xf244, 0x0dbc, 0xffa0, 0x0060,
11044 +0xae84, 0x517c, 0xfb64, 0x049c, 0xec04, 0x13fc, 0xff3c, 0x00c4,
11045 +0xd784, 0x287c, 0xfdf4, 0x020c, 0xf644, 0x09bc, 0xffe0, 0x0020,
11046 +0x9e84, 0x617c, 0xfa64, 0x059c, 0xe804, 0x17fc, 0xfefc, 0x0104,
11047 +0xcf84, 0x307c, 0xfd74, 0x028c, 0xf444, 0x0bbc, 0xffc0, 0x0040,
11048 +0xbe84, 0x417c, 0xfc64, 0x039c, 0xf004, 0x0ffc, 0xff7c, 0x0084,
11049 +0xdf84, 0x207c, 0xfe74, 0x018c, 0xf844, 0x07bc, 0x0000, 0x0000
11050 +};
11051 +
11052 +const unsigned char capiINT2ULAW[16384] = {
11053 +255,127,127,191,191,63,63,223,223,95,95,159,159,31,31,239,
11054 +239,111,111,175,175,47,47,207,207,79,79,143,143,15,15,247,
11055 +247,247,247,119,119,119,119,183,183,183,183,55,55,55,55,215,
11056 +215,215,215,87,87,87,87,151,151,151,151,23,23,23,23,231,
11057 +231,231,231,103,103,103,103,167,167,167,167,39,39,39,39,199,
11058 +199,199,199,71,71,71,71,135,135,135,135,7,7,7,7,251,
11059 +251,251,251,251,251,251,251,123,123,123,123,123,123,123,123,187,
11060 +187,187,187,187,187,187,187,59,59,59,59,59,59,59,59,219,
11061 +219,219,219,219,219,219,219,91,91,91,91,91,91,91,91,155,
11062 +155,155,155,155,155,155,155,27,27,27,27,27,27,27,27,235,
11063 +235,235,235,235,235,235,235,107,107,107,107,107,107,107,107,171,
11064 +171,171,171,171,171,171,171,43,43,43,43,43,43,43,43,203,
11065 +203,203,203,203,203,203,203,75,75,75,75,75,75,75,75,139,
11066 +139,139,139,139,139,139,139,11,11,11,11,11,11,11,11,243,
11067 +243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,115,
11068 +115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,179,
11069 +179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,51,
11070 +51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,211,
11071 +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,83,
11072 +83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,147,
11073 +147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,19,
11074 +19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,227,
11075 +227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,99,
11076 +99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,163,
11077 +163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,35,
11078 +35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,195,
11079 +195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,67,
11080 +67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,131,
11081 +131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,3,
11082 +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,253,
11083 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
11084 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,125,
11085 +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
11086 +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,189,
11087 +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
11088 +189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,61,
11089 +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
11090 +61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,221,
11091 +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
11092 +221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,93,
11093 +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
11094 +93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,157,
11095 +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
11096 +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,29,
11097 +29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
11098 +29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,237,
11099 +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
11100 +237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,109,
11101 +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
11102 +109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,173,
11103 +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
11104 +173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,45,
11105 +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
11106 +45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,205,
11107 +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
11108 +205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,77,
11109 +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
11110 +77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,141,
11111 +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
11112 +141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,13,
11113 +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
11114 +13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,245,
11115 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
11116 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
11117 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
11118 +245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,117,
11119 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
11120 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
11121 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
11122 +117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,181,
11123 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
11124 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
11125 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
11126 +181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,53,
11127 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
11128 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
11129 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
11130 +53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,213,
11131 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
11132 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
11133 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
11134 +213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,85,
11135 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11136 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11137 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
11138 +85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,149,
11139 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
11140 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
11141 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
11142 +149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,21,
11143 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
11144 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
11145 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
11146 +21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,229,
11147 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
11148 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
11149 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
11150 +229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,101,
11151 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
11152 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
11153 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
11154 +101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,165,
11155 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
11156 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
11157 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
11158 +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,37,
11159 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
11160 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
11161 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
11162 +37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,197,
11163 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
11164 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
11165 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
11166 +197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,69,
11167 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
11168 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
11169 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
11170 +69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,133,
11171 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
11172 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
11173 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
11174 +133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,5,
11175 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
11176 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
11177 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
11178 +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,249,
11179 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
11180 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
11181 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
11182 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
11183 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
11184 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
11185 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
11186 +249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,121,
11187 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
11188 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
11189 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
11190 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
11191 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
11192 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
11193 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
11194 +121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,185,
11195 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
11196 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
11197 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
11198 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
11199 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
11200 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
11201 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
11202 +185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,57,
11203 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
11204 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
11205 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
11206 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
11207 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
11208 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
11209 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,
11210 +57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,217,
11211 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
11212 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
11213 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
11214 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
11215 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
11216 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
11217 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,
11218 +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,89,
11219 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
11220 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
11221 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
11222 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
11223 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
11224 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
11225 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,
11226 +89,89,89,89,89,89,89,89,89,89,89,89,89,89,89,153,
11227 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
11228 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
11229 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
11230 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
11231 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
11232 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
11233 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
11234 +153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,25,
11235 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
11236 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
11237 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
11238 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
11239 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
11240 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
11241 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
11242 +25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,233,
11243 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
11244 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
11245 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
11246 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
11247 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
11248 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
11249 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,
11250 +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,105,
11251 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
11252 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
11253 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
11254 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
11255 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
11256 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
11257 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
11258 +105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,169,
11259 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
11260 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
11261 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
11262 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
11263 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
11264 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
11265 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
11266 +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,41,
11267 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
11268 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
11269 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
11270 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
11271 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
11272 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
11273 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,
11274 +41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,201,
11275 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
11276 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
11277 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
11278 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
11279 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
11280 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
11281 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,
11282 +201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,73,
11283 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
11284 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
11285 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
11286 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
11287 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
11288 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
11289 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,
11290 +73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,137,
11291 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
11292 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
11293 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
11294 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
11295 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
11296 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
11297 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
11298 +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,9,
11299 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
11300 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
11301 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
11302 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
11303 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
11304 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
11305 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
11306 +9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,241,
11307 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11308 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11309 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11310 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11311 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11312 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11313 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11314 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11315 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11316 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11317 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11318 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11319 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11320 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11321 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
11322 +241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,113,
11323 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11324 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11325 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11326 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11327 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11328 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11329 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11330 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11331 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11332 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11333 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11334 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11335 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11336 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11337 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
11338 +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,177,
11339 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11340 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11341 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11342 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11343 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11344 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11345 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11346 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11347 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11348 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11349 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11350 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11351 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11352 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11353 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
11354 +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,49,
11355 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11356 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11357 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11358 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11359 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11360 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11361 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11362 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11363 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11364 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11365 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11366 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11367 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11368 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11369 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
11370 +49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,209,
11371 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11372 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11373 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11374 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11375 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11376 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11377 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11378 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11379 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11380 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11381 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11382 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11383 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11384 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11385 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
11386 +209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,81,
11387 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11388 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11389 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11390 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11391 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11392 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11393 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11394 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11395 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11396 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11397 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11398 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11399 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11400 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11401 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
11402 +81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,145,
11403 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11404 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11405 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11406 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11407 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11408 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11409 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11410 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11411 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11412 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11413 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11414 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11415 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11416 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11417 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
11418 +145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,17,
11419 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11420 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11421 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11422 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11423 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11424 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11425 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11426 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11427 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11428 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11429 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11430 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11431 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11432 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11433 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
11434 +17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,225,
11435 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11436 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11437 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11438 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11439 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11440 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11441 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11442 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11443 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11444 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11445 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11446 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11447 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11448 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11449 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
11450 +225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,97,
11451 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11452 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11453 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11454 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11455 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11456 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11457 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11458 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11459 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11460 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11461 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11462 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11463 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11464 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11465 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
11466 +97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,161,
11467 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11468 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11469 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11470 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11471 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11472 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11473 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11474 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11475 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11476 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11477 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11478 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11479 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11480 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11481 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
11482 +161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,33,
11483 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11484 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11485 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11486 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11487 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11488 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11489 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11490 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11491 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11492 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11493 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11494 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11495 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11496 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11497 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
11498 +33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,193,
11499 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11500 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11501 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11502 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11503 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11504 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11505 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11506 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11507 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11508 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11509 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11510 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11511 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11512 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11513 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
11514 +193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,65,
11515 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11516 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11517 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11518 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11519 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11520 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11521 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11522 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11523 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11524 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11525 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11526 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11527 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11528 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11529 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
11530 +65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,129,
11531 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11532 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11533 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11534 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11535 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11536 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11537 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11538 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11539 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11540 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11541 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11542 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11543 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11544 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11545 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
11546 +129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,1,
11547 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11548 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11549 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11550 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11551 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11552 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11553 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11554 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11555 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11556 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11557 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11558 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11559 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11560 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11561 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11562 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11563 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11564 +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
11565 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11566 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11567 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11568 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11569 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11570 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11571 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11572 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11573 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11574 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11575 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11576 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11577 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11578 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11579 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11580 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11581 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11582 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11583 +64,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11584 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11585 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11586 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11587 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11588 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11589 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11590 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11591 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11592 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11593 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11594 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11595 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11596 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11597 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11598 +128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
11599 +128,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11600 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11601 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11602 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11603 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11604 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11605 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11606 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11607 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11608 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11609 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11610 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11611 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11612 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11613 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11614 +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
11615 +64,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11616 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11617 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11618 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11619 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11620 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11621 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11622 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11623 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11624 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11625 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11626 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11627 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11628 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11629 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11630 +192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
11631 +192,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11632 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11633 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11634 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11635 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11636 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11637 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11638 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11639 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11640 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11641 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11642 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11643 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11644 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11645 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11646 +32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
11647 +32,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11648 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11649 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11650 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11651 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11652 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11653 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11654 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11655 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11656 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11657 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11658 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11659 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11660 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11661 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11662 +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
11663 +160,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11664 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11665 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11666 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11667 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11668 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11669 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11670 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11671 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11672 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11673 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11674 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11675 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11676 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11677 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11678 +96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
11679 +96,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11680 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11681 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11682 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11683 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11684 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11685 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11686 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11687 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11688 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11689 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11690 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11691 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11692 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11693 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11694 +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
11695 +224,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11696 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11697 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11698 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11699 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11700 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11701 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11702 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11703 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11704 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11705 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11706 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11707 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11708 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11709 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11710 +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
11711 +16,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11712 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11713 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11714 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11715 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11716 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11717 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11718 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11719 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11720 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11721 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11722 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11723 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11724 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11725 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11726 +144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
11727 +144,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11728 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11729 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11730 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11731 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11732 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11733 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11734 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11735 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11736 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11737 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11738 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11739 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11740 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11741 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11742 +80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
11743 +80,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11744 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11745 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11746 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11747 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11748 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11749 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11750 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11751 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11752 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11753 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11754 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11755 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11756 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11757 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11758 +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
11759 +208,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11760 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11761 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11762 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11763 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11764 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11765 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11766 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11767 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11768 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11769 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11770 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11771 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11772 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11773 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11774 +48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
11775 +48,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11776 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11777 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11778 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11779 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11780 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11781 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11782 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11783 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11784 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11785 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11786 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11787 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11788 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11789 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11790 +176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
11791 +176,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11792 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11793 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11794 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11795 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11796 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11797 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11798 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11799 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11800 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11801 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11802 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11803 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11804 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11805 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11806 +112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
11807 +112,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11808 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11809 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11810 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11811 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11812 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11813 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11814 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11815 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11816 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11817 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11818 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11819 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11820 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11821 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11822 +240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
11823 +240,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11824 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11825 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11826 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11827 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11828 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11829 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11830 +8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
11831 +8,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11832 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11833 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11834 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11835 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11836 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11837 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11838 +136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
11839 +136,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11840 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11841 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11842 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11843 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11844 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11845 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11846 +72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
11847 +72,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11848 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11849 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11850 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11851 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11852 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11853 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11854 +200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
11855 +200,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11856 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11857 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11858 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11859 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11860 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11861 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11862 +40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,
11863 +40,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11864 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11865 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11866 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11867 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11868 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11869 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11870 +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
11871 +168,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11872 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11873 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11874 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11875 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11876 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11877 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11878 +104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
11879 +104,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11880 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11881 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11882 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11883 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11884 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11885 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11886 +232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,
11887 +232,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11888 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11889 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11890 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11891 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11892 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11893 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11894 +24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
11895 +24,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11896 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11897 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11898 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11899 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11900 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11901 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11902 +152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
11903 +152,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11904 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11905 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11906 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11907 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11908 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11909 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11910 +88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,
11911 +88,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11912 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11913 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11914 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11915 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11916 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11917 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11918 +216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,
11919 +216,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11920 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11921 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11922 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11923 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11924 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11925 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11926 +56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,
11927 +56,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11928 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11929 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11930 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11931 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11932 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11933 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11934 +184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
11935 +184,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11936 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11937 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11938 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11939 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11940 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11941 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11942 +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
11943 +120,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11944 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11945 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11946 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11947 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11948 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11949 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11950 +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
11951 +248,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11952 +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11953 +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11954 +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
11955 +4,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11956 +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11957 +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11958 +132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
11959 +132,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11960 +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11961 +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11962 +68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
11963 +68,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11964 +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11965 +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11966 +196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
11967 +196,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11968 +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11969 +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11970 +36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
11971 +36,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11972 +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11973 +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11974 +164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
11975 +164,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11976 +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11977 +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11978 +100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
11979 +100,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11980 +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11981 +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11982 +228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
11983 +228,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11984 +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11985 +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11986 +20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
11987 +20,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11988 +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11989 +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11990 +148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
11991 +148,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11992 +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11993 +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11994 +84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
11995 +84,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11996 +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11997 +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11998 +212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
11999 +212,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
12000 +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
12001 +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
12002 +52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
12003 +52,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
12004 +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
12005 +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
12006 +180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
12007 +180,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
12008 +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
12009 +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
12010 +116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
12011 +116,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
12012 +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
12013 +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
12014 +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
12015 +244,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12016 +12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12017 +12,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
12018 +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
12019 +140,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
12020 +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
12021 +76,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
12022 +204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
12023 +204,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
12024 +44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
12025 +44,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
12026 +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
12027 +172,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
12028 +108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
12029 +108,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
12030 +236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
12031 +236,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
12032 +28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
12033 +28,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
12034 +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
12035 +156,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
12036 +92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
12037 +92,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
12038 +220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
12039 +220,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
12040 +60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
12041 +60,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
12042 +188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
12043 +188,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
12044 +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
12045 +124,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
12046 +252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
12047 +252,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
12048 +2,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,
12049 +130,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,
12050 +66,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,
12051 +194,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,
12052 +34,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,
12053 +162,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,
12054 +98,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,
12055 +226,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,
12056 +18,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,
12057 +146,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,
12058 +82,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,
12059 +210,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
12060 +50,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
12061 +178,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
12062 +114,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
12063 +242,10,10,10,10,10,10,10,10,138,138,138,138,138,138,138,
12064 +138,74,74,74,74,74,74,74,74,202,202,202,202,202,202,202,
12065 +202,42,42,42,42,42,42,42,42,170,170,170,170,170,170,170,
12066 +170,106,106,106,106,106,106,106,106,234,234,234,234,234,234,234,
12067 +234,26,26,26,26,26,26,26,26,154,154,154,154,154,154,154,
12068 +154,90,90,90,90,90,90,90,90,218,218,218,218,218,218,218,
12069 +218,58,58,58,58,58,58,58,58,186,186,186,186,186,186,186,
12070 +186,122,122,122,122,122,122,122,122,250,250,250,250,250,250,250,
12071 +250,6,6,6,6,134,134,134,134,70,70,70,70,198,198,198,
12072 +198,38,38,38,38,166,166,166,166,102,102,102,102,230,230,230,
12073 +230,22,22,22,22,150,150,150,150,86,86,86,86,214,214,214,
12074 +214,54,54,54,54,182,182,182,182,118,118,118,118,246,246,246,
12075 +246,14,14,142,142,78,78,206,206,46,46,174,174,110,110,238,
12076 +238,30,30,158,158,94,94,222,222,62,62,190,190,126,126,254,
12077 +};
12078 +#else
12079 +static short capiALAW2INT[] =
12080 +{
12081 + 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
12082 + 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
12083 + 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
12084 + 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
12085 + 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
12086 + 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
12087 + 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
12088 + 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
12089 + 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
12090 + 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
12091 + 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
12092 + 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
12093 + 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
12094 + 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
12095 + 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
12096 + 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
12097 + 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
12098 + 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
12099 + 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
12100 + 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
12101 + 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
12102 + 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
12103 + 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
12104 + 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
12105 + 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
12106 + 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
12107 + 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
12108 + 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
12109 + 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
12110 + 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
12111 + 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
12112 + 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
12113 +};
12114 +
12115 +const unsigned char capiINT2ALAW[8192] = {
12116 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12117 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12118 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12119 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12120 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12121 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12122 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12123 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12124 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12125 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12126 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12127 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12128 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12129 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12130 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12131 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12132 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12133 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12134 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12135 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12136 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12137 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12138 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12139 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12140 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12141 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12142 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12143 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12144 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12145 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12146 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12147 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12148 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12149 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12150 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12151 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12152 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12153 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12154 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12155 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12156 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12157 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12158 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12159 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12160 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12161 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12162 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12163 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12164 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12165 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12166 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12167 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12168 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12169 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12170 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12171 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12172 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12173 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12174 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12175 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12176 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12177 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12178 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12179 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12180 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12181 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12182 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12183 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12184 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12185 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12186 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12187 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12188 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12189 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12190 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12191 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12192 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12193 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12194 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12195 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12196 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12197 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12198 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12199 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12200 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12201 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12202 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12203 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12204 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12205 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12206 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12207 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12208 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12209 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12210 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12211 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12212 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12213 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12214 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12215 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12216 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12217 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12218 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12219 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12220 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12221 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12222 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12223 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12224 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12225 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12226 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12227 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12228 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12229 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12230 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12231 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12232 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12233 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12234 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12235 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12236 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12237 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12238 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12239 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12240 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12241 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12242 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12243 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12244 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12245 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12246 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12247 + 84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
12248 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
12249 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
12250 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
12251 + 212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,
12252 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
12253 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
12254 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
12255 + 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
12256 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
12257 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
12258 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
12259 + 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
12260 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
12261 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
12262 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
12263 + 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
12264 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
12265 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
12266 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
12267 + 244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
12268 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
12269 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
12270 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
12271 + 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,
12272 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
12273 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
12274 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
12275 + 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
12276 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
12277 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
12278 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
12279 + 68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,
12280 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
12281 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
12282 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
12283 + 196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,
12284 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
12285 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
12286 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
12287 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
12288 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
12289 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
12290 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
12291 + 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
12292 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
12293 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
12294 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
12295 + 100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
12296 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
12297 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
12298 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
12299 + 228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,
12300 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
12301 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
12302 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
12303 + 36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
12304 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
12305 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
12306 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
12307 + 164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,
12308 + 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
12309 + 92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,92,
12310 + 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
12311 + 220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,
12312 + 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
12313 + 28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,
12314 + 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
12315 + 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
12316 + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
12317 + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
12318 + 252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
12319 + 252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
12320 + 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
12321 + 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,
12322 + 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
12323 + 188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
12324 + 76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
12325 + 76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,
12326 + 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
12327 + 204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
12328 + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12329 + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12330 + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
12331 + 140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
12332 + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
12333 + 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
12334 + 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
12335 + 236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
12336 + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
12337 + 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,
12338 + 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
12339 + 172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
12340 + 80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,
12341 + 208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,
12342 + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
12343 + 144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
12344 + 112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
12345 + 240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
12346 + 48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
12347 + 176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
12348 + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
12349 + 192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
12350 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
12351 + 128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
12352 + 96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,
12353 + 224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
12354 + 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,
12355 + 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
12356 + 88,88,88,88,88,88,88,88,216,216,216,216,216,216,216,216,
12357 + 24,24,24,24,24,24,24,24,152,152,152,152,152,152,152,152,
12358 + 120,120,120,120,120,120,120,120,248,248,248,248,248,248,248,248,
12359 + 56,56,56,56,56,56,56,56,184,184,184,184,184,184,184,184,
12360 + 72,72,72,72,72,72,72,72,200,200,200,200,200,200,200,200,
12361 + 8,8,8,8,8,8,8,8,136,136,136,136,136,136,136,136,
12362 + 104,104,104,104,104,104,104,104,232,232,232,232,232,232,232,232,
12363 + 40,40,40,40,40,40,40,40,168,168,168,168,168,168,168,168,
12364 + 86,86,86,86,214,214,214,214,22,22,22,22,150,150,150,150,
12365 + 118,118,118,118,246,246,246,246,54,54,54,54,182,182,182,182,
12366 + 70,70,70,70,198,198,198,198,6,6,6,6,134,134,134,134,
12367 + 102,102,102,102,230,230,230,230,38,38,38,38,166,166,166,166,
12368 + 94,94,222,222,30,30,158,158,126,126,254,254,62,62,190,190,
12369 + 78,78,206,206,14,14,142,142,110,110,238,238,46,46,174,174,
12370 + 82,210,18,146,114,242,50,178,66,194,2,130,98,226,34,162,
12371 + 90,218,26,154,122,250,58,186,74,202,10,138,106,234,42,170,
12372 + 171,43,235,107,139,11,203,75,187,59,251,123,155,27,219,91,
12373 + 163,35,227,99,131,3,195,67,179,51,243,115,147,19,211,83,
12374 + 175,175,47,47,239,239,111,111,143,143,15,15,207,207,79,79,
12375 + 191,191,63,63,255,255,127,127,159,159,31,31,223,223,95,95,
12376 + 167,167,167,167,39,39,39,39,231,231,231,231,103,103,103,103,
12377 + 135,135,135,135,7,7,7,7,199,199,199,199,71,71,71,71,
12378 + 183,183,183,183,55,55,55,55,247,247,247,247,119,119,119,119,
12379 + 151,151,151,151,23,23,23,23,215,215,215,215,87,87,87,87,
12380 + 169,169,169,169,169,169,169,169,41,41,41,41,41,41,41,41,
12381 + 233,233,233,233,233,233,233,233,105,105,105,105,105,105,105,105,
12382 + 137,137,137,137,137,137,137,137,9,9,9,9,9,9,9,9,
12383 + 201,201,201,201,201,201,201,201,73,73,73,73,73,73,73,73,
12384 + 185,185,185,185,185,185,185,185,57,57,57,57,57,57,57,57,
12385 + 249,249,249,249,249,249,249,249,121,121,121,121,121,121,121,121,
12386 + 153,153,153,153,153,153,153,153,25,25,25,25,25,25,25,25,
12387 + 217,217,217,217,217,217,217,217,89,89,89,89,89,89,89,89,
12388 + 161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
12389 + 33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
12390 + 225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
12391 + 97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
12392 + 129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,
12393 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
12394 + 193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
12395 + 65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,
12396 + 177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
12397 + 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
12398 + 241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
12399 + 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
12400 + 145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
12401 + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
12402 + 209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
12403 + 81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,
12404 + 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
12405 + 173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
12406 + 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
12407 + 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,
12408 + 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
12409 + 237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,
12410 + 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
12411 + 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
12412 + 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
12413 + 141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
12414 + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
12415 + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
12416 + 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
12417 + 205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
12418 + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
12419 + 77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,
12420 + 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
12421 + 189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
12422 + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
12423 + 61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,
12424 + 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
12425 + 253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
12426 + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
12427 + 125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,
12428 + 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
12429 + 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
12430 + 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
12431 + 29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,
12432 + 221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
12433 + 221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
12434 + 93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
12435 + 93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,93,
12436 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
12437 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
12438 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
12439 + 165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,
12440 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
12441 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
12442 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
12443 + 37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
12444 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
12445 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
12446 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
12447 + 229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,
12448 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
12449 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
12450 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
12451 + 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
12452 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
12453 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
12454 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
12455 + 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
12456 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
12457 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
12458 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
12459 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
12460 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
12461 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
12462 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
12463 + 197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,
12464 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
12465 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
12466 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
12467 + 69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,
12468 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
12469 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
12470 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
12471 + 181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
12472 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
12473 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
12474 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
12475 + 53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,
12476 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
12477 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
12478 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
12479 + 245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
12480 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
12481 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
12482 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
12483 + 117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
12484 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
12485 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
12486 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
12487 + 149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
12488 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
12489 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
12490 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
12491 + 21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
12492 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
12493 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
12494 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
12495 + 213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,
12496 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12497 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12498 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12499 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12500 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12501 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12502 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12503 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12504 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12505 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12506 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12507 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12508 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12509 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12510 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12511 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12512 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12513 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12514 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12515 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12516 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12517 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12518 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12519 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12520 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12521 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12522 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12523 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12524 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12525 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12526 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12527 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12528 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12529 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12530 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12531 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12532 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12533 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12534 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12535 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12536 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12537 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12538 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12539 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12540 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12541 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12542 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12543 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12544 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12545 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12546 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12547 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12548 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12549 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12550 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12551 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12552 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12553 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12554 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12555 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12556 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12557 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12558 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12559 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12560 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12561 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12562 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12563 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12564 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12565 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12566 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12567 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12568 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12569 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12570 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12571 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12572 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12573 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12574 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12575 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12576 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12577 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12578 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12579 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12580 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12581 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12582 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12583 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12584 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12585 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12586 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12587 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12588 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12589 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12590 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12591 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12592 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12593 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12594 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12595 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12596 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12597 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12598 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12599 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12600 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12601 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12602 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12603 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12604 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12605 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12606 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12607 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12608 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12609 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12610 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12611 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12612 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12613 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12614 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12615 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12616 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12617 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12618 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12619 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12620 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12621 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12622 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12623 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12624 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12625 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12626 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,
12627 + 85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85
12628 +};
12629 +
12630 +#endif // CAPI_ULAW
12631 +#endif
12632 +
12633 diff -urN asterisk-1.2.10.orig/include/asterisk.h asterisk-1.2.10/include/asterisk.h
12634 --- asterisk-1.2.10.orig/include/asterisk.h 2005-11-30 04:37:37.000000000 +0100
12635 +++ asterisk-1.2.10/include/asterisk.h 2006-07-31 14:13:08.000000000 +0200
12636 @@ -36,6 +36,7 @@
12637 extern char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
12638 extern char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
12639 extern char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
12640 +extern char ast_config_AST_SYMBOLIC_NAME[20];
12641 extern char ast_config_AST_CTL_PERMISSIONS[AST_CONFIG_MAX_PATH];
12642 extern char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH];
12643 extern char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH];
12644 diff -urN asterisk-1.2.10.orig/manager.c asterisk-1.2.10/manager.c
12645 --- asterisk-1.2.10.orig/manager.c 2006-02-11 19:15:00.000000000 +0100
12646 +++ asterisk-1.2.10/manager.c 2006-07-31 14:13:08.000000000 +0200
12647 @@ -11,6 +11,9 @@
12648 * the project provides a web site, mailing lists and IRC
12649 * channels for your use.
12650 *
12651 + * Copyright (C) 2003-2004, Junghanns.NET Gmbh
12652 + * Klaus-Peter Junghanns <kpj@junghanns.net>
12653 + *
12654 * This program is free software, distributed under the terms of
12655 * the GNU General Public License Version 2. See the LICENSE file
12656 * at the top of the source tree.
12657 @@ -62,6 +65,7 @@
12658 #include "asterisk/md5.h"
12659 #include "asterisk/acl.h"
12660 #include "asterisk/utils.h"
12661 +#include "asterisk/astdb.h"
12662
12663 struct fast_originate_helper {
12664 char tech[AST_MAX_MANHEADER_LEN];
12665 @@ -76,6 +80,8 @@
12666 char idtext[AST_MAX_MANHEADER_LEN];
12667 char account[AST_MAX_ACCOUNT_CODE];
12668 int priority;
12669 + int callingpres;
12670 + char uniqueid[64];
12671 struct ast_variable *vars;
12672 };
12673
12674 @@ -99,6 +105,7 @@
12675 { EVENT_FLAG_COMMAND, "command" },
12676 { EVENT_FLAG_AGENT, "agent" },
12677 { EVENT_FLAG_USER, "user" },
12678 + { EVENT_FLAG_EXTENSIONSTATUS, "extensionstatus" },
12679 { -1, "all" },
12680 { 0, "none" },
12681 };
12682 @@ -657,11 +664,17 @@
12683 {
12684 struct ast_channel *c = NULL;
12685 char *name = astman_get_header(m, "Channel");
12686 - if (ast_strlen_zero(name)) {
12687 - astman_send_error(s, m, "No channel specified");
12688 + char *uniqueid = astman_get_header(m, "Uniqueid");
12689 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
12690 + astman_send_error(s, m, "No channel or uniqueid specified");
12691 return 0;
12692 }
12693 - c = ast_get_channel_by_name_locked(name);
12694 + if (!ast_strlen_zero(uniqueid)) {
12695 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
12696 + } else {
12697 + if (!ast_strlen_zero(name))
12698 + c = ast_get_channel_by_name_locked(name);
12699 + }
12700 if (!c) {
12701 astman_send_error(s, m, "No such channel");
12702 return 0;
12703 @@ -760,6 +773,7 @@
12704 }
12705
12706
12707 +
12708 /*! \brief action_status: Manager "status" command to show channels */
12709 /* Needs documentation... */
12710 static int action_status(struct mansession *s, struct message *m)
12711 @@ -866,32 +880,50 @@
12712 char *exten = astman_get_header(m, "Exten");
12713 char *context = astman_get_header(m, "Context");
12714 char *priority = astman_get_header(m, "Priority");
12715 + char *uniqueid = astman_get_header(m, "Uniqueid");
12716 + char *uniqueid2 = astman_get_header(m, "ExtraUniqueid");
12717 + char *exten2 = astman_get_header(m, "ExtraExten");
12718 + char *context2 = astman_get_header(m, "ExtraContext");
12719 + char *priority2 = astman_get_header(m, "ExtraPriority");
12720 struct ast_channel *chan, *chan2 = NULL;
12721 int pi = 0;
12722 + int pi2 = 0;
12723 int res;
12724
12725 - if (ast_strlen_zero(name)) {
12726 - astman_send_error(s, m, "Channel not specified");
12727 + if ((!name || ast_strlen_zero(name)) && (!uniqueid || ast_strlen_zero(uniqueid))) {
12728 + astman_send_error(s, m, "Channel or Uniqueid not specified");
12729 return 0;
12730 }
12731 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
12732 astman_send_error(s, m, "Invalid priority\n");
12733 return 0;
12734 }
12735 - chan = ast_get_channel_by_name_locked(name);
12736 + if (uniqueid && (!ast_strlen_zero(uniqueid))) {
12737 + chan = ast_get_channel_by_uniqueid_locked(uniqueid);
12738 + } else {
12739 + chan = ast_get_channel_by_name_locked(name);
12740 + }
12741 if (!chan) {
12742 char buf[BUFSIZ];
12743 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
12744 astman_send_error(s, m, buf);
12745 return 0;
12746 }
12747 - if (!ast_strlen_zero(name2))
12748 + if (!ast_strlen_zero(uniqueid2)) {
12749 + chan2 = ast_get_channel_by_uniqueid_locked(uniqueid2);
12750 + if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%d", &pi2) != 1)) {
12751 + astman_send_error(s, m, "Invalid priority2\n");
12752 + return 0;
12753 + }
12754 + } else {
12755 + if (!ast_strlen_zero(name2))
12756 chan2 = ast_get_channel_by_name_locked(name2);
12757 + }
12758 res = ast_async_goto(chan, context, exten, pi);
12759 if (!res) {
12760 - if (!ast_strlen_zero(name2)) {
12761 + if ((!ast_strlen_zero(name2)) || (!ast_strlen_zero(uniqueid2))){
12762 if (chan2)
12763 - res = ast_async_goto(chan2, context, exten, pi);
12764 + res = ast_async_goto(chan2, context2, exten2, pi2);
12765 else
12766 res = -1;
12767 if (!res)
12768 @@ -937,15 +969,15 @@
12769 struct ast_channel *chan = NULL;
12770
12771 if (!ast_strlen_zero(in->app)) {
12772 - res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1,
12773 + res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, in->callingpres,
12774 !ast_strlen_zero(in->cid_num) ? in->cid_num : NULL,
12775 !ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
12776 - in->vars, in->account, &chan);
12777 + in->vars, in->account, &chan, in->uniqueid);
12778 } else {
12779 - res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
12780 + res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, in->callingpres,
12781 !ast_strlen_zero(in->cid_num) ? in->cid_num : NULL,
12782 !ast_strlen_zero(in->cid_name) ? in->cid_name : NULL,
12783 - in->vars, in->account, &chan);
12784 + in->vars, in->account, &chan, in->uniqueid);
12785 }
12786 if (!res)
12787 manager_event(EVENT_FLAG_CALL,
12788 @@ -956,7 +988,7 @@
12789 "Exten: %s\r\n"
12790 "Reason: %d\r\n"
12791 "Uniqueid: %s\r\n",
12792 - in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
12793 + in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
12794 else
12795 manager_event(EVENT_FLAG_CALL,
12796 "OriginateFailure",
12797 @@ -966,7 +998,7 @@
12798 "Exten: %s\r\n"
12799 "Reason: %d\r\n"
12800 "Uniqueid: %s\r\n",
12801 - in->idtext, in->tech, in->data, in->context, in->exten, reason, chan ? chan->uniqueid : "<null>");
12802 + in->idtext, in->tech, in->data, in->context, in->exten, reason, in->uniqueid ? in->uniqueid : (chan ? chan->uniqueid : "<null>"));
12803
12804 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
12805 if (chan)
12806 @@ -999,6 +1031,7 @@
12807 char *priority = astman_get_header(m, "Priority");
12808 char *timeout = astman_get_header(m, "Timeout");
12809 char *callerid = astman_get_header(m, "CallerID");
12810 + char *callingpres = astman_get_header(m, "CallingPres");
12811 char *account = astman_get_header(m, "Account");
12812 char *app = astman_get_header(m, "Application");
12813 char *appdata = astman_get_header(m, "Data");
12814 @@ -1007,12 +1040,15 @@
12815 struct ast_variable *vars = astman_get_variables(m);
12816 char *tech, *data;
12817 char *l=NULL, *n=NULL;
12818 + char *uniqueid;
12819 int pi = 0;
12820 + int cpresi = 0;
12821 int res;
12822 int to = 30000;
12823 int reason = 0;
12824 char tmp[256];
12825 char tmp2[256];
12826 + char idText[256] = "";
12827
12828 pthread_t th;
12829 pthread_attr_t attr;
12830 @@ -1028,6 +1064,10 @@
12831 astman_send_error(s, m, "Invalid timeout\n");
12832 return 0;
12833 }
12834 + if (!ast_strlen_zero(callingpres) && (sscanf(callingpres, "%d", &cpresi) != 1)) {
12835 + astman_send_error(s, m, "Invalid CallingPres\n");
12836 + return 0;
12837 + }
12838 ast_copy_string(tmp, name, sizeof(tmp));
12839 tech = tmp;
12840 data = strchr(tmp, '/');
12841 @@ -1048,6 +1088,7 @@
12842 if (ast_strlen_zero(l))
12843 l = NULL;
12844 }
12845 + uniqueid = ast_alloc_uniqueid();
12846 if (ast_true(async)) {
12847 struct fast_originate_helper *fast = malloc(sizeof(struct fast_originate_helper));
12848 if (!fast) {
12849 @@ -1068,8 +1109,10 @@
12850 ast_copy_string(fast->context, context, sizeof(fast->context));
12851 ast_copy_string(fast->exten, exten, sizeof(fast->exten));
12852 ast_copy_string(fast->account, account, sizeof(fast->account));
12853 + ast_copy_string(fast->uniqueid, uniqueid, sizeof(fast->uniqueid));
12854 fast->timeout = to;
12855 fast->priority = pi;
12856 + fast->callingpres = cpresi;
12857 pthread_attr_init(&attr);
12858 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12859 if (ast_pthread_create(&th, &attr, fast_originate, fast)) {
12860 @@ -1079,19 +1122,28 @@
12861 }
12862 }
12863 } else if (!ast_strlen_zero(app)) {
12864 - res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
12865 + res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
12866 } else {
12867 if (exten && context && pi)
12868 - res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
12869 + res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 1, cpresi, l, n, vars, account, NULL, uniqueid);
12870 else {
12871 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
12872 return 0;
12873 }
12874 }
12875 - if (!res)
12876 - astman_send_ack(s, m, "Originate successfully queued");
12877 - else
12878 + if (!res) {
12879 + if (id && !ast_strlen_zero(id)) {
12880 + snprintf(idText,256,"ActionID: %s\r\n",id);
12881 + }
12882 + ast_cli(s->fd, "Response: Success\r\n"
12883 + "%s"
12884 + "Message: Originate successfully queued\r\n"
12885 + "Uniqueid: %s\r\n"
12886 + "\r\n",
12887 + idText, uniqueid);
12888 + } else {
12889 astman_send_error(s, m, "Originate failed");
12890 + }
12891 return 0;
12892 }
12893
12894 @@ -1565,10 +1617,12 @@
12895 return 0;
12896 }
12897
12898 -static int manager_state_cb(char *context, char *exten, int state, void *data)
12899 +static int manager_state_cb(char *context, char *exten, int state, void *data, char *cid_num, char *cid_name)
12900 {
12901 + char hint[256] = "";
12902 + ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
12903 /* Notify managers of change */
12904 - manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
12905 + manager_event(EVENT_FLAG_EXTENSIONSTATUS, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\nCallerID: \"%s\" <%s>\r\nHint: %s\r\n", exten, context, state, cid_num, cid_name, hint);
12906 return 0;
12907 }
12908
12909 diff -urN asterisk-1.2.10.orig/pbx/pbx_spool.c asterisk-1.2.10/pbx/pbx_spool.c
12910 --- asterisk-1.2.10.orig/pbx/pbx_spool.c 2006-02-11 19:15:00.000000000 +0100
12911 +++ asterisk-1.2.10/pbx/pbx_spool.c 2006-07-31 14:13:08.000000000 +0200
12912 @@ -259,11 +259,11 @@
12913 if (!ast_strlen_zero(o->app)) {
12914 if (option_verbose > 2)
12915 ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
12916 - res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
12917 + res = ast_pbx_outgoing_app(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, 0, o->cid_num, o->cid_name, o->vars, o->account, NULL, NULL);
12918 } else {
12919 if (option_verbose > 2)
12920 ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
12921 - res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
12922 + res = ast_pbx_outgoing_exten(o->tech, AST_FORMAT_SLINEAR, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, 0, o->cid_num, o->cid_name, o->vars, o->account, NULL, NULL);
12923 }
12924 if (res) {
12925 ast_log(LOG_NOTICE, "Call failed to go through, reason %d\n", reason);
12926 diff -urN asterisk-1.2.10.orig/pbx.c asterisk-1.2.10/pbx.c
12927 --- asterisk-1.2.10.orig/pbx.c 2006-06-18 23:03:58.000000000 +0200
12928 +++ asterisk-1.2.10/pbx.c 2006-07-31 14:13:08.000000000 +0200
12929 @@ -353,7 +353,8 @@
12930
12931 { "Hangup", pbx_builtin_hangup,
12932 "Hang up the calling channel",
12933 - " Hangup(): This application will hang up the calling channel.\n"
12934 + " Hangup(Cause): Unconditionally hangs up a given channel by returning -1 always.\n"
12935 + " If cause is given, it will set the hangup cause accordingly.\n"
12936 },
12937
12938 { "NoOp", pbx_builtin_noop,
12939 @@ -1883,7 +1884,7 @@
12940 return ast_extension_state2(e); /* Check all devices in the hint */
12941 }
12942
12943 -void ast_hint_state_changed(const char *device)
12944 +void ast_hint_state_changed(const char *device, char *cid_num, char *cid_name)
12945 {
12946 struct ast_hint *hint;
12947 struct ast_state_cb *cblist;
12948 @@ -1911,11 +1912,11 @@
12949
12950 /* For general callbacks */
12951 for (cblist = statecbs; cblist; cblist = cblist->next)
12952 - cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
12953 + cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
12954
12955 /* For extension callbacks */
12956 for (cblist = hint->callbacks; cblist; cblist = cblist->next)
12957 - cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
12958 + cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data, cid_num, cid_name);
12959
12960 hint->laststate = state;
12961 break;
12962 @@ -2156,7 +2157,7 @@
12963 /* Notify with -1 and remove all callbacks */
12964 cbprev = cblist;
12965 cblist = cblist->next;
12966 - cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data);
12967 + cbprev->callback(list->exten->parent->name, list->exten->exten, AST_EXTENSION_DEACTIVATED, cbprev->data, NULL, NULL);
12968 free(cbprev);
12969 }
12970 list->callbacks = NULL;
12971 @@ -3777,7 +3778,7 @@
12972 while (thiscb) {
12973 prevcb = thiscb;
12974 thiscb = thiscb->next;
12975 - prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
12976 + prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data, NULL, NULL);
12977 free(prevcb);
12978 }
12979 } else {
12980 @@ -4981,7 +4982,7 @@
12981 return 0; /* success */
12982 }
12983
12984 -int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
12985 +int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, char *uniqueid)
12986 {
12987 struct ast_channel *chan;
12988 struct async_stat *as;
12989 @@ -4991,7 +4992,7 @@
12990
12991 if (sync) {
12992 LOAD_OH(oh);
12993 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
12994 + chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
12995 if (channel) {
12996 *channel = chan;
12997 if (chan)
12998 @@ -5093,7 +5094,7 @@
12999 goto outgoing_exten_cleanup;
13000 }
13001 memset(as, 0, sizeof(struct async_stat));
13002 - chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
13003 + chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
13004 if (channel) {
13005 *channel = chan;
13006 if (chan)
13007 @@ -5139,7 +5140,7 @@
13008 pthread_t t;
13009 };
13010
13011 -static void *ast_pbx_run_app(void *data)
13012 +void *ast_pbx_run_app(void *data)
13013 {
13014 struct app_tmp *tmp = data;
13015 struct ast_app *app;
13016 @@ -5155,7 +5156,7 @@
13017 return NULL;
13018 }
13019
13020 -int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
13021 +int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, int callingpres, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, char *uniqueid)
13022 {
13023 struct ast_channel *chan;
13024 struct async_stat *as;
13025 @@ -5175,7 +5176,7 @@
13026 goto outgoing_app_cleanup;
13027 }
13028 if (sync) {
13029 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
13030 + chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
13031 if (chan) {
13032 if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
13033 ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
13034 @@ -5262,7 +5263,8 @@
13035 goto outgoing_app_cleanup;
13036 }
13037 memset(as, 0, sizeof(struct async_stat));
13038 - chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
13039 + chan = __ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, &oh, uniqueid);
13040 +// chan = ast_request_and_dial(type, format, data, timeout, reason, callingpres, cid_num, cid_name, uniqueid);
13041 if (!chan) {
13042 free(as);
13043 res = -1;
13044 @@ -5551,6 +5553,9 @@
13045 */
13046 static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
13047 {
13048 + /* Copy the hangup cause as specified */
13049 + if (data)
13050 + chan->hangupcause = atoi(data);
13051 /* Just return non-zero and it will hang up */
13052 if (!chan->hangupcause)
13053 chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
13054 @@ -6207,6 +6212,9 @@
13055 return -1;
13056 }
13057 }
13058 + if (chan->_state != AST_STATE_UP) {
13059 + ast_answer(chan);
13060 + }
13061 return res = ast_say_number(chan, atoi((char *) tmp), "", chan->language, options);
13062 }
13063
13064 @@ -6214,8 +6222,12 @@
13065 {
13066 int res = 0;
13067
13068 - if (data)
13069 + if (data) {
13070 + if (chan->_state != AST_STATE_UP) {
13071 + ast_answer(chan);
13072 + }
13073 res = ast_say_digit_str(chan, (char *)data, "", chan->language);
13074 + }
13075 return res;
13076 }
13077
13078 @@ -6223,8 +6235,12 @@
13079 {
13080 int res = 0;
13081
13082 - if (data)
13083 + if (data) {
13084 + if (chan->_state != AST_STATE_UP) {
13085 + ast_answer(chan);
13086 + }
13087 res = ast_say_character_str(chan, (char *)data, "", chan->language);
13088 + }
13089 return res;
13090 }
13091
13092 @@ -6232,8 +6248,12 @@
13093 {
13094 int res = 0;
13095
13096 - if (data)
13097 + if (data) {
13098 + if (chan->_state != AST_STATE_UP) {
13099 + ast_answer(chan);
13100 + }
13101 res = ast_say_phonetic_str(chan, (char *)data, "", chan->language);
13102 + }
13103 return res;
13104 }
13105
13106 diff -urN asterisk-1.2.10.orig/res/Makefile asterisk-1.2.10/res/Makefile
13107 --- asterisk-1.2.10.orig/res/Makefile 2005-11-29 19:24:39.000000000 +0100
13108 +++ asterisk-1.2.10/res/Makefile 2006-07-31 14:13:08.000000000 +0200
13109 @@ -11,7 +11,7 @@
13110 # the GNU General Public License
13111 #
13112
13113 -MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so
13114 +MODS=res_indications.so res_monitor.so res_adsi.so res_agi.so res_features.so res_watchdog.so
13115
13116 ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/odbcinst.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/odbcinst.h),)
13117 ifneq (${OSARCH},FreeBSD)
13118 diff -urN asterisk-1.2.10.orig/res/res_agi.c asterisk-1.2.10/res/res_agi.c
13119 --- asterisk-1.2.10.orig/res/res_agi.c 2006-07-12 15:54:10.000000000 +0200
13120 +++ asterisk-1.2.10/res/res_agi.c 2006-07-31 14:13:08.000000000 +0200
13121 @@ -11,6 +11,9 @@
13122 * the project provides a web site, mailing lists and IRC
13123 * channels for your use.
13124 *
13125 + * Copyright (C) 2005 Junghanns.NET GmbH
13126 + * Klaus-Peter Junghanns <kpj@junghanns.net>
13127 + *
13128 * This program is free software, distributed under the terms of
13129 * the GNU General Public License Version 2. See the LICENSE file
13130 * at the top of the source tree.
13131 @@ -74,16 +77,19 @@
13132
13133 static char *app = "AGI";
13134
13135 +static char *xapp = "XAGI";
13136 +
13137 static char *eapp = "EAGI";
13138
13139 static char *deadapp = "DeadAGI";
13140
13141 static char *synopsis = "Executes an AGI compliant application";
13142 +static char *xsynopsis = "Executes an XAGI compliant application";
13143 static char *esynopsis = "Executes an EAGI compliant application";
13144 static char *deadsynopsis = "Executes AGI on a hungup channel";
13145
13146 static char *descrip =
13147 -" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
13148 +" [E|Dead|X]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
13149 "program on a channel. AGI allows Asterisk to launch external programs\n"
13150 "written in any language to control a telephony channel, play audio,\n"
13151 "read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
13152 @@ -92,6 +98,8 @@
13153 " hangup, or 0 on non-hangup exit. \n"
13154 "Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
13155 "on file descriptor 3\n\n"
13156 +"Using 'XAGI' provides enhanced AGI, with incoming audio available out of band"
13157 +" on file descriptor 3 and outgoing audio available out of band on file descriptor 4\n\n"
13158 "Use the CLI command 'show agi' to list available agi commands\n";
13159
13160 static int agidebug = 0;
13161 @@ -225,13 +233,14 @@
13162 return 0;
13163 }
13164
13165 -static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
13166 +static int launch_script(char *script, char *argv[], int *fds, int *efd, int *efd2, int *opid)
13167 {
13168 char tmp[256];
13169 int pid;
13170 int toast[2];
13171 int fromast[2];
13172 int audio[2];
13173 + int audio2[2];
13174 int x;
13175 int res;
13176 sigset_t signal_set;
13177 @@ -276,6 +285,33 @@
13178 return -1;
13179 }
13180 }
13181 + if (efd2) {
13182 + if (pipe(audio2)) {
13183 + ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
13184 + close(fromast[0]);
13185 + close(fromast[1]);
13186 + close(toast[0]);
13187 + close(toast[1]);
13188 + close(audio[0]);
13189 + close(audio[1]);
13190 + return -1;
13191 + }
13192 + res = fcntl(audio2[0], F_GETFL);
13193 + if (res > -1)
13194 + res = fcntl(audio2[0], F_SETFL, res | O_NONBLOCK);
13195 + if (res < 0) {
13196 + ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
13197 + close(fromast[0]);
13198 + close(fromast[1]);
13199 + close(toast[0]);
13200 + close(toast[1]);
13201 + close(audio[0]);
13202 + close(audio[1]);
13203 + close(audio2[0]);
13204 + close(audio2[1]);
13205 + return -1;
13206 + }
13207 + }
13208 pid = fork();
13209 if (pid < 0) {
13210 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
13211 @@ -293,15 +329,19 @@
13212 } else {
13213 close(STDERR_FILENO + 1);
13214 }
13215 + if (efd2) {
13216 + dup2(audio2[1], STDERR_FILENO + 2);
13217 + } else {
13218 + close(STDERR_FILENO + 2);
13219 + }
13220
13221 /* unblock important signal handlers */
13222 if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
13223 ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
13224 exit(1);
13225 }
13226 -
13227 /* Close everything but stdin/out/error */
13228 - for (x=STDERR_FILENO + 2;x<1024;x++)
13229 + for (x=STDERR_FILENO + 3;x<1024;x++)
13230 close(x);
13231
13232 /* Execute script */
13233 @@ -317,6 +357,9 @@
13234 if (efd) {
13235 *efd = audio[1];
13236 }
13237 + if (efd2) {
13238 + *efd2 = audio2[0];
13239 + }
13240 /* close what we're not using in the parent */
13241 close(toast[1]);
13242 close(fromast[0]);
13243 @@ -325,6 +368,9 @@
13244 /* [PHM 12/18/03] */
13245 close(audio[0]);
13246 }
13247 + if (efd2) {
13248 + close(audio2[1]);
13249 + }
13250
13251 *opid = pid;
13252 return 0;
13253 @@ -355,7 +401,7 @@
13254 fdprintf(fd, "agi_context: %s\n", chan->context);
13255 fdprintf(fd, "agi_extension: %s\n", chan->exten);
13256 fdprintf(fd, "agi_priority: %d\n", chan->priority);
13257 - fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
13258 + fdprintf(fd, "agi_enhanced: %d%s\n", enhanced, ".0");
13259
13260 /* User information */
13261 fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
13262 @@ -387,7 +433,7 @@
13263 return RESULT_SHOWUSAGE;
13264 if (sscanf(argv[3], "%d", &to) != 1)
13265 return RESULT_SHOWUSAGE;
13266 - res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
13267 + res = ast_waitfordigit_full(chan, to, agi->audio_out, agi->ctrl);
13268 fdprintf(agi->fd, "200 result=%d\n", res);
13269 if (res >= 0)
13270 return RESULT_SUCCESS;
13271 @@ -563,7 +609,7 @@
13272 else
13273 return RESULT_FAILURE;
13274 }
13275 - res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
13276 + res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
13277 /* this is to check for if ast_waitstream closed the stream, we probably are at
13278 * the end of the stream, return that amount, else check for the amount */
13279 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
13280 @@ -623,7 +669,7 @@
13281 else
13282 return RESULT_FAILURE;
13283 }
13284 - res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
13285 + res = ast_waitstream_full(chan, argv[3], agi->audio_out, agi->ctrl);
13286 /* this is to check for if ast_waitstream closed the stream, we probably are at
13287 * the end of the stream, return that amount, else check for the amount */
13288 sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
13289 @@ -635,7 +681,7 @@
13290
13291 /* If the user didnt press a key, wait for digitTimeout*/
13292 if (res == 0 ) {
13293 - res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
13294 + res = ast_waitfordigit_full(chan, timeout, agi->audio_out, agi->ctrl);
13295 /* Make sure the new result is in the escape digits of the GET OPTION */
13296 if ( !strchr(edigits,res) )
13297 res=0;
13298 @@ -662,7 +708,7 @@
13299 return RESULT_SHOWUSAGE;
13300 if (sscanf(argv[2], "%d", &num) != 1)
13301 return RESULT_SHOWUSAGE;
13302 - res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
13303 + res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio_out, agi->ctrl);
13304 if (res == 1)
13305 return RESULT_SUCCESS;
13306 fdprintf(agi->fd, "200 result=%d\n", res);
13307 @@ -682,7 +728,7 @@
13308 if (sscanf(argv[2], "%d", &num) != 1)
13309 return RESULT_SHOWUSAGE;
13310
13311 - res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
13312 + res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
13313 if (res == 1) /* New command */
13314 return RESULT_SUCCESS;
13315 fdprintf(agi->fd, "200 result=%d\n", res);
13316 @@ -699,7 +745,7 @@
13317 if (argc != 4)
13318 return RESULT_SHOWUSAGE;
13319
13320 - res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
13321 + res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
13322 if (res == 1) /* New command */
13323 return RESULT_SUCCESS;
13324 fdprintf(agi->fd, "200 result=%d\n", res);
13325 @@ -789,7 +835,7 @@
13326 if (argc != 4)
13327 return RESULT_SHOWUSAGE;
13328
13329 - res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
13330 + res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio_out, agi->ctrl);
13331 if (res == 1) /* New command */
13332 return RESULT_SUCCESS;
13333 fdprintf(agi->fd, "200 result=%d\n", res);
13334 @@ -816,7 +862,7 @@
13335 max = atoi(argv[4]);
13336 else
13337 max = 1024;
13338 - res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
13339 + res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio_out, agi->ctrl);
13340 if (res == 2) /* New command */
13341 return RESULT_SUCCESS;
13342 else if (res == 1)
13343 @@ -1854,7 +1900,12 @@
13344 int ms;
13345 int returnstatus = 0;
13346 struct ast_frame *f;
13347 + struct ast_frame fr;
13348 char buf[2048];
13349 + char audiobuf[2048];
13350 + int audiobytes;
13351 + int fds[2];
13352 + int enhanced = 0;
13353 FILE *readf;
13354 /* how many times we'll retry if ast_waitfor_nandfs will return without either
13355 channel or file descriptor in case select is interrupted by a system call (EINTR) */
13356 @@ -1868,10 +1919,22 @@
13357 return -1;
13358 }
13359 setlinebuf(readf);
13360 - setup_env(chan, request, agi->fd, (agi->audio > -1));
13361 + if (agi->audio_out > -1) {
13362 + enhanced = 1;
13363 + }
13364 + if (agi->audio_in > -1) {
13365 + enhanced++;
13366 + }
13367 + setup_env(chan, request, agi->fd, enhanced);
13368 + fds[0] = agi->ctrl;
13369 + fds[1] = agi->audio_in;
13370 for (;;) {
13371 ms = -1;
13372 - c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
13373 + if (agi->audio_in > -1) {
13374 + c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, fds, 2, NULL, &outfd, &ms);
13375 + } else {
13376 + c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
13377 + }
13378 if (c) {
13379 retry = RETRY;
13380 /* Idle the channel until we get a command */
13381 @@ -1882,13 +1945,24 @@
13382 break;
13383 } else {
13384 /* If it's voice, write it to the audio pipe */
13385 - if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
13386 + if ((agi->audio_out > -1) && (f->frametype == AST_FRAME_VOICE)) {
13387 /* Write, ignoring errors */
13388 - write(agi->audio, f->data, f->datalen);
13389 + write(agi->audio_out, f->data, f->datalen);
13390 }
13391 ast_frfree(f);
13392 }
13393 } else if (outfd > -1) {
13394 + if ((agi->audio_in > -1) && (outfd == agi->audio_in)) {
13395 + audiobytes = read(agi->audio_in, audiobuf, sizeof(audiobuf));
13396 + if (audiobytes > 0) {
13397 + // ast_log(LOG_NOTICE, "read %d bytes of audio\n", audiobytes);
13398 + fr.frametype = AST_FRAME_VOICE;
13399 + fr.subclass = AST_FORMAT_SLINEAR;
13400 + fr.datalen = audiobytes;
13401 + fr.data = audiobuf;
13402 + ast_write(chan, &fr);
13403 + }
13404 + } else {
13405 retry = RETRY;
13406 if (!fgets(buf, sizeof(buf), readf)) {
13407 /* Program terminated */
13408 @@ -1910,6 +1984,7 @@
13409 if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
13410 break;
13411 }
13412 + }
13413 } else {
13414 if (--retry <= 0) {
13415 ast_log(LOG_WARNING, "No channel, no fd?\n");
13416 @@ -2016,6 +2091,7 @@
13417 int argc = 0;
13418 int fds[2];
13419 int efd = -1;
13420 + int efd2 = -1;
13421 int pid;
13422 char *stringp;
13423 AGI agi;
13424 @@ -2041,15 +2117,18 @@
13425 }
13426 }
13427 #endif
13428 - res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
13429 + res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, (enhanced == 2) ? &efd2 : NULL, &pid);
13430 if (!res) {
13431 agi.fd = fds[1];
13432 agi.ctrl = fds[0];
13433 - agi.audio = efd;
13434 + agi.audio_out = efd;
13435 + agi.audio_in = efd2;
13436 res = run_agi(chan, argv[0], &agi, pid, dead);
13437 close(fds[1]);
13438 if (efd > -1)
13439 close(efd);
13440 + if (efd2 > -1)
13441 + close(efd2);
13442 }
13443 LOCAL_USER_REMOVE(u);
13444 return res;
13445 @@ -2083,6 +2162,35 @@
13446 return res;
13447 }
13448
13449 +static int xagi_exec(struct ast_channel *chan, void *data)
13450 +{
13451 + int readformat, writeformat;
13452 + int res;
13453 +
13454 + if (chan->_softhangup)
13455 + ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
13456 + readformat = chan->readformat;
13457 + if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
13458 + ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
13459 + return -1;
13460 + }
13461 + writeformat = chan->writeformat;
13462 + if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
13463 + ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
13464 + return -1;
13465 + }
13466 + res = agi_exec_full(chan, data, 2, 0);
13467 + if (!res) {
13468 + if (ast_set_read_format(chan, readformat)) {
13469 + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
13470 + }
13471 + if (ast_set_write_format(chan, writeformat)) {
13472 + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(writeformat));
13473 + }
13474 + }
13475 + return res;
13476 +}
13477 +
13478 static int deadagi_exec(struct ast_channel *chan, void *data)
13479 {
13480 return agi_exec_full(chan, data, 0, 1);
13481 @@ -2112,6 +2220,7 @@
13482 ast_cli_unregister(&dumpagihtml);
13483 ast_cli_unregister(&cli_debug);
13484 ast_cli_unregister(&cli_no_debug);
13485 + ast_unregister_application(xapp);
13486 ast_unregister_application(eapp);
13487 ast_unregister_application(deadapp);
13488 return ast_unregister_application(app);
13489 @@ -2125,6 +2234,7 @@
13490 ast_cli_register(&cli_no_debug);
13491 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
13492 ast_register_application(eapp, eagi_exec, esynopsis, descrip);
13493 + ast_register_application(xapp, xagi_exec, xsynopsis, descrip);
13494 return ast_register_application(app, agi_exec, synopsis, descrip);
13495 }
13496
13497 diff -urN asterisk-1.2.10.orig/res/res_features.c asterisk-1.2.10/res/res_features.c
13498 --- asterisk-1.2.10.orig/res/res_features.c 2006-05-23 19:15:23.000000000 +0200
13499 +++ asterisk-1.2.10/res/res_features.c 2006-08-02 09:55:40.000000000 +0200
13500 @@ -11,6 +11,10 @@
13501 * the project provides a web site, mailing lists and IRC
13502 * channels for your use.
13503 *
13504 + * Copyright (C) 2004, Junghanns.NET GmbH
13505 + *
13506 + * Klaus-Peter Junghanns <kpj@junghanns.net>
13507 + *
13508 * This program is free software, distributed under the terms of
13509 * the GNU General Public License Version 2. See the LICENSE file
13510 * at the top of the source tree.
13511 @@ -56,6 +60,7 @@
13512 #include "asterisk/utils.h"
13513 #include "asterisk/adsi.h"
13514 #include "asterisk/monitor.h"
13515 +#include "asterisk/indications.h"
13516
13517 #ifdef __AST_DEBUG_MALLOC
13518 static void FREE(void *ptr)
13519 @@ -73,6 +78,7 @@
13520 #define AST_MAX_WATCHERS 256
13521
13522 static char *parkedcall = "ParkedCall";
13523 +static char *holdedcall = "HoldedCall";
13524
13525 /* No more than 45 seconds parked before you do something with them */
13526 static int parkingtime = DEFAULT_PARK_TIME;
13527 @@ -132,6 +138,20 @@
13528 "into the dialplan, although you should include the 'parkedcalls'\n"
13529 "context.\n";
13530
13531 +static char *autoanswerlogin = "AutoanswerLogin";
13532 +
13533 +static char *synopsis3 = "Log in for autoanswer";
13534 +
13535 +static char *descrip3 = "AutoanswerLogin(exten):"
13536 +"Used to login to the autoanswer application for an extension.\n";
13537 +
13538 +static char *autoanswer = "Autoanswer";
13539 +
13540 +static char *synopsis4 = "Autoanswer a call";
13541 +
13542 +static char *descrip4 = "Autoanswer(exten):"
13543 +"Used to autoanswer a call for an extension.\n";
13544 +
13545 static struct ast_app *monitor_app=NULL;
13546 static int monitor_ok=1;
13547
13548 @@ -150,12 +170,51 @@
13549 struct parkeduser *next;
13550 };
13551
13552 +struct holdeduser {
13553 + struct ast_channel *chan;
13554 + struct timeval start;
13555 + int parkingnum;
13556 + int cref;
13557 + int tei;
13558 + /* Where to go if our parking time expires */
13559 + char context[AST_MAX_EXTENSION];
13560 + char exten[AST_MAX_EXTENSION];
13561 + int priority;
13562 + int parkingtime;
13563 + char uniqueid[AST_MAX_UNIQUEID];
13564 + char uniqueidpeer[AST_MAX_UNIQUEID];
13565 + struct holdeduser *next;
13566 +};
13567 +
13568 +/* auto answer user */
13569 +struct aauser {
13570 + struct ast_channel *chan;
13571 + struct timeval start;
13572 + /* waiting on this extension/context */
13573 + char exten[AST_MAX_EXTENSION];
13574 + char context[AST_MAX_EXTENSION];
13575 + int priority;
13576 + int notquiteyet;
13577 + struct aauser *next;
13578 +};
13579 +
13580 +
13581 +static struct aauser *aalot;
13582 +AST_MUTEX_DEFINE_STATIC(autoanswer_lock);
13583 +static pthread_t autoanswer_thread;
13584 +
13585 static struct parkeduser *parkinglot;
13586
13587 +static struct holdeduser *holdlist;
13588 +
13589 AST_MUTEX_DEFINE_STATIC(parking_lock);
13590
13591 +AST_MUTEX_DEFINE_STATIC(holding_lock);
13592 +
13593 static pthread_t parking_thread;
13594
13595 +static pthread_t holding_thread;
13596 +
13597 STANDARD_LOCAL_USER;
13598
13599 LOCAL_USER_DECL;
13600 @@ -165,6 +224,12 @@
13601 return parking_ext;
13602 }
13603
13604 +char *ast_parking_con(void)
13605 +{
13606 + return parking_con;
13607 +}
13608 +
13609 +
13610 char *ast_pickup_ext(void)
13611 {
13612 return pickup_ext;
13613 @@ -362,10 +427,11 @@
13614 "Timeout: %ld\r\n"
13615 "CallerID: %s\r\n"
13616 "CallerIDName: %s\r\n"
13617 + "Unqiueid: %s\r\n\r\n"
13618 ,pu->parkingnum, pu->chan->name, peer ? peer->name : ""
13619 ,(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL)
13620 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
13621 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
13622 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
13623 );
13624
13625 if (peer) {
13626 @@ -418,7 +484,8 @@
13627 ast_copy_string(chan->context, rchan->context, sizeof(chan->context));
13628 ast_copy_string(chan->exten, rchan->exten, sizeof(chan->exten));
13629 chan->priority = rchan->priority;
13630 -
13631 + /* might be dirty but we want trackable channels */
13632 + strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
13633 /* Make the masq execute */
13634 f = ast_read(chan);
13635 if (f)
13636 @@ -906,7 +973,7 @@
13637 }
13638
13639 /* find a feature by name */
13640 -static struct ast_call_feature *find_feature(char *name)
13641 +struct ast_call_feature *ast_find_feature(char *name)
13642 {
13643 struct ast_call_feature *tmp;
13644
13645 @@ -916,10 +983,21 @@
13646 break;
13647 }
13648 AST_LIST_UNLOCK(&feature_list);
13649 -
13650 return tmp;
13651 }
13652
13653 +struct ast_call_feature *ast_find_builtin_feature(char *name)
13654 +{
13655 + int x = 0;
13656 +
13657 + for (x = 0; x < FEATURES_COUNT; x++) {
13658 + if (!strcasecmp(name, builtin_features[x].sname)) {
13659 + return &builtin_features[x];
13660 + }
13661 + }
13662 + return NULL;
13663 +}
13664 +
13665 /* exec an app by feature */
13666 static int feature_exec_app(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
13667 {
13668 @@ -1018,7 +1096,7 @@
13669 return res;
13670
13671 while ((tok = strsep(&tmp, "#")) != NULL) {
13672 - feature = find_feature(tok);
13673 + feature = ast_find_feature(tok);
13674
13675 if (feature) {
13676 /* Feature is up for consideration */
13677 @@ -1071,7 +1149,7 @@
13678
13679 /* while we have a feature */
13680 while (NULL != (tok = strsep(&tmp, "#"))) {
13681 - if ((feature = find_feature(tok))) {
13682 + if ((feature = ast_find_feature(tok))) {
13683 if (ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
13684 if (ast_test_flag(feature, AST_FEATURE_FLAG_CALLER))
13685 ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
13686 @@ -1096,7 +1174,7 @@
13687 struct ast_frame *f = NULL;
13688 int res = 0, ready = 0;
13689
13690 - if ((chan = ast_request(type, format, data, &cause))) {
13691 + if ((chan = ast_request(type, format, data, &cause, NULL))) {
13692 ast_set_callerid(chan, cid_num, cid_name, cid_num);
13693 ast_channel_inherit_variables(caller, chan);
13694 if (!ast_call(chan, data, timeout)) {
13695 @@ -1549,9 +1627,10 @@
13696 "Channel: %s\r\n"
13697 "CallerID: %s\r\n"
13698 "CallerIDName: %s\r\n"
13699 + "Uniqueid: %s\r\n\r\n"
13700 ,pu->parkingnum, pu->chan->name
13701 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
13702 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
13703 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
13704 );
13705
13706 if (option_verbose > 1)
13707 @@ -1594,9 +1673,10 @@
13708 "Channel: %s\r\n"
13709 "CallerID: %s\r\n"
13710 "CallerIDName: %s\r\n"
13711 + "Uniqueid: %s\r\n\r\n"
13712 ,pu->parkingnum, pu->chan->name
13713 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
13714 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
13715 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
13716 );
13717
13718 /* There's a problem, hang them up*/
13719 @@ -1683,6 +1763,282 @@
13720 return res;
13721 }
13722
13723 +int ast_hold_call(struct ast_channel *chan, struct ast_channel *peer)
13724 +{
13725 + /* We put the user in the parking list, then wake up the parking thread to be sure it looks
13726 + after these channels too */
13727 + struct holdeduser *pu;
13728 + pu = malloc(sizeof(struct holdeduser));
13729 + if (pu) {
13730 + memset(pu, 0, sizeof(pu));
13731 + ast_mutex_lock(&holding_lock);
13732 + chan->appl = "Holded Call";
13733 + chan->data = NULL;
13734 +
13735 + pu->chan = chan;
13736 + strncpy(pu->uniqueid, chan->uniqueid, sizeof(pu->uniqueid));
13737 + strncpy(pu->uniqueidpeer, peer->uniqueid, sizeof(pu->uniqueidpeer));
13738 + /* Start music on hold */
13739 + ast_moh_start(pu->chan, NULL);
13740 + gettimeofday(&pu->start, NULL);
13741 + pu->next = holdlist;
13742 + holdlist = pu;
13743 + ast_mutex_unlock(&holding_lock);
13744 + /* Wake up the (presumably select()ing) thread */
13745 + pthread_kill(holding_thread, SIGURG);
13746 +
13747 + manager_event(EVENT_FLAG_CALL, "HoldedCall",
13748 + "Channel1: %s\r\n"
13749 + "Channel2: %s\r\n"
13750 + "Uniqueid1: %s\r\n"
13751 + "Uniqueid2: %s\r\n"
13752 + ,pu->chan->name, peer->name, pu->chan->uniqueid, peer->uniqueid);
13753 +
13754 + } else {
13755 + ast_log(LOG_WARNING, "Out of memory\n");
13756 + return -1;
13757 + }
13758 + return 0;
13759 +}
13760 +
13761 +int ast_masq_hold_call(struct ast_channel *rchan, struct ast_channel *peer)
13762 +{
13763 + struct ast_channel *chan;
13764 + struct ast_frame *f;
13765 + /* Make a new, fake channel that we'll use to masquerade in the real one */
13766 + chan = ast_channel_alloc(0);
13767 + if (chan) {
13768 + /* Let us keep track of the channel name */
13769 + snprintf(chan->name, sizeof (chan->name), "Onhold/%s",rchan->name);
13770 + /* Make formats okay */
13771 + chan->readformat = rchan->readformat;
13772 + chan->writeformat = rchan->writeformat;
13773 + ast_channel_masquerade(chan, rchan);
13774 + /* Setup the extensions and such */
13775 + strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
13776 + strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
13777 + chan->priority = rchan->priority;
13778 + /* this might be dirty, but we need to preserve the uniqueid */
13779 + strncpy(chan->uniqueid, rchan->uniqueid, sizeof(chan->uniqueid) - 1);
13780 + /* Make the masq execute */
13781 + f = ast_read(chan);
13782 + if (f)
13783 + ast_frfree(f);
13784 + ast_hold_call(chan, peer);
13785 + return -1;
13786 + } else {
13787 + ast_log(LOG_WARNING, "Unable to create holded channel\n");
13788 + return -1;
13789 + }
13790 + return 0;
13791 +}
13792 +
13793 +int ast_retrieve_call(struct ast_channel *chan, char *uniqueid)
13794 +{
13795 + int res=-1, dres=-1;
13796 + struct ast_channel *peer=NULL;
13797 + struct ast_bridge_config config;
13798 +
13799 + peer = ast_get_holded_call(uniqueid);
13800 +
13801 + /* JK02: it helps to answer the channel if not already up */
13802 + if (chan->_state != AST_STATE_UP) {
13803 + ast_answer(chan);
13804 + }
13805 +
13806 + if (peer) {
13807 + ast_mutex_unlock(&peer->lock);
13808 + ast_moh_stop(peer);
13809 + res = ast_channel_make_compatible(chan, peer);
13810 + if (res < 0) {
13811 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
13812 + ast_hangup(peer);
13813 + return -1;
13814 + }
13815 + /* This runs sorta backwards, since we give the incoming channel control, as if it
13816 + were the person called. */
13817 + if (option_verbose > 2)
13818 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s connected to holded call %s\n", chan->name, peer->name);
13819 +
13820 + memset(&config,0,sizeof(struct ast_bridge_config));
13821 + ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
13822 + ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
13823 + config.timelimit = 0;
13824 + config.play_warning = 0;
13825 + config.warning_freq = 0;
13826 + config.warning_sound=NULL;
13827 + res = ast_bridge_call(chan,peer,&config);
13828 +
13829 + /* Simulate the PBX hanging up */
13830 + if (res != AST_PBX_NO_HANGUP_PEER)
13831 + ast_hangup(peer);
13832 + return res;
13833 + } else {
13834 + /* XXX Play a message XXX */
13835 + dres = ast_streamfile(chan, "pbx-invalidpark", chan->language);
13836 + if (!dres)
13837 + dres = ast_waitstream(chan, "");
13838 + else {
13839 + ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark", chan->name);
13840 + dres = 0;
13841 + }
13842 + }
13843 + return res;
13844 +}
13845 +
13846 +int ast_retrieve_call_to_death(char *uniqueid)
13847 +{
13848 + int res=-1;
13849 + struct ast_channel *peer=NULL;
13850 +
13851 + peer = ast_get_holded_call(uniqueid);
13852 +
13853 + if (peer) {
13854 + res=0;
13855 + if (option_verbose > 2)
13856 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
13857 + ast_mutex_unlock(&peer->lock);
13858 + ast_hangup(peer);
13859 + } else {
13860 + ast_log(LOG_WARNING, "Could not find channel with uniqueid %s to retrieve.\n", uniqueid);
13861 + }
13862 + return res;
13863 +}
13864 +
13865 +struct ast_channel *ast_get_holded_call(char *uniqueid)
13866 +{
13867 + int res=-1;
13868 + struct ast_channel *peer=NULL;
13869 + struct holdeduser *pu, *pl=NULL;
13870 +
13871 + ast_mutex_lock(&holding_lock);
13872 + pu = holdlist;
13873 + while(pu) {
13874 + if (!strncmp(uniqueid,pu->uniqueid,sizeof(pu->uniqueid))) {
13875 + if (pl)
13876 + pl->next = pu->next;
13877 + else
13878 + holdlist = pu->next;
13879 + break;
13880 + }
13881 + pl = pu;
13882 + pu = pu->next;
13883 + }
13884 + ast_mutex_unlock(&holding_lock);
13885 + if (pu) {
13886 + peer = ast_get_channel_by_uniqueid_locked(pu->uniqueid);
13887 + free(pu);
13888 + if (peer) {
13889 + res=0;
13890 + if (option_verbose > 2)
13891 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s removed from hold.\n", peer->name);
13892 + ast_moh_stop(peer);
13893 + return peer;
13894 + } else {
13895 + if (option_verbose > 2)
13896 + ast_verbose(VERBOSE_PREFIX_3 "Could not find channel with uniqueid %s.\n", uniqueid);
13897 + return NULL;
13898 + }
13899 + } else {
13900 + ast_log(LOG_WARNING, "Could not find held channel with uniqueid %s to retrieve.\n", uniqueid);
13901 + }
13902 + return NULL;
13903 +}
13904 +
13905 +/* this is our autmagically service thread that keeps channels onhold happy */
13906 +static void *do_holding_thread(void *ignore)
13907 +{
13908 + int ms, tms, max;
13909 + struct holdeduser *pu, *pl, *pt = NULL;
13910 + struct timeval tv;
13911 + struct ast_frame *f;
13912 + int x;
13913 + fd_set rfds, efds;
13914 + fd_set nrfds, nefds;
13915 + FD_ZERO(&rfds);
13916 + FD_ZERO(&efds);
13917 + for (;;) {
13918 + ms = -1;
13919 + max = -1;
13920 + ast_mutex_lock(&holding_lock);
13921 + pl = NULL;
13922 + pu = holdlist;
13923 + gettimeofday(&tv, NULL);
13924 + FD_ZERO(&nrfds);
13925 + FD_ZERO(&nefds);
13926 + while(pu) {
13927 + tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
13928 + for (x=0;x<AST_MAX_FDS;x++) {
13929 + if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
13930 + if (FD_ISSET(pu->chan->fds[x], &efds))
13931 + ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
13932 + else
13933 + ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
13934 + pu->chan->fdno = x;
13935 + /* See if they need servicing */
13936 + f = ast_read(pu->chan);
13937 + if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
13938 + /* There's a problem, hang them up*/
13939 + if (option_verbose > 1)
13940 + ast_verbose(VERBOSE_PREFIX_2 "%s got tired of being onhold\n", pu->chan->name);
13941 + ast_hangup(pu->chan);
13942 + /* find the corresponding channel and hang them up too! */
13943 + /* but only if it is not bridged yet! */
13944 + /* And take them out of the parking lot */
13945 + if (pl)
13946 + pl->next = pu->next;
13947 + else
13948 + holdlist = pu->next;
13949 + pt = pu;
13950 + pu = pu->next;
13951 + free(pt);
13952 + break;
13953 + } else {
13954 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
13955 + ast_frfree(f);
13956 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
13957 + }
13958 + }
13959 + }
13960 + if (x >= AST_MAX_FDS) {
13961 +std: for (x=0;x<AST_MAX_FDS;x++) {
13962 + /* Keep this one for next one */
13963 + if (pu->chan->fds[x] > -1) {
13964 + FD_SET(pu->chan->fds[x], &nrfds);
13965 + FD_SET(pu->chan->fds[x], &nefds);
13966 + if (pu->chan->fds[x] > max)
13967 + max = pu->chan->fds[x];
13968 + }
13969 + }
13970 + /* Keep track of our longest wait */
13971 + if ((tms < ms) || (ms < 0))
13972 + ms = tms;
13973 + pl = pu;
13974 + pu = pu->next;
13975 + }
13976 + }
13977 + ast_mutex_unlock(&holding_lock);
13978 + rfds = nrfds;
13979 + efds = nefds;
13980 + tv.tv_sec = ms / 1000;
13981 + tv.tv_usec = (ms % 1000) * 1000;
13982 + /* Wait for something to happen */
13983 + ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
13984 + pthread_testcancel();
13985 + }
13986 + return NULL; /* Never reached */
13987 +}
13988 +
13989 +static int retrieve_call_exec(struct ast_channel *chan, void *data) {
13990 + int res=0;
13991 + struct localuser *u;
13992 + char *uniqueid = (char *)data;
13993 + LOCAL_USER_ADD(u);
13994 + res = ast_retrieve_call(chan, uniqueid);
13995 + LOCAL_USER_REMOVE(u);
13996 + return res;
13997 +}
13998 +
13999 static int park_exec(struct ast_channel *chan, void *data)
14000 {
14001 int res=0;
14002 @@ -1731,9 +2087,10 @@
14003 "From: %s\r\n"
14004 "CallerID: %s\r\n"
14005 "CallerIDName: %s\r\n"
14006 + "Uniqueid: %s\r\n\r\n"
14007 ,pu->parkingnum, pu->chan->name, chan->name
14008 ,(pu->chan->cid.cid_num ? pu->chan->cid.cid_num : "<unknown>")
14009 - ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>")
14010 + ,(pu->chan->cid.cid_name ? pu->chan->cid.cid_name : "<unknown>"), pu->chan->uniqueid
14011 );
14012
14013 free(pu);
14014 @@ -1901,12 +2258,13 @@
14015 "Timeout: %ld\r\n"
14016 "CallerID: %s\r\n"
14017 "CallerIDName: %s\r\n"
14018 + "Uniqueid: %s\r\n"
14019 "%s"
14020 "\r\n"
14021 ,cur->parkingnum, cur->chan->name
14022 ,(long)cur->start.tv_sec + (long)(cur->parkingtime/1000) - (long)time(NULL)
14023 ,(cur->chan->cid.cid_num ? cur->chan->cid.cid_num : "")
14024 - ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : "")
14025 + ,(cur->chan->cid.cid_name ? cur->chan->cid.cid_name : ""), cur->chan->uniqueid
14026 ,idText);
14027
14028 cur = cur->next;
14029 @@ -1922,6 +2280,416 @@
14030 return RESULT_SUCCESS;
14031 }
14032
14033 +static int handle_autoanswer(int fd, int argc, char *argv[])
14034 +{
14035 + struct aauser *cur;
14036 +
14037 + ast_cli(fd, "%25s %10s %15s \n", "Channel"
14038 + , "Extension", "Context");
14039 +
14040 + ast_mutex_lock(&autoanswer_lock);
14041 +
14042 + cur=aalot;
14043 + while(cur) {
14044 + ast_cli(fd, "%25s %10s %15s\n",cur->chan->name, cur->exten, cur->context);
14045 +
14046 + cur = cur->next;
14047 + }
14048 +
14049 + ast_mutex_unlock(&autoanswer_lock);
14050 +
14051 + return RESULT_SUCCESS;
14052 +}
14053 +static char showautoanswer_help[] =
14054 +"Usage: show autoanswer\n"
14055 +" Lists currently logged in autoanswr channels.\n";
14056 +
14057 +static struct ast_cli_entry showautoanswer =
14058 +{ { "show", "autoanswer", NULL }, handle_autoanswer, "Lists autoanswer channels", showautoanswer_help };
14059 +
14060 +int ast_masq_autoanswer_login(struct ast_channel *rchan, void *data)
14061 +{
14062 + struct ast_channel *chan;
14063 + struct ast_frame *f;
14064 + /* Make a new, fake channel that we'll use to masquerade in the real one */
14065 + chan = ast_channel_alloc(0);
14066 + if (chan) {
14067 + /* Let us keep track of the channel name */
14068 + snprintf(chan->name, sizeof (chan->name), "Autoanswer/%s",rchan->name);
14069 + /* Make formats okay */
14070 + chan->readformat = rchan->readformat;
14071 + chan->writeformat = rchan->writeformat;
14072 + ast_channel_masquerade(chan, rchan);
14073 + /* Setup the extensions and such */
14074 + strncpy(chan->context, rchan->context, sizeof(chan->context) - 1);
14075 + strncpy(chan->exten, rchan->exten, sizeof(chan->exten) - 1);
14076 + chan->priority = rchan->priority;
14077 + /* Make the masq execute */
14078 + f = ast_read(chan);
14079 + if (f)
14080 + ast_frfree(f);
14081 + ast_autoanswer_login(chan, data);
14082 + } else {
14083 + ast_log(LOG_WARNING, "Unable to create aa channel\n");
14084 + return -1;
14085 + }
14086 + return 0;
14087 +}
14088 +
14089 +static int autoanswer_login_exec(struct ast_channel *chan, void *data)
14090 +{
14091 + int res=0;
14092 + struct localuser *u;
14093 + LOCAL_USER_ADD(u);
14094 + if (!data) {
14095 + ast_log(LOG_WARNING, "AutoanswerLogin requires an argument (extension number)\n");
14096 + return -1;
14097 + }
14098 + res = ast_masq_autoanswer_login(chan, data);
14099 + LOCAL_USER_REMOVE(u);
14100 + return res;
14101 +}
14102 +
14103 +int ast_autoanswer_login(struct ast_channel *chan, void *data)
14104 +{
14105 + /* We put the user in the parking list, then wake up the parking thread to be sure it looks
14106 + after these channels too */
14107 + struct ast_context *con;
14108 + char exten[AST_MAX_EXTENSION];
14109 + struct aauser *pu,*pl = NULL;
14110 + char *s, *stringp, *aacontext, *aaexten = NULL;
14111 +
14112 + s = ast_strdupa((void *) data);
14113 + stringp=s;
14114 + aacontext = strsep(&stringp, "|");
14115 + aaexten = strsep(&stringp, "|");
14116 + if (!aaexten) {
14117 + aaexten = aacontext;
14118 + aacontext = NULL;
14119 + }
14120 + if (!aaexten) {
14121 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
14122 + return -1;
14123 + } else {
14124 + if (!aacontext) {
14125 + aacontext = "default";
14126 + }
14127 + }
14128 +
14129 + ast_mutex_lock(&autoanswer_lock);
14130 + pu = aalot;
14131 + while(pu) {
14132 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
14133 + if (pl)
14134 + pl->next = pu->next;
14135 + else
14136 + aalot = pu->next;
14137 + break;
14138 + }
14139 + pl = pu;
14140 + pu = pu->next;
14141 + }
14142 + ast_mutex_unlock(&autoanswer_lock);
14143 + if (pu) {
14144 + ast_log(LOG_NOTICE, "Logout old Channel %s for %s@%s.\n",pu->chan->name, pu->exten, pu->context);
14145 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
14146 + "Channel: %s\r\n"
14147 + "Uniqueid: %s\r\n"
14148 + "Context: %s\r\n"
14149 + "Exten: %s\r\n"
14150 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
14151 + ast_hangup(pu->chan);
14152 + free(pu);
14153 + }
14154 + pu = malloc(sizeof(struct aauser));
14155 + if (pu) {
14156 + memset(pu, 0, sizeof(pu));
14157 + ast_mutex_lock(&autoanswer_lock);
14158 + chan->appl = "Autoanswer";
14159 + chan->data = NULL;
14160 +
14161 + pu->chan = chan;
14162 + if (chan->_state != AST_STATE_UP) {
14163 + ast_answer(chan);
14164 + }
14165 +
14166 + /* Start music on hold */
14167 + ast_moh_start(pu->chan, NULL);
14168 + gettimeofday(&pu->start, NULL);
14169 + strncpy(pu->exten, aaexten, sizeof(pu->exten)-1);
14170 + strncpy(pu->context, aacontext, sizeof(pu->exten)-1);
14171 + pu->next = aalot;
14172 + aalot = pu;
14173 + con = ast_context_find(aacontext);
14174 + if (!con) {
14175 + con = ast_context_create(NULL,aacontext, registrar);
14176 + if (!con) {
14177 + ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", aacontext);
14178 + }
14179 + }
14180 + if (con) {
14181 + snprintf(exten, sizeof(exten), "%s", aaexten);
14182 + ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)data), free, registrar);
14183 + }
14184 +
14185 + ast_mutex_unlock(&autoanswer_lock);
14186 + /* Wake up the (presumably select()ing) thread */
14187 + pthread_kill(autoanswer_thread, SIGURG);
14188 + if (option_verbose > 1)
14189 + ast_verbose(VERBOSE_PREFIX_2 "Autoanswer login from %s for %s@%s.\n", pu->chan->name, pu->exten, pu->context);
14190 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogin",
14191 + "Channel: %s\r\n"
14192 + "Uniqueid: %s\r\n"
14193 + "Context: %s\r\n"
14194 + "Exten: %s\r\n"
14195 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
14196 +
14197 + return 0;
14198 + } else {
14199 + ast_log(LOG_WARNING, "Out of memory\n");
14200 + return -1;
14201 + }
14202 + return 0;
14203 +}
14204 +
14205 +static void autoanswer_reregister_extensions(void)
14206 +{
14207 + struct aauser *cur;
14208 + struct ast_context *con;
14209 + char exten[AST_MAX_EXTENSION];
14210 + char args[AST_MAX_EXTENSION];
14211 +
14212 + ast_mutex_lock(&autoanswer_lock);
14213 +
14214 + cur=aalot;
14215 + while(cur) {
14216 + con = ast_context_find(cur->context);
14217 + if (!con) {
14218 + con = ast_context_create(NULL,cur->context, registrar);
14219 + if (!con) {
14220 + ast_log(LOG_ERROR, "Context '%s' does not exist and unable to create\n", cur->context);
14221 + }
14222 + }
14223 + if (con) {
14224 + snprintf(exten, sizeof(exten), "%s", cur->exten);
14225 + snprintf(args, sizeof(args), "%s|%s", cur->context, cur->exten);
14226 + ast_add_extension2(con, 1, exten, 1, NULL, NULL, autoanswer, strdup((char *)args), free, registrar);
14227 + }
14228 + cur = cur->next;
14229 + }
14230 +
14231 + ast_mutex_unlock(&autoanswer_lock);
14232 +}
14233 +static void *do_autoanswer_thread(void *ignore)
14234 +{
14235 + int ms, tms, max;
14236 + struct ast_context *con;
14237 + char exten[AST_MAX_EXTENSION];
14238 + struct aauser *pu, *pl, *pt = NULL;
14239 + struct timeval tv;
14240 + struct ast_frame *f;
14241 + int x;
14242 + fd_set rfds, efds;
14243 + fd_set nrfds, nefds;
14244 + FD_ZERO(&rfds);
14245 + FD_ZERO(&efds);
14246 + for (;;) {
14247 + ms = -1;
14248 + max = -1;
14249 + ast_mutex_lock(&autoanswer_lock);
14250 + pl = NULL;
14251 + pu = aalot;
14252 + gettimeofday(&tv, NULL);
14253 + FD_ZERO(&nrfds);
14254 + FD_ZERO(&nefds);
14255 + while(pu) {
14256 + tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
14257 + for (x=0;x<AST_MAX_FDS;x++) {
14258 + if ((pu->chan->fds[x] > -1) && (FD_ISSET(pu->chan->fds[x], &rfds) || FD_ISSET(pu->chan->fds[x], &efds))) {
14259 + if (FD_ISSET(pu->chan->fds[x], &efds))
14260 + ast_set_flag(pu->chan, AST_FLAG_EXCEPTION);
14261 + else
14262 + ast_clear_flag(pu->chan, AST_FLAG_EXCEPTION);
14263 + pu->chan->fdno = x;
14264 + /* See if they need servicing */
14265 + f = ast_read(pu->chan);
14266 + if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
14267 + /* There's a problem, hang them up*/
14268 + if (option_verbose > 1)
14269 + ast_verbose(VERBOSE_PREFIX_2 "%s logged out of autoanswer app\n", pu->chan->name);
14270 + manager_event(EVENT_FLAG_CALL, "AutoanswerLogout",
14271 + "Channel: %s\r\n"
14272 + "Uniqueid: %s\r\n"
14273 + "Context: %s\r\n"
14274 + "Exten: %s\r\n"
14275 + ,pu->chan->name, pu->chan->uniqueid, pu->context, pu->exten);
14276 + ast_hangup(pu->chan);
14277 + con = ast_context_find(pu->context);
14278 + if (con) {
14279 + snprintf(exten, sizeof(exten), "%s", pu->exten);
14280 + if (ast_context_remove_extension2(con, exten, 1, registrar))
14281 + ast_log(LOG_WARNING, "Whoa, failed to remove the extension!\n");
14282 + } else {
14283 + ast_log(LOG_WARNING, "Whoa, no %s context?\n", pu->exten);
14284 + }
14285 + /* And take them out of the parking lot */
14286 + if (pl)
14287 + pl->next = pu->next;
14288 + else
14289 + aalot = pu->next;
14290 + pt = pu;
14291 + pu = pu->next;
14292 + free(pt);
14293 + break;
14294 + } else {
14295 + /* XXX Maybe we could do something with packets, like dial "0" for operator or something XXX */
14296 + ast_frfree(f);
14297 + goto std; /* XXX Ick: jumping into an else statement??? XXX */
14298 + }
14299 + }
14300 + }
14301 + if (x >= AST_MAX_FDS) {
14302 +std: for (x=0;x<AST_MAX_FDS;x++) {
14303 + /* Keep this one for next one */
14304 + if (pu->chan->fds[x] > -1) {
14305 + FD_SET(pu->chan->fds[x], &nrfds);
14306 + FD_SET(pu->chan->fds[x], &nefds);
14307 + if (pu->chan->fds[x] > max)
14308 + max = pu->chan->fds[x];
14309 + }
14310 + }
14311 + /* Keep track of our longest wait */
14312 + if ((tms < ms) || (ms < 0))
14313 + ms = tms;
14314 + pl = pu;
14315 + pu = pu->next;
14316 + }
14317 + }
14318 + ast_mutex_unlock(&autoanswer_lock);
14319 + rfds = nrfds;
14320 + efds = nefds;
14321 + tv.tv_sec = ms / 1000;
14322 + tv.tv_usec = (ms % 1000) * 1000;
14323 + /* Wait for something to happen */
14324 + ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
14325 + pthread_testcancel();
14326 + }
14327 + return NULL; /* Never reached */
14328 +}
14329 +
14330 +static int autoanswer_exec(struct ast_channel *chan, void *data)
14331 +{
14332 + int res=0;
14333 + struct localuser *u;
14334 + struct ast_channel *peer=NULL;
14335 + struct aauser *pu, *pl=NULL;
14336 + struct ast_bridge_config config;
14337 + char *s, *stringp, *aacontext, *aaexten = NULL;
14338 + char datastring[80];
14339 +
14340 + if (!data) {
14341 + ast_log(LOG_WARNING, "Autoanswer requires an argument (extension number)\n");
14342 + return -1;
14343 + }
14344 + s = ast_strdupa((void *) data);
14345 + stringp=s;
14346 + aacontext = strsep(&stringp, "|");
14347 + aaexten = strsep(&stringp, "|");
14348 + if (!aaexten) {
14349 + aaexten = aacontext;
14350 + aacontext = NULL;
14351 + }
14352 + if (!aaexten) {
14353 + ast_log(LOG_WARNING, "AutoanswerLogin requires at least an extension!\n");
14354 + return -1;
14355 + } else {
14356 + if (!aacontext) {
14357 + aacontext = "default";
14358 + }
14359 + }
14360 +
14361 + LOCAL_USER_ADD(u);
14362 + ast_mutex_lock(&autoanswer_lock);
14363 + pu = aalot;
14364 + while(pu) {
14365 + if ((!strncasecmp(pu->exten, aaexten, sizeof(pu->exten)-1)) && (!strncasecmp(pu->context, aacontext, sizeof(pu->context)-1))){
14366 + if (pl)
14367 + pl->next = pu->next;
14368 + else
14369 + aalot = pu->next;
14370 + break;
14371 + }
14372 + pl = pu;
14373 + pu = pu->next;
14374 + }
14375 + ast_mutex_unlock(&autoanswer_lock);
14376 + if (pu) {
14377 + peer = pu->chan;
14378 + free(pu);
14379 + pu = NULL;
14380 + }
14381 + /* JK02: it helps to answer the channel if not already up */
14382 + if (chan->_state != AST_STATE_UP) {
14383 + ast_answer(chan);
14384 + }
14385 +
14386 + if (peer) {
14387 + ast_moh_stop(peer);
14388 + /* Play a courtesy beep in the callED channel to prefix the bridge connecting */
14389 + if (!ast_strlen_zero(courtesytone)) {
14390 + if (!ast_streamfile(peer, courtesytone, peer->language)) {
14391 + if (ast_waitstream(peer, "") < 0) {
14392 + ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
14393 + ast_hangup(peer);
14394 + return -1;
14395 + }
14396 + }
14397 + }
14398 +
14399 + res = ast_channel_make_compatible(chan, peer);
14400 + if (res < 0) {
14401 + ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, peer->name);
14402 + ast_hangup(peer);
14403 + return -1;
14404 + }
14405 + /* This runs sorta backwards, since we give the incoming channel control, as if it
14406 + were the person called. */
14407 + if (option_verbose > 2)
14408 + ast_verbose(VERBOSE_PREFIX_3 "Channel %s autoanswered %s\n", peer->name, chan->name);
14409 + manager_event(EVENT_FLAG_CALL, "Autoanswer",
14410 + "Channel: %s\r\n"
14411 + "Uniqueid: %s\r\n"
14412 + "Channel2: %s\r\n"
14413 + "Uniqueid2: %s\r\n"
14414 + "Context: %s\r\n"
14415 + "Exten: %s\r\n"
14416 + ,chan->name, chan->uniqueid, peer->name, peer->uniqueid, aacontext, aaexten);
14417 +
14418 +
14419 + memset(&config,0,sizeof(struct ast_bridge_config));
14420 + ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
14421 + ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
14422 + config.timelimit = 0;
14423 + config.play_warning = 0;
14424 + config.warning_freq = 0;
14425 + config.warning_sound=NULL;
14426 + res = ast_bridge_call(chan,peer,&config);
14427 +
14428 + if (option_verbose > 2)
14429 + ast_verbose(VERBOSE_PREFIX_3 "returning from bridge %s\n", peer->name);
14430 + /* relogin */
14431 + snprintf(datastring, sizeof(datastring) - 1, "%s|%s", aacontext, aaexten);
14432 + ast_autoanswer_login(peer, datastring);
14433 + return res;
14434 + } else {
14435 + if (option_verbose > 2)
14436 + ast_verbose(VERBOSE_PREFIX_3 "Nobody logged in for autoanswer %s@%s\n", aaexten, aacontext);
14437 + res = -1;
14438 + }
14439 + LOCAL_USER_REMOVE(u);
14440 + return res;
14441 +}
14442 +
14443
14444 int ast_pickup_call(struct ast_channel *chan)
14445 {
14446 @@ -2076,7 +2844,7 @@
14447 }
14448
14449 {
14450 - struct ast_call_feature *feature=find_feature(var->name);
14451 + struct ast_call_feature *feature = ast_find_feature(var->name);
14452 int mallocd=0;
14453
14454 if (!feature) {
14455 @@ -2138,6 +2906,7 @@
14456 }
14457
14458 int reload(void) {
14459 + autoanswer_reregister_extensions();
14460 return load_config();
14461 }
14462
14463 @@ -2151,14 +2920,22 @@
14464 if ((res = load_config()))
14465 return res;
14466 ast_cli_register(&showparked);
14467 + ast_cli_register(&showautoanswer);
14468 ast_cli_register(&showfeatures);
14469 ast_pthread_create(&parking_thread, NULL, do_parking_thread, NULL);
14470 + ast_pthread_create(&holding_thread, NULL, do_holding_thread, NULL);
14471 res = ast_register_application(parkedcall, park_exec, synopsis, descrip);
14472 if (!res)
14473 res = ast_register_application(parkcall, park_call_exec, synopsis2, descrip2);
14474 if (!res) {
14475 ast_manager_register("ParkedCalls", 0, manager_parking_status, "List parked calls" );
14476 }
14477 + res = ast_register_application(holdedcall, retrieve_call_exec, synopsis, descrip);
14478 + ast_pthread_create(&autoanswer_thread, NULL, do_autoanswer_thread, NULL);
14479 + if (!res)
14480 + res = ast_register_application(autoanswerlogin, autoanswer_login_exec, synopsis3, descrip3);
14481 + if (!res)
14482 + res = ast_register_application(autoanswer, autoanswer_exec, synopsis4, descrip4);
14483 return res;
14484 }
14485
14486 @@ -2169,7 +2946,11 @@
14487
14488 ast_manager_unregister("ParkedCalls");
14489 ast_cli_unregister(&showfeatures);
14490 + ast_cli_unregister(&showautoanswer);
14491 ast_cli_unregister(&showparked);
14492 + ast_unregister_application(autoanswer);
14493 + ast_unregister_application(autoanswerlogin);
14494 + ast_unregister_application(holdedcall);
14495 ast_unregister_application(parkcall);
14496 return ast_unregister_application(parkedcall);
14497 }
14498 diff -urN asterisk-1.2.10.orig/res/res_monitor.c asterisk-1.2.10/res/res_monitor.c
14499 --- asterisk-1.2.10.orig/res/res_monitor.c 2006-03-02 20:05:40.000000000 +0100
14500 +++ asterisk-1.2.10/res/res_monitor.c 2006-07-31 14:13:08.000000000 +0200
14501 @@ -90,7 +90,7 @@
14502
14503 /* Start monitoring a channel */
14504 int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
14505 - const char *fname_base, int need_lock)
14506 + const char *fname_base, const char *target_url, const char *target_script, int need_lock)
14507 {
14508 int res = 0;
14509 char tmp[256];
14510 @@ -122,6 +122,11 @@
14511 }
14512 memset(monitor, 0, sizeof(struct ast_channel_monitor));
14513
14514 + if (target_url)
14515 + ast_copy_string(monitor->target_url, target_url, sizeof(monitor->target_url));
14516 + if (target_script)
14517 + ast_copy_string(monitor->target_script, target_script, sizeof(monitor->target_script));
14518 +
14519 /* Determine file names */
14520 if (!ast_strlen_zero(fname_base)) {
14521 int directory = strchr(fname_base, '/') ? 1 : 0;
14522 @@ -257,6 +262,8 @@
14523 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
14524 char tmp[1024];
14525 char tmp2[1024];
14526 + char tmp3[1024];
14527 + int result;
14528 char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
14529 char *name = chan->monitor->filename_base;
14530 int directory = strchr(name, '/') ? 1 : 0;
14531 @@ -278,9 +285,19 @@
14532 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */
14533 ast_copy_string(tmp, tmp2, sizeof(tmp));
14534 }
14535 - ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
14536 - if (ast_safe_system(tmp) == -1)
14537 + if (!ast_strlen_zero(chan->monitor->target_script) && !ast_strlen_zero(chan->monitor->target_url)) {
14538 + snprintf(tmp3,sizeof(tmp3), "( %s& nice -19 %s \"%s/%s.%s\" \"%s\" ) &",tmp, chan->monitor->target_script , dir, name, format, chan->monitor->target_url);
14539 + ast_copy_string(tmp, tmp3, sizeof(tmp));
14540 + }
14541 + ast_log(LOG_NOTICE,"monitor executing %s\n",tmp);
14542 + result = ast_safe_system(tmp);
14543 + if (result == -1)
14544 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
14545 + manager_event(EVENT_FLAG_CALL, "MonitorStopped",
14546 + "Channel: %s\r\n"
14547 + "Uniqueid: %s\r\n"
14548 + "Result: %d\r\n"
14549 + ,chan->name, chan->uniqueid, result);
14550 }
14551
14552 free(chan->monitor->format);
14553 @@ -392,7 +409,7 @@
14554 return 0;
14555 }
14556
14557 - res = ast_monitor_start(chan, format, fname_base, 1);
14558 + res = ast_monitor_start(chan, format, fname_base, NULL, NULL, 1);
14559 if (res < 0)
14560 res = ast_monitor_change_fname(chan, fname_base, 1);
14561 ast_monitor_setjoinfiles(chan, joinfiles);
14562 @@ -428,19 +445,30 @@
14563 {
14564 struct ast_channel *c = NULL;
14565 char *name = astman_get_header(m, "Channel");
14566 + char *uniqueid = astman_get_header(m, "Uniqueid");
14567 char *fname = astman_get_header(m, "File");
14568 char *format = astman_get_header(m, "Format");
14569 char *mix = astman_get_header(m, "Mix");
14570 + char *target_url = astman_get_header(m, "TargetURL");
14571 + char *target_script = astman_get_header(m, "TargetScript");
14572 char *d;
14573
14574 - if (ast_strlen_zero(name)) {
14575 - astman_send_error(s, m, "No channel specified");
14576 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
14577 + astman_send_error(s, m, "No channel/uniqueid specified");
14578 return 0;
14579 }
14580 - c = ast_get_channel_by_name_locked(name);
14581 - if (!c) {
14582 + if (!ast_strlen_zero(uniqueid)) {
14583 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
14584 + if (!c) {
14585 + astman_send_error(s, m, "No such uniqueid");
14586 + return 0;
14587 + }
14588 + } else {
14589 + c = ast_get_channel_by_name_locked(name);
14590 + if (!c) {
14591 astman_send_error(s, m, "No such channel");
14592 return 0;
14593 + }
14594 }
14595
14596 if (ast_strlen_zero(fname)) {
14597 @@ -457,7 +485,7 @@
14598 if ((d=strchr(fname, '/'))) *d='-';
14599 }
14600
14601 - if (ast_monitor_start(c, format, fname, 1)) {
14602 + if (ast_monitor_start(c, format, fname, target_url, target_script, 1)) {
14603 if (ast_monitor_change_fname(c, fname, 1)) {
14604 astman_send_error(s, m, "Could not start monitoring channel");
14605 ast_mutex_unlock(&c->lock);
14606 @@ -483,16 +511,26 @@
14607 {
14608 struct ast_channel *c = NULL;
14609 char *name = astman_get_header(m, "Channel");
14610 + char *uniqueid = astman_get_header(m, "Uniqueid");
14611 int res;
14612 - if (ast_strlen_zero(name)) {
14613 - astman_send_error(s, m, "No channel specified");
14614 + if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
14615 + astman_send_error(s, m, "No channel/uniqueid specified");
14616 return 0;
14617 }
14618 - c = ast_get_channel_by_name_locked(name);
14619 - if (!c) {
14620 + if (!ast_strlen_zero(uniqueid)) {
14621 + c = ast_get_channel_by_uniqueid_locked(uniqueid);
14622 + if (!c) {
14623 + astman_send_error(s, m, "No such uniqueid");
14624 + return 0;
14625 + }
14626 + } else {
14627 + c = ast_get_channel_by_name_locked(name);
14628 + if (!c) {
14629 astman_send_error(s, m, "No such channel");
14630 return 0;
14631 + }
14632 }
14633 +
14634 res = ast_monitor_stop(c, 1);
14635 ast_mutex_unlock(&c->lock);
14636 if (res) {
14637 diff -urN asterisk-1.2.10.orig/res/res_watchdog.c asterisk-1.2.10/res/res_watchdog.c
14638 --- asterisk-1.2.10.orig/res/res_watchdog.c 1970-01-01 01:00:00.000000000 +0100
14639 +++ asterisk-1.2.10/res/res_watchdog.c 2006-08-10 14:07:14.000000000 +0200
14640 @@ -0,0 +1,149 @@
14641 +/*
14642 + * Asterisk -- A telephony toolkit for Linux.
14643 + *
14644 + * Resource to make watchdogs happy
14645 + *
14646 + * Copyright (C) 2005, Junghanns.NET GmbH
14647 + *
14648 + * Klaus-Peter Junghanns <kpj@junghanns.net>
14649 + *
14650 + * This program is free software, distributed under the terms of
14651 + * the GNU General Public License
14652 + */
14653 +
14654 +#include <stdlib.h>
14655 +#include <errno.h>
14656 +#include <unistd.h>
14657 +#include <string.h>
14658 +#include <stdlib.h>
14659 +#include <stdio.h>
14660 +#include <sys/time.h>
14661 +#include <sys/signal.h>
14662 +#include <netinet/in.h>
14663 +#include <asterisk/lock.h>
14664 +#include <asterisk/file.h>
14665 +#include <asterisk/logger.h>
14666 +#include <asterisk/channel.h>
14667 +#include <asterisk/pbx.h>
14668 +#include <asterisk/options.h>
14669 +#include <asterisk/module.h>
14670 +#include <asterisk/translate.h>
14671 +#include <asterisk/say.h>
14672 +#include <asterisk/features.h>
14673 +#include <asterisk/musiconhold.h>
14674 +#include <asterisk/config.h>
14675 +#include <asterisk/cli.h>
14676 +#include <asterisk/manager.h>
14677 +#include <asterisk/utils.h>
14678 +#include <asterisk/adsi.h>
14679 +
14680 +static struct watchdog_pvt *watchdogs = NULL;
14681 +
14682 +STANDARD_LOCAL_USER;
14683 +
14684 +LOCAL_USER_DECL;
14685 +
14686 +typedef struct watchdog_pvt {
14687 + char device[80];
14688 + int fd;
14689 + int type;
14690 + int interval;
14691 + pthread_t watchdog_thread;
14692 + struct watchdog_pvt *next;
14693 +} watchdog_pvt;
14694 +
14695 +static void *do_watchdog_thread(void *data) {
14696 + struct watchdog_pvt *woof = (struct watchdog_pvt *)data;
14697 + for (;;) {
14698 + if (woof->fd) {
14699 + write(woof->fd, "PING\n", 1);
14700 + }
14701 + usleep(woof->interval * 1000);
14702 + }
14703 + return NULL;
14704 +}
14705 +
14706 +
14707 +int load_module(void)
14708 +{
14709 + int res = 0;
14710 + char *cat, *utype, *udevice, *uinterval;
14711 + struct ast_config *cfg;
14712 + struct watchdog_pvt *woof = NULL;
14713 +
14714 + cfg = ast_config_load("watchdog.conf");
14715 + if (cfg) {
14716 + cat = ast_category_browse(cfg, NULL);
14717 + while(cat) {
14718 + cat = ast_category_browse(cfg, cat);
14719 + utype = ast_variable_retrieve(cfg, cat, "type");
14720 +/* if (utype) {
14721 + ast_log(LOG_NOTICE, "type = %s\n", utype);
14722 + } */
14723 + udevice = ast_variable_retrieve(cfg, cat, "device");
14724 +/* if (udevice) {
14725 + ast_log(LOG_NOTICE, "device = %s\n", udevice);
14726 + } */
14727 + uinterval = ast_variable_retrieve(cfg, cat, "interval");
14728 +/* if (uinterval) {
14729 + ast_log(LOG_NOTICE, "interval = %s\n", uinterval);
14730 + } */
14731 + if (uinterval && udevice && utype) {
14732 + woof = malloc(sizeof(struct watchdog_pvt));
14733 + if (!woof) {
14734 + ast_log(LOG_ERROR, "unable to malloc!\n");
14735 + return -1;
14736 + }
14737 + memset(woof, 0x0, sizeof(struct watchdog_pvt));
14738 + strncpy(woof->device, udevice, sizeof(woof->device) - 1);
14739 +
14740 + woof->interval = atoi(uinterval);;
14741 + woof->next = watchdogs;
14742 + watchdogs = woof;
14743 + woof->fd = open(woof->device, O_WRONLY | O_SYNC);
14744 + if (woof->fd) {
14745 + if (!strncmp(utype, "isdnguard", sizeof(utype))) {
14746 + woof->type = 1;
14747 + write(woof->fd, "START\n", 6);
14748 + }
14749 + ast_pthread_create(&woof->watchdog_thread, NULL, do_watchdog_thread, woof);
14750 + } else {
14751 + ast_log(LOG_WARNING, "error opening watchdog device %s !\n", woof->device);
14752 + }
14753 + }
14754 + }
14755 + ast_config_destroy(cfg);
14756 + }
14757 + return res;
14758 +}
14759 +
14760 +
14761 +int unload_module(void)
14762 +{
14763 + struct watchdog_pvt *dogs, *woof;
14764 + STANDARD_HANGUP_LOCALUSERS;
14765 + dogs = watchdogs;
14766 + while (dogs) {
14767 + pthread_cancel(dogs->watchdog_thread);
14768 + close(dogs->fd);
14769 + woof = dogs->next;
14770 + free(dogs);
14771 + dogs = woof;
14772 + }
14773 + return 0;
14774 +}
14775 +
14776 +char *description(void)
14777 +{
14778 + return "Watchdog Resource";
14779 +}
14780 +
14781 +int usecount(void)
14782 +{
14783 + return 1;
14784 +}
14785 +
14786 +char *key()
14787 +{
14788 + return ASTERISK_GPL_KEY;
14789 +}
14790 diff -urN asterisk-1.2.10.orig/rtp.c asterisk-1.2.10/rtp.c
14791 --- asterisk-1.2.10.orig/rtp.c 2006-07-13 20:44:17.000000000 +0200
14792 +++ asterisk-1.2.10/rtp.c 2006-07-31 14:16:56.000000000 +0200
14793 @@ -445,6 +445,11 @@
14794 struct rtpPayloadType rtpPT;
14795
14796 len = sizeof(sin);
14797 +
14798 + /* XXX SYMPTON CURE, DIRTY FIX, CHECK, BEGIN */
14799 + if (!rtp)
14800 + return &null_frame;
14801 + /* XXX SYMPTON CURE, DIRTY FIX, CHECK, END */
14802
14803 /* Cache where the header will go */
14804 res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,